summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt12
-rw-r--r--api/system-current.txt13
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java2
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java581
-rw-r--r--core/java/android/app/Activity.java4
-rw-r--r--core/java/android/app/ActivityManager.java145
-rw-r--r--core/java/android/app/AppOpsManager.java2
-rw-r--r--core/java/android/app/Notification.java4
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java2
-rw-r--r--core/java/android/app/usage/UsageStatsManagerInternal.java3
-rw-r--r--core/java/android/content/pm/PackageManager.java2
-rw-r--r--core/java/android/net/http/X509TrustManagerExtensions.java13
-rw-r--r--core/java/android/os/UserManager.java10
-rw-r--r--core/java/android/os/UserManagerInternal.java4
-rw-r--r--core/java/android/util/FloatProperty.java8
-rw-r--r--core/java/android/util/IntProperty.java8
-rw-r--r--core/java/android/view/IWindowSession.aidl17
-rw-r--r--core/java/android/view/Surface.java14
-rw-r--r--core/java/android/view/SurfaceControl.java11
-rw-r--r--core/java/android/view/SurfaceView.java14
-rw-r--r--core/java/android/view/View.java34
-rw-r--r--core/java/android/view/ViewRootImpl.java14
-rw-r--r--core/java/android/view/Window.java4
-rw-r--r--core/java/android/webkit/WebResourceRequest.java4
-rw-r--r--core/java/android/webkit/WebViewFactory.java53
-rw-r--r--core/java/com/android/internal/os/InstallerConnection.java18
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java43
-rw-r--r--core/java/com/android/internal/widget/NonClientDecorView.java6
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp3
-rw-r--r--core/jni/android_os_Parcel.cpp36
-rw-r--r--core/jni/android_util_AssetManager.cpp44
-rw-r--r--core/jni/android_util_XmlBlock.cpp32
-rw-r--r--core/jni/android_view_DisplayListCanvas.cpp4
-rw-r--r--core/jni/android_view_Surface.cpp5
-rw-r--r--core/jni/android_view_SurfaceControl.cpp19
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/values/config.xml6
-rw-r--r--core/res/res/values/dimens.xml5
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--core/tests/benchmarks/src/android/content/res/ResourcesBenchmark.java84
-rw-r--r--core/tests/coretests/AndroidManifest.xml4
-rw-r--r--core/tests/coretests/src/android/widget/TextViewActivityTest.java6
-rw-r--r--graphics/java/android/graphics/drawable/Icon.java4
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java4
-rw-r--r--libs/hwui/Android.mk2
-rw-r--r--libs/hwui/BakedOpRenderer.cpp120
-rw-r--r--libs/hwui/BakedOpRenderer.h23
-rw-r--r--libs/hwui/Caches.cpp1
-rw-r--r--libs/hwui/Caches.h1
-rw-r--r--libs/hwui/DisplayList.h6
-rw-r--r--libs/hwui/Extensions.cpp1
-rw-r--r--libs/hwui/Extensions.h6
-rw-r--r--libs/hwui/GlopBuilder.cpp14
-rw-r--r--libs/hwui/GlopBuilder.h1
-rw-r--r--libs/hwui/GradientCache.cpp2
-rw-r--r--libs/hwui/LayerUpdateQueue.cpp42
-rw-r--r--libs/hwui/LayerUpdateQueue.h53
-rw-r--r--libs/hwui/OpReorderer.cpp98
-rw-r--r--libs/hwui/OpReorderer.h36
-rw-r--r--libs/hwui/PathCache.cpp2
-rw-r--r--libs/hwui/Properties.cpp6
-rw-r--r--libs/hwui/Properties.h2
-rw-r--r--libs/hwui/RecordedOp.h34
-rw-r--r--libs/hwui/RecordingCanvas.cpp1
-rw-r--r--libs/hwui/RecordingCanvas.h7
-rw-r--r--libs/hwui/RenderBufferCache.cpp6
-rw-r--r--libs/hwui/RenderNode.cpp64
-rw-r--r--libs/hwui/RenderNode.h29
-rw-r--r--libs/hwui/TreeInfo.h10
-rw-r--r--libs/hwui/microbench/OpReordererBench.cpp4
-rw-r--r--libs/hwui/renderstate/MeshState.cpp18
-rw-r--r--libs/hwui/renderstate/MeshState.h3
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp12
-rw-r--r--libs/hwui/renderthread/CanvasContext.h8
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp5
-rw-r--r--libs/hwui/renderthread/RenderProxy.h3
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp29
-rw-r--r--libs/hwui/renderthread/RenderThread.h12
-rw-r--r--libs/hwui/tests/TreeContentAnimation.cpp25
-rw-r--r--libs/hwui/unit_tests/FatVectorTests.cpp29
-rw-r--r--libs/hwui/unit_tests/LayerUpdateQueueTests.cpp82
-rw-r--r--libs/hwui/unit_tests/OpReordererTests.cpp189
-rw-r--r--libs/hwui/unit_tests/RecordingCanvasTests.cpp23
-rw-r--r--libs/hwui/unit_tests/TestUtils.h23
-rw-r--r--libs/hwui/utils/FatVector.h4
-rw-r--r--media/java/android/media/AudioDeviceInfo.java5
-rw-r--r--media/java/android/media/AudioManager.java6
-rw-r--r--packages/DocumentsUI/res/layout/fragment_directory.xml8
-rw-r--r--packages/DocumentsUI/res/values-fa/strings.xml2
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java61
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryItemAnimator.java195
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java17
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java5
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java10
-rw-r--r--packages/DocumentsUI/tests/Android.mk2
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java208
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java88
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java155
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java100
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java170
-rw-r--r--packages/Keyguard/res/values-hu/strings.xml18
-rw-r--r--packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java188
-rw-r--r--packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java205
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-am/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-az-rAZ/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-bg/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-bn-rBD/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-cs/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-da/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-de/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-el/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-en-rAU/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-en-rGB/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-en-rIN/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-et-rEE/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-eu-rES/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-gl-rES/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-gu-rIN/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-hr/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml36
-rw-r--r--packages/SettingsLib/res/values-hy-rAM/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-in/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-is-rIS/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ja/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ka-rGE/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-kk-rKZ/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-km-rKH/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-kn-rIN/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ko/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ky-rKG/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-lo-rLA/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-lt/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-lv/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-mk-rMK/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ml-rIN/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-mn-rMN/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-mr-rIN/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ms-rMY/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-my-rMM/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-nb/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ne-rNP/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-nl/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-pa-rIN/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-si-rLK/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-sl/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-sq-rAL/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-sr/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-sv/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-sw/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-ta-rIN/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-te-rIN/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-th/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-tl/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-uk/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-ur-rPK/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-uz-rUZ/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-vi/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/strings.xml35
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/strings.xml34
-rw-r--r--packages/SettingsLib/res/values-zu/strings.xml35
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java3
-rw-r--r--packages/Shell/src/com/android/shell/BugreportReceiver.java7
-rw-r--r--packages/SystemUI/res/values-af/strings.xml7
-rw-r--r--packages/SystemUI/res/values-am/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml7
-rw-r--r--packages/SystemUI/res/values-az-rAZ/strings.xml6
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml7
-rw-r--r--packages/SystemUI/res/values-bn-rBD/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml7
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml11
-rw-r--r--packages/SystemUI/res/values-da/strings.xml7
-rw-r--r--packages/SystemUI/res/values-de/strings.xml7
-rw-r--r--packages/SystemUI/res/values-el/strings.xml7
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml7
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml7
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml11
-rw-r--r--packages/SystemUI/res/values-es/strings.xml6
-rw-r--r--packages/SystemUI/res/values-et-rEE/strings.xml6
-rw-r--r--packages/SystemUI/res/values-eu-rES/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-gl-rES/strings.xml7
-rw-r--r--packages/SystemUI/res/values-gu-rIN/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml7
-rw-r--r--packages/SystemUI/res/values-hy-rAM/strings.xml7
-rw-r--r--packages/SystemUI/res/values-in/strings.xml7
-rw-r--r--packages/SystemUI/res/values-is-rIS/strings.xml7
-rw-r--r--packages/SystemUI/res/values-it/strings.xml7
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml11
-rw-r--r--packages/SystemUI/res/values-ka-rGE/strings.xml7
-rw-r--r--packages/SystemUI/res/values-kk-rKZ/strings.xml7
-rw-r--r--packages/SystemUI/res/values-km-rKH/strings.xml7
-rw-r--r--packages/SystemUI/res/values-kn-rIN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ky-rKG/strings.xml7
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings.xml7
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml6
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml7
-rw-r--r--packages/SystemUI/res/values-mk-rMK/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ml-rIN/strings.xml9
-rw-r--r--packages/SystemUI/res/values-mn-rMN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-mr-rIN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings.xml6
-rw-r--r--packages/SystemUI/res/values-my-rMM/strings.xml6
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ne-rNP/strings.xml7
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pa-rIN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml11
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml11
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml7
-rw-r--r--packages/SystemUI/res/values-si-rLK/strings.xml4
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sq-rAL/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ta-rIN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-te-rIN/strings.xml6
-rw-r--r--packages/SystemUI/res/values-th/strings.xml7
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ur-rPK/strings.xml7
-rw-r--r--packages/SystemUI/res/values-uz-rUZ/strings.xml7
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml7
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml10
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml11
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Recents.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/ParametricCurve.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java301
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java114
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java2
-rw-r--r--services/core/java/com/android/server/MountService.java58
-rw-r--r--services/core/java/com/android/server/NativeDaemonConnector.java16
-rw-r--r--services/core/java/com/android/server/NetworkTimeUpdateService.java13
-rwxr-xr-xservices/core/java/com/android/server/am/ActiveServices.java15
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java376
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java88
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java77
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java2
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java5
-rw-r--r--services/core/java/com/android/server/am/RecentTasks.java2
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java15
-rw-r--r--services/core/java/com/android/server/am/UserController.java292
-rw-r--r--services/core/java/com/android/server/am/UserSwitchingDialog.java2
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java6
-rw-r--r--services/core/java/com/android/server/content/AppIdleMonitor.java4
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java13
-rw-r--r--services/core/java/com/android/server/job/controllers/AppIdleController.java4
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/Installer.java8
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java15
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java529
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java636
-rw-r--r--services/core/java/com/android/server/pm/UserRestrictionsUtils.java127
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java4
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateService.java21
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java21
-rw-r--r--services/core/java/com/android/server/wm/DimLayerController.java (renamed from services/core/java/com/android/server/wm/DimBehindController.java)90
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java27
-rw-r--r--services/core/java/com/android/server/wm/DockedStackDividerController.java2
-rw-r--r--services/core/java/com/android/server/wm/Session.java6
-rw-r--r--services/core/java/com/android/server/wm/Task.java17
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java37
-rw-r--r--services/core/java/com/android/server/wm/WallpaperController.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java108
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java55
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java28
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfacePlacer.java4
-rw-r--r--services/core/jni/com_android_server_UsbMidiDevice.cpp22
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java166
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java4
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java42
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java17
-rw-r--r--telephony/java/com/android/ims/ImsCallProfile.java14
-rw-r--r--tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java15
-rw-r--r--tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionTest.java19
-rw-r--r--tools/aapt2/Android.mk13
-rw-r--r--tools/aapt2/ConfigDescription.cpp31
-rw-r--r--tools/aapt2/ConfigDescription_test.cpp17
-rw-r--r--tools/aapt2/Flags.cpp10
-rw-r--r--tools/aapt2/ManifestValidator.cpp217
-rw-r--r--tools/aapt2/ManifestValidator.h55
-rw-r--r--tools/aapt2/Resource.cpp2
-rw-r--r--tools/aapt2/Resource.h1
-rw-r--r--tools/aapt2/ResourceParser.cpp148
-rw-r--r--tools/aapt2/ResourceParser_test.cpp28
-rw-r--r--tools/aapt2/ResourceUtils.cpp48
-rw-r--r--tools/aapt2/ResourceUtils.h10
-rw-r--r--tools/aapt2/Resource_test.cpp4
-rw-r--r--tools/aapt2/SdkConstants.h1
-rw-r--r--tools/aapt2/XmlDom.cpp20
-rw-r--r--tools/aapt2/XmlDom.h4
-rw-r--r--tools/aapt2/flatten/ResourceTypeExtensions.h52
-rw-r--r--tools/aapt2/flatten/TableFlattener.cpp23
-rw-r--r--tools/aapt2/java/AnnotationProcessor.cpp89
-rw-r--r--tools/aapt2/java/AnnotationProcessor.h94
-rw-r--r--tools/aapt2/java/JavaClassGenerator.cpp (renamed from tools/aapt2/JavaClassGenerator.cpp)124
-rw-r--r--tools/aapt2/java/JavaClassGenerator.h (renamed from tools/aapt2/JavaClassGenerator.h)0
-rw-r--r--tools/aapt2/java/JavaClassGenerator_test.cpp (renamed from tools/aapt2/JavaClassGenerator_test.cpp)33
-rw-r--r--tools/aapt2/java/ManifestClassGenerator.cpp131
-rw-r--r--tools/aapt2/java/ManifestClassGenerator.h35
-rw-r--r--tools/aapt2/java/ManifestClassGenerator_test.cpp120
-rw-r--r--tools/aapt2/java/ProguardRules.cpp (renamed from tools/aapt2/ProguardRules.cpp)18
-rw-r--r--tools/aapt2/java/ProguardRules.h (renamed from tools/aapt2/ProguardRules.h)0
-rw-r--r--tools/aapt2/link/Link.cpp80
-rw-r--r--tools/aapt2/link/ManifestFixer.cpp100
-rw-r--r--tools/aapt2/link/ManifestFixer.h44
-rw-r--r--tools/aapt2/link/ManifestFixer_test.cpp165
-rw-r--r--tools/aapt2/test/Builders.h2
-rw-r--r--tools/aapt2/unflatten/BinaryResourceParser.cpp22
-rw-r--r--tools/aapt2/util/StringPiece.h1
-rw-r--r--tools/aapt2/util/Util.cpp118
-rw-r--r--tools/aapt2/util/Util.h10
-rw-r--r--tools/aapt2/util/Util_test.cpp8
-rw-r--r--tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java5
-rw-r--r--tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java5
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java4
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java6
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java7
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java4
370 files changed, 9306 insertions, 3279 deletions
diff --git a/api/current.txt b/api/current.txt
index 3b4e3a9eeba2..62f0113a7d1c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -34268,6 +34268,18 @@ package android.util {
public deprecated class FloatMath {
}
+ public abstract class FloatProperty extends android.util.Property {
+ ctor public FloatProperty(java.lang.String);
+ method public final void set(T, java.lang.Float);
+ method public abstract void setValue(T, float);
+ }
+
+ public abstract class IntProperty extends android.util.Property {
+ ctor public IntProperty(java.lang.String);
+ method public final void set(T, java.lang.Integer);
+ method public abstract void setValue(T, int);
+ }
+
public final class JsonReader implements java.io.Closeable {
ctor public JsonReader(java.io.Reader);
method public void beginArray() throws java.io.IOException;
diff --git a/api/system-current.txt b/api/system-current.txt
index 9db70e3cfa07..4118f338ed64 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -20523,6 +20523,7 @@ package android.net.http {
public class X509TrustManagerExtensions {
ctor public X509TrustManagerExtensions(javax.net.ssl.X509TrustManager) throws java.lang.IllegalArgumentException;
method public java.util.List<java.security.cert.X509Certificate> checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, java.lang.String) throws java.security.cert.CertificateException;
+ method public boolean isSameTrustConfiguration(java.lang.String, java.lang.String);
method public boolean isUserAddedCertificate(java.security.cert.X509Certificate);
}
@@ -36565,6 +36566,18 @@ package android.util {
public deprecated class FloatMath {
}
+ public abstract class FloatProperty extends android.util.Property {
+ ctor public FloatProperty(java.lang.String);
+ method public final void set(T, java.lang.Float);
+ method public abstract void setValue(T, float);
+ }
+
+ public abstract class IntProperty extends android.util.Property {
+ ctor public IntProperty(java.lang.String);
+ method public final void set(T, java.lang.Integer);
+ method public abstract void setValue(T, int);
+ }
+
public final class JsonReader implements java.io.Closeable {
ctor public JsonReader(java.io.Reader);
method public void beginArray() throws java.io.IOException;
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 12780a8742b9..7f33cb5df1a3 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -18,7 +18,7 @@
package com.android.commands.am;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
import static android.app.ActivityManager.RESIZE_MODE_USER;
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 2960cdc9084e..ab781bbac6ba 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -25,7 +25,6 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO
import android.accounts.IAccountManager;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
import android.app.PackageInstallObserver;
import android.content.ComponentName;
import android.content.Context;
@@ -34,30 +33,25 @@ import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
-import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageInstaller;
import android.content.pm.IPackageManager;
-import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageInstaller.SessionParams;
-import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
import android.content.pm.VerificationParams;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IUserManager;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -80,11 +74,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.WeakHashMap;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
@@ -96,9 +85,6 @@ public final class Pm {
IUserManager mUm;
IAccountManager mAm;
- private WeakHashMap<String, Resources> mResourceCache
- = new WeakHashMap<String, Resources>();
-
private String[] mArgs;
private int mNextArg;
private String mCurArgData;
@@ -275,10 +261,10 @@ public final class Pm {
if (args.length == 1) {
if (args[0].equalsIgnoreCase("-l")) {
validCommand = true;
- return runListPackages(false);
- } else if (args[0].equalsIgnoreCase("-lf")){
+ return runShellCommand("package", new String[] { "list", "package" });
+ } else if (args[0].equalsIgnoreCase("-lf")) {
validCommand = true;
- return runListPackages(true);
+ return runShellCommand("package", new String[] { "list", "package", "-f" });
}
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("-p")) {
@@ -297,473 +283,38 @@ public final class Pm {
}
}
- /**
- * Execute the list sub-command.
- *
- * pm list [package | packages]
- * pm list permission-groups
- * pm list permissions
- * pm list features
- * pm list libraries
- * pm list instrumentation
- */
- private int runList() {
- String type = nextArg();
- if (type == null) {
- System.err.println("Error: didn't specify type of data to list");
- return 1;
- }
- if ("package".equals(type) || "packages".equals(type)) {
- return runListPackages(false);
- } else if ("permission-groups".equals(type)) {
- return runListPermissionGroups();
- } else if ("permissions".equals(type)) {
- return runListPermissions();
- } else if ("features".equals(type)) {
- return runListFeatures();
- } else if ("libraries".equals(type)) {
- return runListLibraries();
- } else if ("instrumentation".equals(type)) {
- return runListInstrumentation();
- } else if ("users".equals(type)) {
- return runListUsers();
- } else {
- System.err.println("Error: unknown list type '" + type + "'");
- return 1;
- }
- }
-
- /**
- * Lists all the installed packages.
- */
- private int runListPackages(boolean showApplicationPackage) {
- int getFlags = 0;
- boolean listDisabled = false, listEnabled = false;
- boolean listSystem = false, listThirdParty = false;
- boolean listInstaller = false;
- int userId = UserHandle.USER_SYSTEM;
+ private int runShellCommand(String serviceName, String[] args) {
+ final HandlerThread handlerThread = new HandlerThread("results");
+ handlerThread.start();
try {
- String opt;
- while ((opt=nextOption()) != null) {
- if (opt.equals("-l")) {
- // old compat
- } else if (opt.equals("-lf")) {
- showApplicationPackage = true;
- } else if (opt.equals("-f")) {
- showApplicationPackage = true;
- } else if (opt.equals("-d")) {
- listDisabled = true;
- } else if (opt.equals("-e")) {
- listEnabled = true;
- } else if (opt.equals("-s")) {
- listSystem = true;
- } else if (opt.equals("-3")) {
- listThirdParty = true;
- } else if (opt.equals("-i")) {
- listInstaller = true;
- } else if (opt.equals("--user")) {
- userId = Integer.parseInt(nextArg());
- } else if (opt.equals("-u")) {
- getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
- } else {
- System.err.println("Error: Unknown option: " + opt);
- return 1;
- }
- }
- } catch (RuntimeException ex) {
- System.err.println("Error: " + ex.toString());
- return 1;
- }
-
- String filter = nextArg();
-
- try {
- final List<PackageInfo> packages = getInstalledPackages(mPm, getFlags, userId);
-
- int count = packages.size();
- for (int p = 0 ; p < count ; p++) {
- PackageInfo info = packages.get(p);
- if (filter != null && !info.packageName.contains(filter)) {
- continue;
- }
- final boolean isSystem =
- (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
- if ((!listDisabled || !info.applicationInfo.enabled) &&
- (!listEnabled || info.applicationInfo.enabled) &&
- (!listSystem || isSystem) &&
- (!listThirdParty || !isSystem)) {
- System.out.print("package:");
- if (showApplicationPackage) {
- System.out.print(info.applicationInfo.sourceDir);
- System.out.print("=");
- }
- System.out.print(info.packageName);
- if (listInstaller) {
- System.out.print(" installer=");
- System.out.print(mPm.getInstallerPackageName(info.packageName));
- }
- System.out.println();
- }
- }
+ ServiceManager.getService(serviceName).shellCommand(
+ FileDescriptor.in, FileDescriptor.out, FileDescriptor.err,
+ args, new ResultReceiver(new Handler(handlerThread.getLooper())));
return 0;
} catch (RemoteException e) {
- System.err.println(e.toString());
- System.err.println(PM_NOT_RUNNING_ERR);
- return 1;
+ e.printStackTrace();
+ } finally {
+ handlerThread.quitSafely();
}
- }
-
- @SuppressWarnings("unchecked")
- private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId)
- throws RemoteException {
- ParceledListSlice<PackageInfo> slice = pm.getInstalledPackages(flags, userId);
- return slice.getList();
+ return -1;
}
/**
- * Lists all of the features supported by the current device.
+ * Execute the list sub-command.
*
+ * pm list [package | packages]
+ * pm list permission-groups
+ * pm list permissions
* pm list features
- */
- private int runListFeatures() {
- try {
- List<FeatureInfo> list = new ArrayList<FeatureInfo>();
- FeatureInfo[] rawList = mPm.getSystemAvailableFeatures();
- for (int i=0; i<rawList.length; i++) {
- list.add(rawList[i]);
- }
-
-
- // Sort by name
- Collections.sort(list, new Comparator<FeatureInfo>() {
- public int compare(FeatureInfo o1, FeatureInfo o2) {
- if (o1.name == o2.name) return 0;
- if (o1.name == null) return -1;
- if (o2.name == null) return 1;
- return o1.name.compareTo(o2.name);
- }
- });
-
- int count = (list != null) ? list.size() : 0;
- for (int p = 0; p < count; p++) {
- FeatureInfo fi = list.get(p);
- System.out.print("feature:");
- if (fi.name != null) System.out.println(fi.name);
- else System.out.println("reqGlEsVersion=0x"
- + Integer.toHexString(fi.reqGlEsVersion));
- }
- return 0;
- } catch (RemoteException e) {
- System.err.println(e.toString());
- System.err.println(PM_NOT_RUNNING_ERR);
- return 1;
- }
- }
-
- /**
- * Lists all of the libraries supported by the current device.
- *
* pm list libraries
+ * pm list instrumentation
*/
- private int runListLibraries() {
- try {
- List<String> list = new ArrayList<String>();
- String[] rawList = mPm.getSystemSharedLibraryNames();
- for (int i=0; i<rawList.length; i++) {
- list.add(rawList[i]);
- }
-
-
- // Sort by name
- Collections.sort(list, new Comparator<String>() {
- public int compare(String o1, String o2) {
- if (o1 == o2) return 0;
- if (o1 == null) return -1;
- if (o2 == null) return 1;
- return o1.compareTo(o2);
- }
- });
-
- int count = (list != null) ? list.size() : 0;
- for (int p = 0; p < count; p++) {
- String lib = list.get(p);
- System.out.print("library:");
- System.out.println(lib);
- }
- return 0;
- } catch (RemoteException e) {
- System.err.println(e.toString());
- System.err.println(PM_NOT_RUNNING_ERR);
- return 1;
- }
- }
-
- /**
- * Lists all of the installed instrumentation, or all for a given package
- *
- * pm list instrumentation [package] [-f]
- */
- private int runListInstrumentation() {
- int flags = 0; // flags != 0 is only used to request meta-data
- boolean showPackage = false;
- String targetPackage = null;
-
- try {
- String opt;
- while ((opt=nextArg()) != null) {
- if (opt.equals("-f")) {
- showPackage = true;
- } else if (opt.charAt(0) != '-') {
- targetPackage = opt;
- } else {
- System.err.println("Error: Unknown option: " + opt);
- return 1;
- }
- }
- } catch (RuntimeException ex) {
- System.err.println("Error: " + ex.toString());
- return 1;
- }
-
- try {
- List<InstrumentationInfo> list = mPm.queryInstrumentation(targetPackage, flags);
-
- // Sort by target package
- Collections.sort(list, new Comparator<InstrumentationInfo>() {
- public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
- return o1.targetPackage.compareTo(o2.targetPackage);
- }
- });
-
- int count = (list != null) ? list.size() : 0;
- for (int p = 0; p < count; p++) {
- InstrumentationInfo ii = list.get(p);
- System.out.print("instrumentation:");
- if (showPackage) {
- System.out.print(ii.sourceDir);
- System.out.print("=");
- }
- ComponentName cn = new ComponentName(ii.packageName, ii.name);
- System.out.print(cn.flattenToShortString());
- System.out.print(" (target=");
- System.out.print(ii.targetPackage);
- System.out.println(")");
- }
- return 0;
- } catch (RemoteException e) {
- System.err.println(e.toString());
- System.err.println(PM_NOT_RUNNING_ERR);
- return 1;
- }
- }
-
- /**
- * Lists all the known permission groups.
- */
- private int runListPermissionGroups() {
- try {
- List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0);
-
- int count = pgs.size();
- for (int p = 0 ; p < count ; p++) {
- PermissionGroupInfo pgi = pgs.get(p);
- System.out.print("permission group:");
- System.out.println(pgi.name);
- }
- return 0;
- } catch (RemoteException e) {
- System.err.println(e.toString());
- System.err.println(PM_NOT_RUNNING_ERR);
- return 1;
- }
- }
-
- private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized) {
- if (nonLocalized != null) {
- return nonLocalized.toString();
- }
- if (res != 0) {
- Resources r = getResources(pii);
- if (r != null) {
- try {
- return r.getString(res);
- } catch (Resources.NotFoundException e) {
- }
- }
- }
- return null;
- }
-
- /**
- * Lists all the permissions in a group.
- */
- private int runListPermissions() {
- try {
- boolean labels = false;
- boolean groups = false;
- boolean userOnly = false;
- boolean summary = false;
- boolean dangerousOnly = false;
- String opt;
- while ((opt=nextOption()) != null) {
- if (opt.equals("-f")) {
- labels = true;
- } else if (opt.equals("-g")) {
- groups = true;
- } else if (opt.equals("-s")) {
- groups = true;
- labels = true;
- summary = true;
- } else if (opt.equals("-u")) {
- userOnly = true;
- } else if (opt.equals("-d")) {
- dangerousOnly = true;
- } else {
- System.err.println("Error: Unknown option: " + opt);
- return 1;
- }
- }
-
- String grp = nextArg();
- ArrayList<String> groupList = new ArrayList<String>();
- if (groups) {
- List<PermissionGroupInfo> infos =
- mPm.getAllPermissionGroups(0);
- for (int i=0; i<infos.size(); i++) {
- groupList.add(infos.get(i).name);
- }
- groupList.add(null);
- } else {
- groupList.add(grp);
- }
-
- if (dangerousOnly) {
- System.out.println("Dangerous Permissions:");
- System.out.println("");
- doListPermissions(groupList, groups, labels, summary,
- PermissionInfo.PROTECTION_DANGEROUS,
- PermissionInfo.PROTECTION_DANGEROUS);
- if (userOnly) {
- System.out.println("Normal Permissions:");
- System.out.println("");
- doListPermissions(groupList, groups, labels, summary,
- PermissionInfo.PROTECTION_NORMAL,
- PermissionInfo.PROTECTION_NORMAL);
- }
- } else if (userOnly) {
- System.out.println("Dangerous and Normal Permissions:");
- System.out.println("");
- doListPermissions(groupList, groups, labels, summary,
- PermissionInfo.PROTECTION_NORMAL,
- PermissionInfo.PROTECTION_DANGEROUS);
- } else {
- System.out.println("All Permissions:");
- System.out.println("");
- doListPermissions(groupList, groups, labels, summary,
- -10000, 10000);
- }
- return 0;
- } catch (RemoteException e) {
- System.err.println(e.toString());
- System.err.println(PM_NOT_RUNNING_ERR);
- return 1;
- }
- }
-
- private void doListPermissions(ArrayList<String> groupList,
- boolean groups, boolean labels, boolean summary,
- int startProtectionLevel, int endProtectionLevel)
- throws RemoteException {
- for (int i=0; i<groupList.size(); i++) {
- String groupName = groupList.get(i);
- String prefix = "";
- if (groups) {
- if (i > 0) System.out.println("");
- if (groupName != null) {
- PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(
- groupName, 0);
- if (summary) {
- Resources res = getResources(pgi);
- if (res != null) {
- System.out.print(loadText(pgi, pgi.labelRes,
- pgi.nonLocalizedLabel) + ": ");
- } else {
- System.out.print(pgi.name + ": ");
-
- }
- } else {
- System.out.println((labels ? "+ " : "")
- + "group:" + pgi.name);
- if (labels) {
- System.out.println(" package:" + pgi.packageName);
- Resources res = getResources(pgi);
- if (res != null) {
- System.out.println(" label:"
- + loadText(pgi, pgi.labelRes,
- pgi.nonLocalizedLabel));
- System.out.println(" description:"
- + loadText(pgi, pgi.descriptionRes,
- pgi.nonLocalizedDescription));
- }
- }
- }
- } else {
- System.out.println(((labels && !summary)
- ? "+ " : "") + "ungrouped:");
- }
- prefix = " ";
- }
- List<PermissionInfo> ps = mPm.queryPermissionsByGroup(
- groupList.get(i), 0);
- int count = ps.size();
- boolean first = true;
- for (int p = 0 ; p < count ; p++) {
- PermissionInfo pi = ps.get(p);
- if (groups && groupName == null && pi.group != null) {
- continue;
- }
- final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
- if (base < startProtectionLevel
- || base > endProtectionLevel) {
- continue;
- }
- if (summary) {
- if (first) {
- first = false;
- } else {
- System.out.print(", ");
- }
- Resources res = getResources(pi);
- if (res != null) {
- System.out.print(loadText(pi, pi.labelRes,
- pi.nonLocalizedLabel));
- } else {
- System.out.print(pi.name);
- }
- } else {
- System.out.println(prefix + (labels ? "+ " : "")
- + "permission:" + pi.name);
- if (labels) {
- System.out.println(prefix + " package:" + pi.packageName);
- Resources res = getResources(pi);
- if (res != null) {
- System.out.println(prefix + " label:"
- + loadText(pi, pi.labelRes,
- pi.nonLocalizedLabel));
- System.out.println(prefix + " description:"
- + loadText(pi, pi.descriptionRes,
- pi.nonLocalizedDescription));
- }
- System.out.println(prefix + " protectionLevel:"
- + PermissionInfo.protectionToString(pi.protectionLevel));
- }
- }
- }
-
- if (summary) {
- System.out.println("");
- }
+ private int runList() {
+ final String type = nextArg();
+ if ("users".equals(type)) {
+ return runShellCommand("user", new String[] { "list" });
}
+ return runShellCommand("package", mArgs);
}
private int runPath() {
@@ -1467,29 +1018,6 @@ public final class Pm {
}
}
- public int runListUsers() {
- try {
- IActivityManager am = ActivityManagerNative.getDefault();
-
- List<UserInfo> users = mUm.getUsers(false);
- if (users == null) {
- System.err.println("Error: couldn't get users");
- return 1;
- } else {
- System.out.println("Users:");
- for (int i = 0; i < users.size(); i++) {
- String running = am.isUserRunning(users.get(i).id, false) ? " running" : "";
- System.out.println("\t" + users.get(i).toString() + running);
- }
- return 0;
- }
- } catch (RemoteException e) {
- System.err.println(e.toString());
- System.err.println(PM_NOT_RUNNING_ERR);
- return 1;
- }
- }
-
public int runGetMaxUsers() {
System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers());
return 0;
@@ -1997,24 +1525,6 @@ public final class Pm {
return 1;
}
- private Resources getResources(PackageItemInfo pii) {
- Resources res = mResourceCache.get(pii.packageName);
- if (res != null) return res;
-
- try {
- ApplicationInfo ai = mPm.getApplicationInfo(pii.packageName, 0, 0);
- AssetManager am = new AssetManager();
- am.addAssetPath(ai.publicSourceDir);
- res = new Resources(am, null, null);
- mResourceCache.put(pii.packageName, res);
- return res;
- } catch (RemoteException e) {
- System.err.println(e.toString());
- System.err.println(PM_NOT_RUNNING_ERR);
- return null;
- }
- }
-
private static String checkAbiArgument(String abi) {
if (TextUtils.isEmpty(abi)) {
throw new IllegalArgumentException("Missing ABI argument");
@@ -2110,14 +1620,7 @@ public final class Pm {
}
private static int showUsage() {
- System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
- System.err.println(" pm list permission-groups");
- System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
- System.err.println(" pm list instrumentation [-f] [TARGET-PACKAGE]");
- System.err.println(" pm list features");
- System.err.println(" pm list libraries");
- System.err.println(" pm list users");
- System.err.println(" pm path [--user USER_ID] PACKAGE");
+ System.err.println("usage: pm path [--user USER_ID] PACKAGE");
System.err.println(" pm dump PACKAGE");
System.err.println(" pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]");
System.err.println(" pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]");
@@ -2151,34 +1654,8 @@ public final class Pm {
System.err.println(" pm remove-user USER_ID");
System.err.println(" pm get-max-users");
System.err.println("");
- System.err.println("pm list packages: prints all packages, optionally only");
- System.err.println(" those whose package name contains the text in FILTER. Options:");
- System.err.println(" -f: see their associated file.");
- System.err.println(" -d: filter to only show disbled packages.");
- System.err.println(" -e: filter to only show enabled packages.");
- System.err.println(" -s: filter to only show system packages.");
- System.err.println(" -3: filter to only show third party packages.");
- System.err.println(" -i: see the installer for the packages.");
- System.err.println(" -u: also include uninstalled packages.");
- System.err.println("");
- System.err.println("pm list permission-groups: prints all known permission groups.");
- System.err.println("");
- System.err.println("pm list permissions: prints all known permissions, optionally only");
- System.err.println(" those in GROUP. Options:");
- System.err.println(" -g: organize by group.");
- System.err.println(" -f: print all information.");
- System.err.println(" -s: short summary.");
- System.err.println(" -d: only list dangerous permissions.");
- System.err.println(" -u: list only the permissions users will see.");
- System.err.println("");
- System.err.println("pm list instrumentation: use to list all test packages; optionally");
- System.err.println(" supply <TARGET-PACKAGE> to list the test packages for a particular");
- System.err.println(" application. Options:");
- System.err.println(" -f: list the .apk file for the test package.");
- System.err.println("");
- System.err.println("pm list features: prints all features of the system.");
- System.err.println("");
- System.err.println("pm list users: prints all users on the system.");
+ System.err.println("NOTE: 'pm list' commands have moved! Run 'adb shell cmd package'");
+ System.err.println(" to display the new commands.");
System.err.println("");
System.err.println("pm path: print the path to the .apk of the given PACKAGE.");
System.err.println("");
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 2f0849f39aa2..472d97fdb9ed 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2728,8 +2728,8 @@ public class Activity extends ContextThemeWrapper
/**
* Called to move the window and its activity/task to a different stack container.
* For example, a window can move between
- * {@link android.app.ActivityManager#FULLSCREEN_WORKSPACE_STACK_ID} stack and
- * {@link android.app.ActivityManager#FREEFORM_WORKSPACE_STACK_ID} stack.
+ * {@link android.app.ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} stack and
+ * {@link android.app.ActivityManager.StackId#FREEFORM_WORKSPACE_STACK_ID} stack.
*
* @param stackId stack Id to change to.
* @hide
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 203f34236723..b809baa28119 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -73,7 +73,6 @@ import java.util.List;
*/
public class ActivityManager {
private static String TAG = "ActivityManager";
- private static boolean localLOGV = false;
private static int gMaxRecentTasks = -1;
@@ -397,60 +396,112 @@ public class ActivityManager {
*/
public static final int COMPAT_MODE_TOGGLE = 2;
- /**
- * Invalid stack ID.
- * @hide
- */
- public static final int INVALID_STACK_ID = -1;
+ /** @hide */
+ public static class StackId {
+ /** Invalid stack ID. */
+ public static final int INVALID_STACK_ID = -1;
- /**
- * First static stack ID.
- * @hide
- */
- public static final int FIRST_STATIC_STACK_ID = 0;
+ /** First static stack ID. */
+ public static final int FIRST_STATIC_STACK_ID = 0;
- /**
- * Home activity stack ID.
- * @hide
- */
- public static final int HOME_STACK_ID = FIRST_STATIC_STACK_ID;
+ /** Home activity stack ID. */
+ public static final int HOME_STACK_ID = FIRST_STATIC_STACK_ID;
- /**
- * ID of stack where fullscreen activities are normally launched into.
- * @hide
- */
- public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;
+ /** ID of stack where fullscreen activities are normally launched into. */
+ public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;
- /**
- * ID of stack where freeform/resized activities are normally launched into.
- * @hide
- */
- public static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;
+ /** ID of stack where freeform/resized activities are normally launched into. */
+ public static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;
- /**
- * ID of stack that occupies a dedicated region of the screen.
- * @hide
- */
- public static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;
+ /** ID of stack that occupies a dedicated region of the screen. */
+ public static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;
- /**
- * ID of stack that always on top (always visible) when it exist.
- * Mainly used for this in Picture-in-Picture mode.
- * @hide
- */
- public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;
+ /** ID of stack that always on top (always visible) when it exist. */
+ public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;
- /**
- * Last static stack stack ID.
- * @hide
- */
- public static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
+ /** Last static stack stack ID. */
+ public static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
- /**
- * Start of ID range used by stacks that are created dynamically.
- * @hide
- */
- public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1;
+ /** Start of ID range used by stacks that are created dynamically. */
+ public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1;
+
+ public static boolean isStaticStack(int stackId) {
+ return stackId >= FIRST_STATIC_STACK_ID && stackId <= LAST_STATIC_STACK_ID;
+ }
+
+ /**
+ * Returns true if the activities contained in the input stack display a shadow around
+ * their border.
+ */
+ public static boolean hasWindowShadow(int stackId) {
+ return stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == PINNED_STACK_ID;
+ }
+
+ /**
+ * Returns true if the activities contained in the input stack display a decor view.
+ */
+ public static boolean hasWindowDecor(int stackId) {
+ return stackId == FREEFORM_WORKSPACE_STACK_ID;
+ }
+
+ /**
+ * Returns true if the tasks contained in the stack can be resized independently of the
+ * stack.
+ */
+ public static boolean isTaskResizeAllowed(int stackId) {
+ return stackId == FREEFORM_WORKSPACE_STACK_ID;
+ }
+
+ /**
+ * Returns true if the task bounds should persist across power cycles.
+ */
+ public static boolean persistTaskBounds(int stackId) {
+ return isStaticStack(stackId) &&
+ stackId != DOCKED_STACK_ID && stackId != PINNED_STACK_ID;
+ }
+
+ /**
+ * Returns true if dynamic stacks are allowed to be visible behind the input stack.
+ */
+ public static boolean isDynamicStacksVisibleBehindAllowed(int stackId) {
+ return stackId == PINNED_STACK_ID;
+ }
+
+ /**
+ * Returns true if we try to maintain focus in the current stack when the top activity
+ * finishes.
+ */
+ public static boolean keepFocusInStackIfPossible(int stackId) {
+ return stackId == FREEFORM_WORKSPACE_STACK_ID
+ || stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID;
+ }
+
+ /**
+ * Returns true if Stack size is affected by the docked stack changing size.
+ */
+ public static boolean isResizeableByDockedStack(int stackId) {
+ return isStaticStack(stackId) &&
+ stackId != DOCKED_STACK_ID && stackId != PINNED_STACK_ID;
+ }
+
+ /**
+ * Returns true if the size of tasks in the input stack are affected by the docked stack
+ * changing size.
+ */
+ public static boolean isTaskResizeableByDockedStack(int stackId) {
+ return isStaticStack(stackId) && stackId != FREEFORM_WORKSPACE_STACK_ID
+ && stackId != DOCKED_STACK_ID && stackId != PINNED_STACK_ID;
+ }
+
+ /**
+ * Returns true if the windows of tasks being moved to this stack should be preserved so
+ * there isn't a display gap.
+ */
+ public static boolean preserveWindowOnTaskMove(int stackId) {
+ return stackId == FULLSCREEN_WORKSPACE_STACK_ID
+ || stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID;
+ }
+ }
/**
* Input parameter to {@link android.app.IActivityManager#moveTaskToDockedStack} which
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 09c0a6e3ae46..77a9795bb59f 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -653,7 +653,7 @@ public class AppOpsManager {
null, //WRITE_SETTINGS
UserManager.DISALLOW_CREATE_WINDOWS, //SYSTEM_ALERT_WINDOW
null, //ACCESS_NOTIFICATIONS
- null, //CAMERA
+ UserManager.DISALLOW_CAMERA, //CAMERA
UserManager.DISALLOW_RECORD_AUDIO, //RECORD_AUDIO
null, //PLAY_AUDIO
null, //READ_CLIPBOARD
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 49edff411342..ffeb6ed32950 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3829,7 +3829,9 @@ public class Notification implements Parcelable
@Override
public void purgeResources() {
super.purgeResources();
- if (mPicture != null && mPicture.isMutable()) {
+ if (mPicture != null &&
+ mPicture.isMutable() &&
+ mPicture.getAllocationByteCount() >= (128 * (1 << 10))) {
mPicture = mPicture.createAshmemBitmap();
}
if (mBigLargeIcon != null) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9e9d9496b461..0fdf3d3693c3 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2271,6 +2271,8 @@ public class DevicePolicyManager {
* on the device, for this user. After setting this, no applications running as this user
* will be able to access any cameras on the device.
*
+ * <p>If the caller is device owner, then the restriction will be applied to all users.
+ *
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call
* this method; if it has not, a security exception will be thrown.
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 948ea1effae7..498ff811cc74 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -71,10 +71,11 @@ public abstract class UsageStatsManagerInternal {
* Could be hours, could be days, who knows?
*
* @param packageName
+ * @param uidForAppId The uid of the app, which will be used for its app id
* @param userId
* @return
*/
- public abstract boolean isAppIdle(String packageName, int userId);
+ public abstract boolean isAppIdle(String packageName, int uidForAppId, int userId);
/**
* Returns all of the uids for a given user where all packages associating with that uid
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 27ecf9fc1309..c57fc89d19f8 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1125,7 +1125,7 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
- * The device has professional audio level of functionality, performance, and acoustics.
+ * The device has professional audio level of functionality and performance.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_AUDIO_PRO = "android.hardware.audio.pro";
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
index eb4cedab83b7..25ef8b500cda 100644
--- a/core/java/android/net/http/X509TrustManagerExtensions.java
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -16,6 +16,8 @@
package android.net.http;
+import android.annotation.SystemApi;
+
import com.android.org.conscrypt.TrustManagerImpl;
import java.security.cert.CertificateException;
@@ -80,4 +82,15 @@ public class X509TrustManagerExtensions {
public boolean isUserAddedCertificate(X509Certificate cert) {
return mDelegate.isUserAddedCertificate(cert);
}
+
+ /**
+ * Returns {@code true} if the TrustManager uses the same trust configuration for the provided
+ * hostnames.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean isSameTrustConfiguration(String hostname1, String hostname2) {
+ return true;
+ }
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 2e31ab692a51..e892349c34f6 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -487,6 +487,16 @@ public class UserManager {
public static final String DISALLOW_RECORD_AUDIO = "no_record_audio";
/**
+ * Specifies if a user is not allowed to use the camera.
+ *
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ * @hide
+ */
+ public static final String DISALLOW_CAMERA = "no_camera";
+
+ /**
* Allows apps in the parent profile to handle web links from the managed profile.
*
* This user restriction has an effect only in a managed profile.
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index d7be6d8c6b29..b50cc79ad341 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -36,7 +36,7 @@ public abstract class UserManagerInternal {
*
* Must be called while taking the {@link #getUserRestrictionsLock()} lock.
*/
- public abstract void updateEffectiveUserRestrictionsRL(int userId);
+ public abstract void updateEffectiveUserRestrictionsLR(int userId);
/**
* Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to get
@@ -44,7 +44,7 @@ public abstract class UserManagerInternal {
*
* Must be called while taking the {@link #getUserRestrictionsLock()} lock.
*/
- public abstract void updateEffectiveUserRestrictionsForAllUsersRL();
+ public abstract void updateEffectiveUserRestrictionsForAllUsersLR();
/**
* Returns the "base" user restrictions.
diff --git a/core/java/android/util/FloatProperty.java b/core/java/android/util/FloatProperty.java
index a67b3cb09f7a..4aac1962ebcf 100644
--- a/core/java/android/util/FloatProperty.java
+++ b/core/java/android/util/FloatProperty.java
@@ -15,18 +15,14 @@
*/
package android.util;
-import android.util.Property;
-
/**
* An implementation of {@link android.util.Property} to be used specifically with fields of type
* <code>float</code>. This type-specific subclass enables performance benefit by allowing
- * calls to a {@link #set(Object, Float) set()} function that takes the primitive
+ * calls to a {@link #setValue(Object, float) setValue()} function that takes the primitive
* <code>float</code> type and avoids autoboxing and other overhead associated with the
* <code>Float</code> class.
*
* @param <T> The class on which the Property is declared.
- *
- * @hide
*/
public abstract class FloatProperty<T> extends Property<T, Float> {
@@ -35,7 +31,7 @@ public abstract class FloatProperty<T> extends Property<T, Float> {
}
/**
- * A type-specific override of the {@link #set(Object, Float)} that is faster when dealing
+ * A type-specific variant of {@link #set(Object, Float)} that is faster when dealing
* with fields of type <code>float</code>.
*/
public abstract void setValue(T object, float value);
diff --git a/core/java/android/util/IntProperty.java b/core/java/android/util/IntProperty.java
index 17977ca63518..9e21cedf1b4b 100644
--- a/core/java/android/util/IntProperty.java
+++ b/core/java/android/util/IntProperty.java
@@ -15,18 +15,14 @@
*/
package android.util;
-import android.util.Property;
-
/**
* An implementation of {@link android.util.Property} to be used specifically with fields of type
* <code>int</code>. This type-specific subclass enables performance benefit by allowing
- * calls to a {@link #set(Object, Integer) set()} function that takes the primitive
+ * calls to a {@link #setValue(Object, int) setValue()} function that takes the primitive
* <code>int</code> type and avoids autoboxing and other overhead associated with the
* <code>Integer</code> class.
*
* @param <T> The class on which the Property is declared.
- *
- * @hide
*/
public abstract class IntProperty<T> extends Property<T, Integer> {
@@ -35,7 +31,7 @@ public abstract class IntProperty<T> extends Property<T, Integer> {
}
/**
- * A type-specific override of the {@link #set(Object, Integer)} that is faster when dealing
+ * A type-specific variant of {@link #set(Object, Integer)} that is faster when dealing
* with fields of type <code>int</code>.
*/
public abstract void setValue(T object, int value);
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 017364a5a0b1..1be2f95cf55a 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -96,6 +96,23 @@ interface IWindowSession {
out Rect outOutsets, out Configuration outConfig, out Surface outSurface);
/**
+ * Position a window relative to it's parent (attached) window without triggering
+ * a full relayout. This action may be deferred until a given frame number
+ * for the parent window appears. This allows for synchronizing movement of a child
+ * to repainting the contents of the parent.
+ *
+ * @param window The window being modified. Must be attached to a parent window
+ * or this call will fail.
+ * @param x The new x position
+ * @param y The new y position
+ * @param deferTransactionUntilFrame Frame number from our parent (attached) to
+ * defer this action until.
+ * @param outFrame Rect in which is placed the new position/size on screen.
+ */
+ void repositionChild(IWindow childWindow, int x, int y, long deferTransactionUntilFrame,
+ out Rect outFrame);
+
+ /**
* If a call to relayout() asked to have the surface destroy deferred,
* it must call this once it is okay to destroy that surface.
*/
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 6de4d3e4e4c3..394660fb538b 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -56,6 +56,8 @@ public class Surface implements Parcelable {
private static native int nativeGetWidth(long nativeObject);
private static native int nativeGetHeight(long nativeObject);
+ private static native long nativeGetNextFrameNumber(long nativeObject);
+
public static final Parcelable.Creator<Surface> CREATOR =
new Parcelable.Creator<Surface>() {
@Override
@@ -220,6 +222,18 @@ public class Surface implements Parcelable {
}
/**
+ * Returns the next frame number which will be dequeued for rendering.
+ * Intended for use with SurfaceFlinger's deferred transactions API.
+ *
+ * @hide
+ */
+ public long getNextFrameNumber() {
+ synchronized (mLock) {
+ return nativeGetNextFrameNumber(mNativeObject);
+ }
+ }
+
+ /**
* Returns true if the consumer of this Surface is running behind the producer.
*
* @return True if the consumer is more than one buffer ahead of the producer.
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index bcf9b2c7fe7c..b58c68f782ee 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -81,6 +81,9 @@ public class SurfaceControl {
private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
private static native void nativeSetDisplayPowerMode(
IBinder displayToken, int mode);
+ private static native void nativeDeferTransactionUntil(long nativeObject,
+ IBinder handle, long frame);
+ private static native IBinder nativeGetHandle(long nativeObject);
private final CloseGuard mCloseGuard = CloseGuard.get();
@@ -358,6 +361,14 @@ public class SurfaceControl {
nativeCloseTransaction();
}
+ public void deferTransactionUntil(IBinder handle, long frame) {
+ nativeDeferTransactionUntil(mNativeObject, handle, frame);
+ }
+
+ public IBinder getHandle() {
+ return nativeGetHandle(mNativeObject);
+ }
+
/** flag the transaction as an animation */
public static void setAnimationTransaction() {
nativeSetAnimationTransaction();
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index db68c29d025f..dddea210ed83 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -448,11 +448,10 @@ public class SurfaceView extends View {
final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
final boolean visibleChanged = mVisible != mRequestedVisible;
final boolean layoutSizeChanged = getWidth() != mLayout.width || getHeight() != mLayout.height;
+ final boolean positionChanged = mLeft != mLocation[0] || mTop != mLocation[1];
if (force || creating || formatChanged || sizeChanged || visibleChanged
- || mLeft != mLocation[0] || mTop != mLocation[1]
|| mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded || layoutSizeChanged) {
-
if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
+ " format=" + formatChanged + " size=" + sizeChanged
+ " visible=" + visibleChanged
@@ -616,11 +615,22 @@ public class SurfaceView extends View {
mSession.performDeferredDestroy(mWindow);
}
} catch (RemoteException ex) {
+ Log.e(TAG, "Exception from relayout", ex);
}
if (DEBUG) Log.v(
TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
" w=" + mLayout.width + " h=" + mLayout.height +
", frame=" + mSurfaceFrame);
+ } else if (positionChanged) { // Only the position has changed
+ mLeft = mLocation[0];
+ mTop = mLocation[1];
+ try {
+ mSession.repositionChild(mWindow, mLeft, mTop,
+ viewRoot != null ? viewRoot.getNextFrameNumber() : -1,
+ mWinFrame);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Exception from relayout", ex);
+ }
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 8b804e8ddc8a..c2af9f7bb24a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3551,6 +3551,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
ListenerInfo mListenerInfo;
+ // Temporary values used to hold (x,y) coordinates when delegating from the
+ // two-arg performLongClick() method to the legacy no-arg version.
+ private float mLongClickX = Float.NaN;
+ private float mLongClickY = Float.NaN;
+
/**
* The application environment this view lives in.
* This field should be made private, so it is hidden from the SDK.
@@ -5379,7 +5384,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@code false} otherwise
*/
public boolean performLongClick() {
- return performLongClickInternal(false, 0, 0);
+ return performLongClickInternal(mLongClickX, mLongClickY);
}
/**
@@ -5387,13 +5392,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* context menu if the OnLongClickListener did not consume the event,
* anchoring it to an (x,y) coordinate.
*
- * @param x x coordinate of the anchoring touch event
- * @param y y coordinate of the anchoring touch event
+ * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
+ * to disable anchoring
+ * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
+ * to disable anchoring
* @return {@code true} if one of the above receivers consumed the event,
* {@code false} otherwise
*/
public boolean performLongClick(float x, float y) {
- return performLongClickInternal(true, x, y);
+ mLongClickX = x;
+ mLongClickY = y;
+ final boolean handled = performLongClick();
+ mLongClickX = Float.NaN;
+ mLongClickY = Float.NaN;
+ return handled;
}
/**
@@ -5401,15 +5413,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* context menu if the OnLongClickListener did not consume the event,
* optionally anchoring it to an (x,y) coordinate.
*
- * @param isAnchored whether this long click is anchored to a touch event
- * @param x x coordinate of the anchoring touch event, ignored if
- * {@code isAnchored} is set to {@code false}
- * @param y y coordinate of the anchoring touch event, ignored if
- * {@code isAnchored} is set to {@code false}
+ * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
+ * to disable anchoring
+ * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
+ * to disable anchoring
* @return {@code true} if one of the above receivers consumed the event,
* {@code false} otherwise
*/
- private boolean performLongClickInternal(boolean isAnchored, float x, float y) {
+ private boolean performLongClickInternal(float x, float y) {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
boolean handled = false;
@@ -5418,6 +5429,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
handled = li.mOnLongClickListener.onLongClick(View.this);
}
if (!handled) {
+ final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
}
if (handled) {
@@ -5455,7 +5467,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
protected boolean performButtonActionOnTouchDown(MotionEvent event) {
- if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
+ if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
(event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
showContextMenu(event.getX(), event.getY());
mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e17bdd7d9a3e..faeb35313174 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -6607,6 +6607,20 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ long getNextFrameNumber() {
+ long frameNumber = -1;
+ if (mSurfaceHolder != null) {
+ mSurfaceHolder.mSurfaceLock.lock();
+ }
+ if (mSurface.isValid()) {
+ frameNumber = mSurface.getNextFrameNumber();
+ }
+ if (mSurfaceHolder != null) {
+ mSurfaceHolder.mSurfaceLock.unlock();
+ }
+ return frameNumber;
+ }
+
class TakenSurfaceHolder extends BaseSurfaceHolder {
@Override
public boolean onAllowLockCanvas() {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 5d11c8b7d888..825937289233 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -552,8 +552,8 @@ public abstract class Window {
/**
* Called to move the window and its activity/task to a different stack container.
* For example, a window can move between
- * {@link android.app.ActivityManager#FULLSCREEN_WORKSPACE_STACK_ID} stack and
- * {@link android.app.ActivityManager#FREEFORM_WORKSPACE_STACK_ID} stack.
+ * {@link android.app.ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} stack and
+ * {@link android.app.ActivityManager.StackId#FREEFORM_WORKSPACE_STACK_ID} stack.
*
* @param stackId stack Id to change to.
*/
diff --git a/core/java/android/webkit/WebResourceRequest.java b/core/java/android/webkit/WebResourceRequest.java
index 23e9a0df56fb..ab935050eb73 100644
--- a/core/java/android/webkit/WebResourceRequest.java
+++ b/core/java/android/webkit/WebResourceRequest.java
@@ -40,9 +40,9 @@ public interface WebResourceRequest {
boolean isForMainFrame();
/**
- * Gets whether the request was a result of a redirect.
+ * Gets whether the request was a result of a server-side redirect.
*
- * @return whether the request was a result of a redirect.
+ * @return whether the request was a result of a server-side redirect.
*/
boolean isRedirect();
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 584deff2659b..cb18b49b65f8 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -96,27 +96,49 @@ public final class WebViewFactory {
public MissingWebViewPackageException(Exception e) { super(e); }
}
+ /** @hide */
+ public static String[] getWebViewPackageNames() {
+ return AppGlobals.getInitialApplication().getResources().getStringArray(
+ com.android.internal.R.array.config_webViewPackageNames);
+ }
+
+ // TODO (gsennton) remove when committing webview xts test change
public static String getWebViewPackageName() {
- return AppGlobals.getInitialApplication().getString(
- com.android.internal.R.string.config_webViewPackageName);
+ String[] webViewPackageNames = getWebViewPackageNames();
+ return webViewPackageNames[webViewPackageNames.length-1];
}
- private static PackageInfo fetchPackageInfo() {
+ /**
+ * Return the package info of the first package in the webview priority list that contains
+ * webview.
+ *
+ * @hide
+ */
+ public static PackageInfo findPreferredWebViewPackage() {
PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
- try {
- return pm.getPackageInfo(getWebViewPackageName(), PackageManager.GET_META_DATA);
- } catch (PackageManager.NameNotFoundException e) {
- throw new MissingWebViewPackageException(e);
+
+ for (String packageName : getWebViewPackageNames()) {
+ try {
+ PackageInfo packageInfo = pm.getPackageInfo(packageName,
+ PackageManager.GET_META_DATA);
+ ApplicationInfo applicationInfo = packageInfo.applicationInfo;
+
+ // If the correct flag is set the package contains webview.
+ if (getWebViewLibrary(applicationInfo) != null) {
+ return packageInfo;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ }
}
+ throw new MissingWebViewPackageException("Could not find a loadable WebView package");
}
// throws MissingWebViewPackageException
private static ApplicationInfo getWebViewApplicationInfo() {
- if (sPackageInfo == null) {
- return fetchPackageInfo().applicationInfo;
- } else {
+ if (sPackageInfo == null)
+ return findPreferredWebViewPackage().applicationInfo;
+ else
return sPackageInfo.applicationInfo;
- }
}
private static String getWebViewLibrary(ApplicationInfo ai) {
@@ -134,7 +156,12 @@ public final class WebViewFactory {
* name is the same as the one providing the webview.
*/
public static int loadWebViewNativeLibraryFromPackage(String packageName) {
- sPackageInfo = fetchPackageInfo();
+ try {
+ sPackageInfo = findPreferredWebViewPackage();
+ } catch (MissingWebViewPackageException e) {
+ return LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
+ }
+
if (packageName != null && packageName.equals(sPackageInfo.packageName)) {
return loadNativeLibrary();
}
@@ -180,7 +207,7 @@ public final class WebViewFactory {
private static Class<WebViewFactoryProvider> getProviderClass() {
try {
// First fetch the package info so we can log the webview package version.
- sPackageInfo = fetchPackageInfo();
+ sPackageInfo = findPreferredWebViewPackage();
Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
index 13d046e45070..830da79c2a0b 100644
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ b/core/java/com/android/internal/os/InstallerConnection.java
@@ -21,6 +21,8 @@ import android.net.LocalSocketAddress;
import android.os.SystemClock;
import android.util.Slog;
+import com.android.internal.util.Preconditions;
+
import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -42,11 +44,22 @@ public class InstallerConnection {
private OutputStream mOut;
private LocalSocket mSocket;
+ private volatile Object mWarnIfHeld;
+
private final byte buf[] = new byte[1024];
public InstallerConnection() {
}
+ /**
+ * Yell loudly if someone tries making future calls while holding a lock on
+ * the given object.
+ */
+ public void setWarnIfHeld(Object warnIfHeld) {
+ Preconditions.checkState(mWarnIfHeld == null);
+ mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
+ }
+
public synchronized String transact(String cmd) {
if (!connect()) {
Slog.e(TAG, "connection failed");
@@ -84,6 +97,11 @@ public class InstallerConnection {
}
public int execute(String cmd) {
+ if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
+ Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+ + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
+ }
+
String res = transact(cmd);
try {
return Integer.parseInt(res);
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index b3bd46dd3869..1bce585c8358 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -16,11 +16,8 @@
package com.android.internal.policy;
-import static android.app.ActivityManager.FIRST_DYNAMIC_STACK_ID;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.INVALID_STACK_ID;
-import static android.app.ActivityManager.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.view.View.MeasureSpec.AT_MOST;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.getMode;
@@ -30,6 +27,7 @@ import static android.view.WindowManager.LayoutParams.*;
import android.animation.Animator;
import android.animation.ObjectAnimator;
+import android.app.ActivityManager.StackId;
import android.app.ActivityManagerNative;
import android.app.SearchManager;
import android.os.Build;
@@ -737,9 +735,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (mWorkspaceId != workspaceId) {
mWorkspaceId = workspaceId;
// We might have to change the kind of surface before we do anything else.
- mNonClientDecorView.phoneWindowUpdated(hasNonClientDecor(mWorkspaceId),
- nonClientDecorHasShadow(mWorkspaceId));
- mDecor.enableNonClientDecor(hasNonClientDecor(workspaceId));
+ mNonClientDecorView.phoneWindowUpdated(StackId.hasWindowDecor(mWorkspaceId),
+ StackId.hasWindowShadow(mWorkspaceId));
+ mDecor.enableNonClientDecor(StackId.hasWindowDecor(workspaceId));
}
}
}
@@ -3735,7 +3733,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
* @return Returns true when the window has a shadow created by the non client decor.
**/
private boolean windowHasShadow() {
- return windowHasNonClientDecor() && nonClientDecorHasShadow(mWindow.mWorkspaceId);
+ return windowHasNonClientDecor() && StackId.hasWindowShadow(mWindow.mWorkspaceId);
}
void setWindow(PhoneWindow phoneWindow) {
@@ -4234,7 +4232,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mWorkspaceId = getWorkspaceId();
// Only a non floating application window on one of the allowed workspaces can get a non
// client decor.
- if (!isFloating() && isApplication && mWorkspaceId < FIRST_DYNAMIC_STACK_ID) {
+ if (!isFloating() && isApplication && StackId.isStaticStack(mWorkspaceId)) {
// Dependent on the brightness of the used title we either use the
// dark or the light button frame.
if (nonClientDecorView == null) {
@@ -4250,12 +4248,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
R.layout.non_client_decor_light, null);
}
}
- nonClientDecorView.setPhoneWindow(this, hasNonClientDecor(mWorkspaceId),
- nonClientDecorHasShadow(mWorkspaceId), getResizingBackgroundDrawable(),
+ nonClientDecorView.setPhoneWindow(this, StackId.hasWindowDecor(mWorkspaceId),
+ StackId.hasWindowShadow(mWorkspaceId), getResizingBackgroundDrawable(),
mDecor.getContext().getDrawable(R.drawable.non_client_decor_title_focused));
}
// Tell the decor if it has a visible non client decor.
- mDecor.enableNonClientDecor(nonClientDecorView != null && hasNonClientDecor(mWorkspaceId));
+ mDecor.enableNonClientDecor(
+ nonClientDecorView != null&& StackId.hasWindowDecor(mWorkspaceId));
return nonClientDecorView;
}
@@ -5428,24 +5427,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return workspaceId;
}
- /**
- * Determines if the window should show a non client decor for the workspace it is in.
- * @param workspaceId The Id of the workspace which contains this window.
- * @Return Returns true if the window should show a non client decor.
- **/
- private static boolean hasNonClientDecor(int workspaceId) {
- return workspaceId == FREEFORM_WORKSPACE_STACK_ID;
- }
-
- /**
- * Determines if the window should show a shadow or not, dependent on the workspace.
- * @param workspaceId The Id of the workspace which contains this window.
- * @Return Returns true if the window should show a shadow.
- **/
- private static boolean nonClientDecorHasShadow(int workspaceId) {
- return workspaceId == FREEFORM_WORKSPACE_STACK_ID || workspaceId == PINNED_STACK_ID;
- }
-
@Override
public void setTheme(int resid) {
mTheme = resid;
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
index be9be11f9da6..de542b1bc65f 100644
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -16,8 +16,9 @@
package com.android.internal.widget;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+
import android.content.Context;
-import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Looper;
@@ -332,8 +333,7 @@ public class NonClientDecorView extends LinearLayout
Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback();
if (callback != null) {
try {
- callback.changeWindowStack(
- android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID);
+ callback.changeWindowStack(FULLSCREEN_WORKSPACE_STACK_ID);
} catch (RemoteException ex) {
Log.e(TAG, "Cannot change task workspace.");
}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index e6c7c2bcf9d7..703a9bd2fcd5 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -28,6 +28,7 @@
#include <cutils/ashmem.h>
#define DEBUG_PARCEL 0
+#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
namespace android {
@@ -993,7 +994,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
// Map the bitmap in place from the ashmem region if possible otherwise copy.
Bitmap* nativeBitmap;
- if (blob.fd() >= 0 && (blob.isMutable() || !isMutable)) {
+ if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
#if DEBUG_PARCEL
ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
"(fds %s)",
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 41aa9ca977fb..0a8ae2bdeecd 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -722,33 +722,33 @@ static jlong android_os_Parcel_getBlobAshmemSize(JNIEnv* env, jclass clazz, jlon
// ----------------------------------------------------------------------------
static const JNINativeMethod gParcelMethods[] = {
- {"nativeDataSize", "(J)I", (void*)android_os_Parcel_dataSize},
- {"nativeDataAvail", "(J)I", (void*)android_os_Parcel_dataAvail},
- {"nativeDataPosition", "(J)I", (void*)android_os_Parcel_dataPosition},
- {"nativeDataCapacity", "(J)I", (void*)android_os_Parcel_dataCapacity},
- {"nativeSetDataSize", "(JI)J", (void*)android_os_Parcel_setDataSize},
- {"nativeSetDataPosition", "(JI)V", (void*)android_os_Parcel_setDataPosition},
- {"nativeSetDataCapacity", "(JI)V", (void*)android_os_Parcel_setDataCapacity},
+ {"nativeDataSize", "!(J)I", (void*)android_os_Parcel_dataSize},
+ {"nativeDataAvail", "!(J)I", (void*)android_os_Parcel_dataAvail},
+ {"nativeDataPosition", "!(J)I", (void*)android_os_Parcel_dataPosition},
+ {"nativeDataCapacity", "!(J)I", (void*)android_os_Parcel_dataCapacity},
+ {"nativeSetDataSize", "!(JI)J", (void*)android_os_Parcel_setDataSize},
+ {"nativeSetDataPosition", "!(JI)V", (void*)android_os_Parcel_setDataPosition},
+ {"nativeSetDataCapacity", "!(JI)V", (void*)android_os_Parcel_setDataCapacity},
- {"nativePushAllowFds", "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
- {"nativeRestoreAllowFds", "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
+ {"nativePushAllowFds", "!(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
+ {"nativeRestoreAllowFds", "!(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
{"nativeWriteByteArray", "(J[BII)V", (void*)android_os_Parcel_writeNative},
{"nativeWriteBlob", "(J[BII)V", (void*)android_os_Parcel_writeBlob},
- {"nativeWriteInt", "(JI)V", (void*)android_os_Parcel_writeInt},
- {"nativeWriteLong", "(JJ)V", (void*)android_os_Parcel_writeLong},
- {"nativeWriteFloat", "(JF)V", (void*)android_os_Parcel_writeFloat},
- {"nativeWriteDouble", "(JD)V", (void*)android_os_Parcel_writeDouble},
+ {"nativeWriteInt", "!(JI)V", (void*)android_os_Parcel_writeInt},
+ {"nativeWriteLong", "!(JJ)V", (void*)android_os_Parcel_writeLong},
+ {"nativeWriteFloat", "!(JF)V", (void*)android_os_Parcel_writeFloat},
+ {"nativeWriteDouble", "!(JD)V", (void*)android_os_Parcel_writeDouble},
{"nativeWriteString", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString},
{"nativeWriteStrongBinder", "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
{"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)J", (void*)android_os_Parcel_writeFileDescriptor},
{"nativeCreateByteArray", "(J)[B", (void*)android_os_Parcel_createByteArray},
{"nativeReadBlob", "(J)[B", (void*)android_os_Parcel_readBlob},
- {"nativeReadInt", "(J)I", (void*)android_os_Parcel_readInt},
- {"nativeReadLong", "(J)J", (void*)android_os_Parcel_readLong},
- {"nativeReadFloat", "(J)F", (void*)android_os_Parcel_readFloat},
- {"nativeReadDouble", "(J)D", (void*)android_os_Parcel_readDouble},
+ {"nativeReadInt", "!(J)I", (void*)android_os_Parcel_readInt},
+ {"nativeReadLong", "!(J)J", (void*)android_os_Parcel_readLong},
+ {"nativeReadFloat", "!(J)F", (void*)android_os_Parcel_readFloat},
+ {"nativeReadDouble", "!(J)D", (void*)android_os_Parcel_readDouble},
{"nativeReadString", "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString},
{"nativeReadStrongBinder", "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
{"nativeReadFileDescriptor", "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
@@ -765,7 +765,7 @@ static const JNINativeMethod gParcelMethods[] = {
{"nativeMarshall", "(J)[B", (void*)android_os_Parcel_marshall},
{"nativeUnmarshall", "(J[BII)J", (void*)android_os_Parcel_unmarshall},
{"nativeAppendFrom", "(JJII)J", (void*)android_os_Parcel_appendFrom},
- {"nativeHasFileDescriptors", "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
+ {"nativeHasFileDescriptors", "!(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
{"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
{"nativeEnforceInterface", "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index c94bc649014e..55b7e7ec8325 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -2156,9 +2156,9 @@ static const JNINativeMethod gAssetManagerMethods[] = {
(void*) android_content_AssetManager_readAsset },
{ "seekAsset", "(JJI)J",
(void*) android_content_AssetManager_seekAsset },
- { "getAssetLength", "(J)J",
+ { "getAssetLength", "!(J)J",
(void*) android_content_AssetManager_getAssetLength },
- { "getAssetRemainingLength", "(J)J",
+ { "getAssetRemainingLength", "!(J)J",
(void*) android_content_AssetManager_getAssetRemainingLength },
{ "addAssetPathNative", "(Ljava/lang/String;Z)I",
(void*) android_content_AssetManager_addAssetPath },
@@ -2174,25 +2174,25 @@ static const JNINativeMethod gAssetManagerMethods[] = {
(void*) android_content_AssetManager_getLocales },
{ "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
(void*) android_content_AssetManager_getSizeConfigurations },
- { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
+ { "setConfiguration", "!(IILjava/lang/String;IIIIIIIIIIIIII)V",
(void*) android_content_AssetManager_setConfiguration },
- { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+ { "getResourceIdentifier","!(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
(void*) android_content_AssetManager_getResourceIdentifier },
- { "getResourceName","(I)Ljava/lang/String;",
+ { "getResourceName","!(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getResourceName },
- { "getResourcePackageName","(I)Ljava/lang/String;",
+ { "getResourcePackageName","!(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getResourcePackageName },
- { "getResourceTypeName","(I)Ljava/lang/String;",
+ { "getResourceTypeName","!(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getResourceTypeName },
- { "getResourceEntryName","(I)Ljava/lang/String;",
+ { "getResourceEntryName","!(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getResourceEntryName },
- { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
+ { "loadResourceValue","!(ISLandroid/util/TypedValue;Z)I",
(void*) android_content_AssetManager_loadResourceValue },
- { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
+ { "loadResourceBagValue","!(IILandroid/util/TypedValue;Z)I",
(void*) android_content_AssetManager_loadResourceBagValue },
- { "getStringBlockCount","()I",
+ { "getStringBlockCount","!()I",
(void*) android_content_AssetManager_getStringBlockCount },
- { "getNativeStringBlock","(I)J",
+ { "getNativeStringBlock","!(I)J",
(void*) android_content_AssetManager_getNativeStringBlock },
{ "getCookieName","(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getCookieName },
@@ -2210,21 +2210,21 @@ static const JNINativeMethod gAssetManagerMethods[] = {
(void*) android_content_AssetManager_copyTheme },
{ "clearTheme", "(J)V",
(void*) android_content_AssetManager_clearTheme },
- { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
+ { "loadThemeAttributeValue", "!(JILandroid/util/TypedValue;Z)I",
(void*) android_content_AssetManager_loadThemeAttributeValue },
- { "getThemeChangingConfigurations", "(J)I",
+ { "getThemeChangingConfigurations", "!(J)I",
(void*) android_content_AssetManager_getThemeChangingConfigurations },
{ "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
(void*) android_content_AssetManager_dumpTheme },
- { "applyStyle","(JIIJ[I[I[I)Z",
+ { "applyStyle","!(JIIJ[I[I[I)Z",
(void*) android_content_AssetManager_applyStyle },
- { "resolveAttrs","(JII[I[I[I[I)Z",
+ { "resolveAttrs","!(JII[I[I[I[I)Z",
(void*) android_content_AssetManager_resolveAttrs },
- { "retrieveAttributes","(J[I[I[I)Z",
+ { "retrieveAttributes","!(J[I[I[I)Z",
(void*) android_content_AssetManager_retrieveAttributes },
- { "getArraySize","(I)I",
+ { "getArraySize","!(I)I",
(void*) android_content_AssetManager_getArraySize },
- { "retrieveArray","(I[I)I",
+ { "retrieveArray","!(I[I)I",
(void*) android_content_AssetManager_retrieveArray },
// XML files.
@@ -2234,11 +2234,11 @@ static const JNINativeMethod gAssetManagerMethods[] = {
// Arrays.
{ "getArrayStringResource","(I)[Ljava/lang/String;",
(void*) android_content_AssetManager_getArrayStringResource },
- { "getArrayStringInfo","(I)[I",
+ { "getArrayStringInfo","!(I)[I",
(void*) android_content_AssetManager_getArrayStringInfo },
- { "getArrayIntResource","(I)[I",
+ { "getArrayIntResource","!(I)[I",
(void*) android_content_AssetManager_getArrayIntResource },
- { "getStyleAttributes","(I)[I",
+ { "getStyleAttributes","!(I)[I",
(void*) android_content_AssetManager_getStyleAttributes },
// Bookkeeping.
diff --git a/core/jni/android_util_XmlBlock.cpp b/core/jni/android_util_XmlBlock.cpp
index 7ae51c89fab7..a15c23cd879a 100644
--- a/core/jni/android_util_XmlBlock.cpp
+++ b/core/jni/android_util_XmlBlock.cpp
@@ -372,37 +372,37 @@ static const JNINativeMethod gXmlBlockMethods[] = {
(void*) android_content_XmlBlock_nativeGetStringBlock },
{ "nativeCreateParseState", "(J)J",
(void*) android_content_XmlBlock_nativeCreateParseState },
- { "nativeNext", "(J)I",
+ { "nativeNext", "!(J)I",
(void*) android_content_XmlBlock_nativeNext },
- { "nativeGetNamespace", "(J)I",
+ { "nativeGetNamespace", "!(J)I",
(void*) android_content_XmlBlock_nativeGetNamespace },
- { "nativeGetName", "(J)I",
+ { "nativeGetName", "!(J)I",
(void*) android_content_XmlBlock_nativeGetName },
- { "nativeGetText", "(J)I",
+ { "nativeGetText", "!(J)I",
(void*) android_content_XmlBlock_nativeGetText },
- { "nativeGetLineNumber", "(J)I",
+ { "nativeGetLineNumber", "!(J)I",
(void*) android_content_XmlBlock_nativeGetLineNumber },
- { "nativeGetAttributeCount", "(J)I",
+ { "nativeGetAttributeCount", "!(J)I",
(void*) android_content_XmlBlock_nativeGetAttributeCount },
- { "nativeGetAttributeNamespace","(JI)I",
+ { "nativeGetAttributeNamespace","!(JI)I",
(void*) android_content_XmlBlock_nativeGetAttributeNamespace },
- { "nativeGetAttributeName", "(JI)I",
+ { "nativeGetAttributeName", "!(JI)I",
(void*) android_content_XmlBlock_nativeGetAttributeName },
- { "nativeGetAttributeResource", "(JI)I",
+ { "nativeGetAttributeResource", "!(JI)I",
(void*) android_content_XmlBlock_nativeGetAttributeResource },
- { "nativeGetAttributeDataType", "(JI)I",
+ { "nativeGetAttributeDataType", "!(JI)I",
(void*) android_content_XmlBlock_nativeGetAttributeDataType },
- { "nativeGetAttributeData", "(JI)I",
+ { "nativeGetAttributeData", "!(JI)I",
(void*) android_content_XmlBlock_nativeGetAttributeData },
- { "nativeGetAttributeStringValue", "(JI)I",
+ { "nativeGetAttributeStringValue", "!(JI)I",
(void*) android_content_XmlBlock_nativeGetAttributeStringValue },
- { "nativeGetAttributeIndex", "(JLjava/lang/String;Ljava/lang/String;)I",
+ { "nativeGetAttributeIndex", "!(JLjava/lang/String;Ljava/lang/String;)I",
(void*) android_content_XmlBlock_nativeGetAttributeIndex },
- { "nativeGetIdAttribute", "(J)I",
+ { "nativeGetIdAttribute", "!(J)I",
(void*) android_content_XmlBlock_nativeGetIdAttribute },
- { "nativeGetClassAttribute", "(J)I",
+ { "nativeGetClassAttribute", "!(J)I",
(void*) android_content_XmlBlock_nativeGetClassAttribute },
- { "nativeGetStyleAttribute", "(J)I",
+ { "nativeGetStyleAttribute", "!(J)I",
(void*) android_content_XmlBlock_nativeGetStyleAttribute },
{ "nativeDestroyParseState", "(J)V",
(void*) android_content_XmlBlock_nativeDestroyParseState },
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index b64acc32e634..9b41eb3c659b 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -151,10 +151,10 @@ static jboolean android_view_DisplayListCanvas_isAvailable(JNIEnv* env, jobject
// not in the emulator
return JNI_TRUE;
}
- // In the emulator this property will be set to 1 when hardware GLES is
+ // In the emulator this property will be set > 0 when OpenGL ES 2.0 is
// enabled, 0 otherwise. On old emulator versions it will be undefined.
property_get("ro.kernel.qemu.gles", prop, "0");
- return atoi(prop) == 1 ? JNI_TRUE : JNI_FALSE;
+ return atoi(prop) > 0 ? JNI_TRUE : JNI_FALSE;
}
// ----------------------------------------------------------------------------
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index da96b935883e..ff51e4ee1263 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -460,6 +460,10 @@ static jint nativeGetHeight(JNIEnv* env, jclass clazz, jlong nativeObject) {
anw->query(anw, NATIVE_WINDOW_HEIGHT, &value);
return value;
}
+static jlong nativeGetNextFrameNumber(JNIEnv *env, jclass clazz, jlong nativeObject) {
+ Surface* surface = reinterpret_cast<Surface*>(nativeObject);
+ return surface->getNextFrameNumber();
+}
namespace uirenderer {
@@ -536,6 +540,7 @@ static const JNINativeMethod gSurfaceMethods[] = {
(void*)nativeWriteToParcel },
{"nativeGetWidth", "(J)I", (void*)nativeGetWidth },
{"nativeGetHeight", "(J)I", (void*)nativeGetHeight },
+ {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber },
// HWUI context
{"nHwuiCreate", "(JJ)J", (void*) hwui::create },
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 931ad54fb5e8..1dfe40a324b3 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -571,6 +571,21 @@ static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject
return JNI_TRUE;
}
+
+static void nativeDeferTransactionUntil(JNIEnv* env, jclass clazz, jlong nativeObject,
+ jobject handleObject, jlong frameNumber) {
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ sp<IBinder> handle = ibinderForJavaObject(env, handleObject);
+
+ ctrl->deferTransactionUntil(handle, frameNumber);
+}
+
+static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+
+ return javaObjectForIBinder(env, ctrl->getHandle());
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -638,6 +653,10 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeGetAnimationFrameStats },
{"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V",
(void*)nativeSetDisplayPowerMode },
+ {"nativeDeferTransactionUntil", "(JLandroid/os/IBinder;J)V",
+ (void*)nativeDeferTransactionUntil },
+ {"nativeGetHandle", "(J)Landroid/os/IBinder;",
+ (void*)nativeGetHandle }
};
int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5828829511c1..561bcbc26d0c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2127,7 +2127,7 @@
<!-- Allows an application to grant specific permissions.
@hide -->
<permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"
- android:protectionLevel="signature|installer" />
+ android:protectionLevel="signature|installer|verifier" />
<!-- Allows an app that has this permission and the permissions to install packages
to request certain runtime permissions to be granted at installation.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 400c8224b28e..76f70629c5ac 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2130,8 +2130,10 @@
string that's stored in 8-bit unpacked format) characters.-->
<bool translatable="false" name="config_sms_decode_gsm_8bit_data">false</bool>
- <!-- Package name providing WebView implementation. -->
- <string name="config_webViewPackageName" translatable="false">com.android.webview</string>
+ <!-- List of package names (ordered by preference) providing WebView implementations. -->
+ <string-array name="config_webViewPackageNames" translatable="false">
+ <item>com.android.webview</item>
+ </string-array>
<!-- If EMS is not supported, framework breaks down EMS into single segment SMS
and adds page info " x/y". This config is used to set which carrier doesn't
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index dd42c2278ba2..bfb0d103d7f2 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -367,11 +367,6 @@
<dimen name="resolver_max_width">480dp</dimen>
- <!-- @deprecated Use config_windowOutsetBottom instead.
- Size of the offset applied to the position of the circular mask. This
- is only used on circular displays. In the case where there is no
- "chin", this will default to 0 -->
- <dimen name="circular_display_mask_offset">0px</dimen>
<!-- Amount to reduce the size of the circular mask by (to compensate for
aliasing effects). This is only used on circular displays. -->
<dimen name="circular_display_mask_thickness">1px</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d1932fc9061d..ba28e81e5794 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -445,7 +445,6 @@
<java-symbol type="dimen" name="notification_large_icon_circle_padding" />
<java-symbol type="dimen" name="notification_badge_size" />
<java-symbol type="dimen" name="immersive_mode_cling_width" />
- <java-symbol type="dimen" name="circular_display_mask_offset" />
<java-symbol type="dimen" name="accessibility_magnification_indicator_width" />
<java-symbol type="dimen" name="circular_display_mask_thickness" />
@@ -2019,7 +2018,7 @@
<java-symbol type="attr" name="actionModeWebSearchDrawable" />
<java-symbol type="string" name="websearch" />
<java-symbol type="drawable" name="ic_media_video_poster" />
- <java-symbol type="string" name="config_webViewPackageName" />
+ <java-symbol type="array" name="config_webViewPackageNames" />
<!-- From SubtitleView -->
<java-symbol type="dimen" name="subtitle_corner_radius" />
diff --git a/core/tests/benchmarks/src/android/content/res/ResourcesBenchmark.java b/core/tests/benchmarks/src/android/content/res/ResourcesBenchmark.java
new file mode 100644
index 000000000000..3638473aac03
--- /dev/null
+++ b/core/tests/benchmarks/src/android/content/res/ResourcesBenchmark.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import com.android.internal.R;
+import com.google.caliper.SimpleBenchmark;
+
+import org.xmlpull.v1.XmlPullParser;
+
+public class ResourcesBenchmark extends SimpleBenchmark {
+
+ private AssetManager mAsset;
+ private Resources mRes;
+
+ private int mTextId;
+ private int mColorId;
+ private int mIntegerId;
+ private int mLayoutId;
+
+ @Override
+ protected void setUp() {
+ mAsset = new AssetManager();
+ mAsset.addAssetPath("/system/framework/framework-res.apk");
+ mRes = new Resources(mAsset, null, null);
+
+ mTextId = mRes.getIdentifier("cancel", "string", "android");
+ mColorId = mRes.getIdentifier("transparent", "color", "android");
+ mIntegerId = mRes.getIdentifier("config_shortAnimTime", "integer", "android");
+ mLayoutId = mRes.getIdentifier("two_line_list_item", "layout", "android");
+ }
+
+ @Override
+ protected void tearDown() {
+ mAsset.close();
+ }
+
+ public void timeGetString(int reps) {
+ for (int i = 0; i < reps; i++) {
+ mRes.getText(mTextId);
+ }
+ }
+
+ public void timeGetColor(int reps) {
+ for (int i = 0; i < reps; i++) {
+ mRes.getColor(mColorId, null);
+ }
+ }
+
+ public void timeGetInteger(int reps) {
+ for (int i = 0; i < reps; i++) {
+ mRes.getInteger(mIntegerId);
+ }
+ }
+
+ public void timeGetLayoutAndTraverse(int reps) throws Exception {
+ for (int i = 0; i < reps; i++) {
+ final XmlResourceParser parser = mRes.getLayout(mLayoutId);
+ try {
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ // Walk the entire tree
+ }
+ } finally {
+ parser.close();
+ }
+ }
+ }
+}
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 3c1036846595..6903b7b8a3fc 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -136,7 +136,9 @@
</intent-filter>
</activity>
- <activity android:name="android.widget.TextViewActivity" android:label="TextViewActivity">
+ <activity android:name="android.widget.TextViewActivity"
+ android:label="TextViewActivity"
+ android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 6a76a27c0bd3..bb515701ef8e 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -36,7 +36,6 @@ import com.android.frameworks.coretests.R;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
-import android.util.OrientationUtil;
import android.view.KeyEvent;
/**
@@ -44,16 +43,13 @@ import android.view.KeyEvent;
*/
public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextViewActivity>{
- private OrientationUtil mOrientationUtil;
-
public TextViewActivityTest() {
super(TextViewActivity.class);
}
@Override
public void setUp() {
- mOrientationUtil = OrientationUtil.initializeAndStartActivityIfNotStarted(this);
- mOrientationUtil.setPortraitOrientation();
+ getActivity();
}
@SmallTest
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 26232a9bc89c..44d7530c6c11 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -382,7 +382,9 @@ public final class Icon implements Parcelable {
* @hide
*/
public void convertToAshmem() {
- if (mType == TYPE_BITMAP && getBitmap().isMutable()) {
+ if (mType == TYPE_BITMAP &&
+ getBitmap().isMutable() &&
+ getBitmap().getAllocationByteCount() >= (128 * (1 << 10))) {
setBitmap(getBitmap().createAshmemBitmap());
}
}
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 340503074447..1ede1052d21b 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -1772,7 +1772,9 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
final Drawable clone;
if (dr != null) {
final ConstantState cs = dr.getConstantState();
- if (res != null) {
+ if (cs == null) {
+ clone = dr;
+ } else if (res != null) {
clone = cs.newDrawable(res);
} else {
clone = cs.newDrawable();
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index d94c91d64572..ae5fa6c15c01 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -56,6 +56,7 @@ hwui_src_files := \
Layer.cpp \
LayerCache.cpp \
LayerRenderer.cpp \
+ LayerUpdateQueue.cpp \
Matrix.cpp \
OpenGLRenderer.cpp \
Patch.cpp \
@@ -204,6 +205,7 @@ LOCAL_SRC_FILES += \
unit_tests/ClipAreaTests.cpp \
unit_tests/DamageAccumulatorTests.cpp \
unit_tests/FatVectorTests.cpp \
+ unit_tests/LayerUpdateQueueTests.cpp \
unit_tests/LinearAllocatorTests.cpp \
unit_tests/StringUtilsTests.cpp
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index 086885320cce..2fca5ea8b962 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -20,6 +20,7 @@
#include "Glop.h"
#include "GlopBuilder.h"
#include "renderstate/RenderState.h"
+#include "utils/FatVector.h"
#include "utils/GLUtils.h"
namespace android {
@@ -29,10 +30,13 @@ namespace uirenderer {
// OffscreenBuffer
////////////////////////////////////////////////////////////////////////////////
-OffscreenBuffer::OffscreenBuffer(Caches& caches, uint32_t textureWidth, uint32_t textureHeight,
+OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches,
+ uint32_t textureWidth, uint32_t textureHeight,
uint32_t viewportWidth, uint32_t viewportHeight)
- : texture(caches)
- , texCoords(0, viewportHeight / float(textureHeight), viewportWidth / float(textureWidth), 0) {
+ : renderState(renderState)
+ , viewportWidth(viewportWidth)
+ , viewportHeight(viewportHeight)
+ , texture(caches) {
texture.width = textureWidth;
texture.height = textureHeight;
@@ -48,16 +52,72 @@ OffscreenBuffer::OffscreenBuffer(Caches& caches, uint32_t textureWidth, uint32_t
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
}
+void OffscreenBuffer::updateMeshFromRegion() {
+ // avoid T-junctions as they cause artifacts in between the resultant
+ // geometry when complex transforms occur.
+ // TODO: generate the safeRegion only if necessary based on drawing transform
+ Region safeRegion = Region::createTJunctionFreeRegion(region);
+
+ size_t count;
+ const android::Rect* rects = safeRegion.getArray(&count);
+
+ const float texX = 1.0f / float(viewportWidth);
+ const float texY = 1.0f / float(viewportHeight);
+
+ FatVector<TextureVertex, 64> meshVector(count * 4); // uses heap if more than 64 vertices needed
+ TextureVertex* mesh = &meshVector[0];
+ for (size_t i = 0; i < count; i++) {
+ const android::Rect* r = &rects[i];
+
+ const float u1 = r->left * texX;
+ const float v1 = (viewportHeight - r->top) * texY;
+ const float u2 = r->right * texX;
+ const float v2 = (viewportHeight - r->bottom) * texY;
+
+ TextureVertex::set(mesh++, r->left, r->top, u1, v1);
+ TextureVertex::set(mesh++, r->right, r->top, u2, v1);
+ TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
+ TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
+ }
+ elementCount = count * 6;
+ renderState.meshState().genOrUpdateMeshBuffer(&vbo,
+ sizeof(TextureVertex) * count * 4,
+ &meshVector[0],
+ GL_DYNAMIC_DRAW); // TODO: GL_STATIC_DRAW if savelayer
+}
+
+OffscreenBuffer::~OffscreenBuffer() {
+ texture.deleteTexture();
+ renderState.meshState().deleteMeshBuffer(vbo);
+ elementCount = 0;
+ vbo = 0;
+}
+
////////////////////////////////////////////////////////////////////////////////
// BakedOpRenderer
////////////////////////////////////////////////////////////////////////////////
-OffscreenBuffer* BakedOpRenderer::startLayer(uint32_t width, uint32_t height) {
+OffscreenBuffer* BakedOpRenderer::createOffscreenBuffer(RenderState& renderState,
+ uint32_t width, uint32_t height) {
+ // TODO: get from cache!
+ return new OffscreenBuffer(renderState, Caches::getInstance(), width, height, width, height);
+}
+
+void BakedOpRenderer::destroyOffscreenBuffer(OffscreenBuffer* offscreenBuffer) {
+ // TODO: return texture/offscreenbuffer to cache!
+ delete offscreenBuffer;
+}
+
+OffscreenBuffer* BakedOpRenderer::createLayer(uint32_t width, uint32_t height) {
LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");
- // TODO: really should be caching these!
- OffscreenBuffer* buffer = new OffscreenBuffer(mCaches, width, height, width, height);
- mRenderTarget.offscreenBuffer = buffer;
+ OffscreenBuffer* buffer = createOffscreenBuffer(mRenderState, width, height);
+ startLayer(buffer);
+ return buffer;
+}
+
+void BakedOpRenderer::startLayer(OffscreenBuffer* offscreenBuffer) {
+ mRenderTarget.offscreenBuffer = offscreenBuffer;
// create and bind framebuffer
mRenderTarget.frameBufferId = mRenderState.genFramebuffer();
@@ -65,7 +125,7 @@ OffscreenBuffer* BakedOpRenderer::startLayer(uint32_t width, uint32_t height) {
// attach the texture to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- buffer->texture.id, 0);
+ offscreenBuffer->texture.id, 0);
LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "startLayer FAILED");
LOG_ALWAYS_FATAL_IF(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
"framebuffer incomplete!");
@@ -75,11 +135,11 @@ OffscreenBuffer* BakedOpRenderer::startLayer(uint32_t width, uint32_t height) {
glClear(GL_COLOR_BUFFER_BIT);
// Change the viewport & ortho projection
- setViewport(width, height);
- return buffer;
+ setViewport(offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight);
}
void BakedOpRenderer::endLayer() {
+ mRenderTarget.offscreenBuffer->updateMeshFromRegion();
mRenderTarget.offscreenBuffer = nullptr;
// Detach the texture from the FBO
@@ -144,6 +204,12 @@ void BakedOpRenderer::renderGlop(const BakedOpState& state, const Glop& glop) {
mRenderState.scissor().set(clip.left, mRenderTarget.viewportHeight - clip.bottom,
clip.getWidth(), clip.getHeight());
}
+ if (mRenderTarget.offscreenBuffer) { // TODO: not with multi-draw
+ // register layer damage to draw-back region
+ const Rect& uiDirty = state.computedState.clippedBounds;
+ android::Rect dirty(uiDirty.left, uiDirty.top, uiDirty.right, uiDirty.bottom);
+ mRenderTarget.offscreenBuffer->region.orSelf(dirty);
+ }
mRenderState.render(glop, mRenderTarget.orthoMatrix);
mHasDrawn = true;
}
@@ -156,6 +222,14 @@ void BakedOpDispatcher::onRenderNodeOp(BakedOpRenderer&, const RenderNodeOp&, co
LOG_ALWAYS_FATAL("unsupported operation");
}
+void BakedOpDispatcher::onBeginLayerOp(BakedOpRenderer& renderer, const BeginLayerOp& op, const BakedOpState& state) {
+ LOG_ALWAYS_FATAL("unsupported operation");
+}
+
+void BakedOpDispatcher::onEndLayerOp(BakedOpRenderer& renderer, const EndLayerOp& op, const BakedOpState& state) {
+ LOG_ALWAYS_FATAL("unsupported operation");
+}
+
void BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op, const BakedOpState& state) {
renderer.caches().textureState().activateTexture(0); // TODO: should this be automatic, and/or elsewhere?
Texture* texture = renderer.getTexture(op.bitmap);
@@ -199,36 +273,26 @@ void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleR
renderer.renderGlop(state, glop);
}
-void BakedOpDispatcher::onBeginLayerOp(BakedOpRenderer& renderer, const BeginLayerOp& op, const BakedOpState& state) {
- LOG_ALWAYS_FATAL("unsupported operation");
-}
-
-void BakedOpDispatcher::onEndLayerOp(BakedOpRenderer& renderer, const EndLayerOp& op, const BakedOpState& state) {
- LOG_ALWAYS_FATAL("unsupported operation");
-}
-
void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) {
OffscreenBuffer* buffer = *op.layerHandle;
// TODO: extend this to handle HW layers & paint properties which
// reside in node.properties().layerProperties()
- float layerAlpha = (op.paint->getAlpha() / 255.0f) * state.alpha;
- const bool tryToSnap = state.computedState.transform.isPureTranslate();
+ float layerAlpha = op.alpha * state.alpha;
Glop glop;
GlopBuilder(renderer.renderState(), renderer.caches(), &glop)
.setRoundRectClipState(state.roundRectClipState)
- .setMeshTexturedUvQuad(nullptr, buffer->texCoords)
- .setFillLayer(buffer->texture, op.paint->getColorFilter(), layerAlpha, PaintUtils::getXfermodeDirect(op.paint), Blend::ModeOrderSwap::NoSwap)
+ .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount)
+ .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap)
.setTransform(state.computedState.transform, TransformFlags::None)
- .setModelViewMapUnitToRectOptionalSnap(tryToSnap, op.unmappedBounds)
+ .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top,
+ Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight()))
.build();
renderer.renderGlop(state, glop);
- // destroy and delete, since each clipped saveLayer is only drawn once.
- buffer->texture.deleteTexture();
-
- // TODO: return texture/offscreenbuffer to cache!
- delete buffer;
+ if (op.destroy) {
+ BakedOpRenderer::destroyOffscreenBuffer(buffer);
+ }
}
} // namespace uirenderer
diff --git a/libs/hwui/BakedOpRenderer.h b/libs/hwui/BakedOpRenderer.h
index 16afad44657e..aa1e67d45d56 100644
--- a/libs/hwui/BakedOpRenderer.h
+++ b/libs/hwui/BakedOpRenderer.h
@@ -35,12 +35,24 @@ class RenderState;
*/
class OffscreenBuffer {
public:
- OffscreenBuffer(Caches& caches, uint32_t textureWidth, uint32_t textureHeight,
+ OffscreenBuffer(RenderState& renderState, Caches& caches,
+ uint32_t textureWidth, uint32_t textureHeight,
uint32_t viewportWidth, uint32_t viewportHeight);
+ ~OffscreenBuffer();
+ // must be called prior to rendering, to construct/update vertex buffer
+ void updateMeshFromRegion();
+
+ RenderState& renderState;
+ uint32_t viewportWidth;
+ uint32_t viewportHeight;
Texture texture;
- Rect texCoords;
+
+ // Portion of offscreen buffer that has been drawn to. Used to minimize drawing area when
+ // drawing back to screen / parent FBO.
Region region;
+ GLsizei elementCount = 0;
+ GLuint vbo = 0;
};
/**
@@ -60,12 +72,17 @@ public:
, mOpaque(opaque) {
}
+ static OffscreenBuffer* createOffscreenBuffer(RenderState& renderState,
+ uint32_t width, uint32_t height);
+ static void destroyOffscreenBuffer(OffscreenBuffer*);
+
RenderState& renderState() { return mRenderState; }
Caches& caches() { return mCaches; }
void startFrame(uint32_t width, uint32_t height);
void endFrame();
- OffscreenBuffer* startLayer(uint32_t width, uint32_t height);
+ OffscreenBuffer* createLayer(uint32_t width, uint32_t height);
+ void startLayer(OffscreenBuffer* offscreenBuffer);
void endLayer();
Texture* getTexture(const SkBitmap* bitmap);
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 7c63e316ba38..94a11f131229 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -23,6 +23,7 @@
#include "ShadowTessellator.h"
#include "utils/GLUtils.h"
+#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/String8.h>
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 61e958d42148..330dc2951ec9 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -43,7 +43,6 @@
#include <GLES3/gl3.h>
#include <utils/KeyedVector.h>
-#include <utils/Singleton.h>
#include <cutils/compiler.h>
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 86796c5a5e0c..00c4e2d47e4c 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -154,7 +154,11 @@ public:
return allocator.usedSize();
}
bool isEmpty() {
+#if HWUI_NEW_OPS
+ return ops.empty();
+#else
return !hasDrawOps;
+#endif
}
private:
@@ -179,7 +183,7 @@ private:
// List of functors
LsaVector<Functor*> functors;
- bool hasDrawOps;
+ bool hasDrawOps; // only used if !HWUI_NEW_OPS
void cleanupResources();
};
diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp
index 06c8a21b019b..6dd29ad8c703 100644
--- a/libs/hwui/Extensions.cpp
+++ b/libs/hwui/Extensions.cpp
@@ -20,6 +20,7 @@
#include "Properties.h"
#include "utils/StringUtils.h"
+#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <utils/Log.h>
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index 0a30d162f2e8..6689b88f17e3 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -19,12 +19,6 @@
#include <cutils/compiler.h>
-#include <utils/Singleton.h>
-#include <utils/SortedVector.h>
-#include <utils/String8.h>
-
-#include <GLES2/gl2.h>
-
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index d2da8513ff56..f3ac93b89893 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -70,6 +70,20 @@ GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop
// Mesh
////////////////////////////////////////////////////////////////////////////////
+GlopBuilder& GlopBuilder::setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementCount) {
+ TRIGGER_STAGE(kMeshStage);
+
+ mOutGlop->mesh.primitiveMode = GL_TRIANGLES;
+ mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr };
+ mOutGlop->mesh.vertices = {
+ vbo,
+ VertexAttribFlags::TextureCoord,
+ nullptr, nullptr, nullptr,
+ kTextureVertexStride };
+ mOutGlop->mesh.elementCount = elementCount;
+ return *this;
+}
+
GlopBuilder& GlopBuilder::setMeshUnitQuad() {
TRIGGER_STAGE(kMeshStage);
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 6f5802eedefd..6270dcbe7a84 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -47,6 +47,7 @@ class GlopBuilder {
public:
GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop);
+ GlopBuilder& setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementCount);
GlopBuilder& setMeshUnitQuad();
GlopBuilder& setMeshTexturedUnitQuad(const UvMapper* uvMapper);
GlopBuilder& setMeshTexturedUvQuad(const UvMapper* uvMapper, const Rect uvs);
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index aa105f9fec0a..8c4645092c97 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -21,6 +21,8 @@
#include "GradientCache.h"
#include "Properties.h"
+#include <cutils/properties.h>
+
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/LayerUpdateQueue.cpp b/libs/hwui/LayerUpdateQueue.cpp
new file mode 100644
index 000000000000..db5f676d09dc
--- /dev/null
+++ b/libs/hwui/LayerUpdateQueue.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "LayerUpdateQueue.h"
+
+#include "RenderNode.h"
+
+namespace android {
+namespace uirenderer {
+
+void LayerUpdateQueue::clear() {
+ mEntries.clear();
+}
+
+void LayerUpdateQueue::enqueueLayerWithDamage(RenderNode* renderNode, Rect damage) {
+ damage.doIntersect(0, 0, renderNode->getWidth(), renderNode->getHeight());
+ if (!damage.isEmpty()) {
+ for (Entry& entry : mEntries) {
+ if (CC_UNLIKELY(entry.renderNode == renderNode)) {
+ entry.damage.unionWith(damage);
+ return;
+ }
+ }
+ mEntries.emplace_back(renderNode, damage);
+ }
+}
+
+} // namespace uirenderer
+} // namespace android
diff --git a/libs/hwui/LayerUpdateQueue.h b/libs/hwui/LayerUpdateQueue.h
new file mode 100644
index 000000000000..be612d2a15e7
--- /dev/null
+++ b/libs/hwui/LayerUpdateQueue.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 ANDROID_HWUI_LAYER_UPDATE_QUEUE_H
+#define ANDROID_HWUI_LAYER_UPDATE_QUEUE_H
+
+#include "Rect.h"
+#include "utils/Macros.h"
+
+#include <vector>
+#include <unordered_map>
+
+namespace android {
+namespace uirenderer {
+
+class RenderNode;
+
+class LayerUpdateQueue {
+ PREVENT_COPY_AND_ASSIGN(LayerUpdateQueue);
+public:
+ struct Entry {
+ Entry(RenderNode* renderNode, const Rect& damage)
+ : renderNode(renderNode)
+ , damage(damage) {}
+ RenderNode* renderNode;
+ Rect damage;
+ };
+
+ LayerUpdateQueue() {}
+ void enqueueLayerWithDamage(RenderNode* renderNode, Rect dirty);
+ void clear();
+ const std::vector<Entry> entries() const { return mEntries; }
+private:
+ std::vector<Entry> mEntries;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_LAYER_UPDATE_QUEUE_H
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp
index ddeb33624798..163f7cc4b1d0 100644
--- a/libs/hwui/OpReorderer.cpp
+++ b/libs/hwui/OpReorderer.cpp
@@ -18,6 +18,7 @@
#include "utils/PaintUtils.h"
#include "RenderNode.h"
+#include "LayerUpdateQueue.h"
#include "SkCanvas.h"
#include "utils/Trace.h"
@@ -202,6 +203,14 @@ private:
Rect mClipRect;
};
+OpReorderer::LayerReorderer::LayerReorderer(uint32_t width, uint32_t height,
+ const BeginLayerOp* beginLayerOp, RenderNode* renderNode)
+ : width(width)
+ , height(height)
+ , offscreenBuffer(renderNode ? renderNode->getLayer() : nullptr)
+ , beginLayerOp(beginLayerOp)
+ , renderNode(renderNode) {}
+
// iterate back toward target to see if anything drawn since should overlap the new op
// if no target, merging ops still iterate to find similar batch to insert after
void OpReorderer::LayerReorderer::locateInsertIndex(int batchId, const Rect& clippedBounds,
@@ -288,33 +297,48 @@ void OpReorderer::LayerReorderer::replayBakedOpsImpl(void* arg, BakedOpDispatche
}
void OpReorderer::LayerReorderer::dump() const {
+ ALOGD("LayerReorderer %p, %ux%u buffer %p, blo %p, rn %p",
+ this, width, height, offscreenBuffer, beginLayerOp, renderNode);
for (const BatchBase* batch : mBatches) {
batch->dump();
}
}
-OpReorderer::OpReorderer(const SkRect& clip, uint32_t viewportWidth, uint32_t viewportHeight,
+OpReorderer::OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip,
+ uint32_t viewportWidth, uint32_t viewportHeight,
const std::vector< sp<RenderNode> >& nodes)
: mCanvasState(*this) {
ATRACE_NAME("prepare drawing commands");
-
mLayerReorderers.emplace_back(viewportWidth, viewportHeight);
- mLayerStack.push_back(0);
+ mLayerStack.push_back(0);
mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
clip.fLeft, clip.fTop, clip.fRight, clip.fBottom,
Vector3());
+
+ // Render all layers to be updated, in order. Defer in reverse order, so that they'll be
+ // updated in the order they're passed in (mLayerReorderers are issued to Renderer in reverse)
+ for (int i = layers.entries().size() - 1; i >= 0; i--) {
+ RenderNode* layerNode = layers.entries()[i].renderNode;
+ const Rect& layerDamage = layers.entries()[i].damage;
+
+ saveForLayer(layerNode->getWidth(), layerNode->getHeight(), nullptr, layerNode);
+ mCanvasState.writableSnapshot()->setClip(
+ layerDamage.left, layerDamage.top, layerDamage.right, layerDamage.bottom);
+
+ if (layerNode->getDisplayList()) {
+ deferImpl(*(layerNode->getDisplayList()));
+ }
+ restoreForLayer();
+ }
+
+ // Defer Fbo0
for (const sp<RenderNode>& node : nodes) {
if (node->nothingToDraw()) continue;
- // TODO: dedupe this code with onRenderNode()
- mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
- if (node->applyViewProperties(mCanvasState)) {
- // not rejected do ops...
- const DisplayList& displayList = node->getDisplayList();
- deferImpl(displayList);
- }
- mCanvasState.restore();
+ int count = mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
+ deferNodePropsAndOps(*node);
+ mCanvasState.restoreToCount(count);
}
}
@@ -334,6 +358,23 @@ void OpReorderer::onViewportInitialized() {}
void OpReorderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
+void OpReorderer::deferNodePropsAndOps(RenderNode& node) {
+ if (node.applyViewProperties(mCanvasState)) {
+ // not rejected so render
+ if (node.getLayer()) {
+ // HW layer
+ LayerOp* drawLayerOp = new (mAllocator) LayerOp(node);
+ BakedOpState* bakedOpState = tryBakeOpState(*drawLayerOp);
+ if (bakedOpState) {
+ // Layer will be drawn into parent layer (which is now current, since we popped mLayerStack)
+ currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Bitmap);
+ }
+ } else {
+ deferImpl(*(node.getDisplayList()));
+ }
+ }
+}
+
/**
* Used to define a list of lambdas referencing private OpReorderer::onXXXXOp() methods.
*
@@ -365,11 +406,9 @@ void OpReorderer::onRenderNodeOp(const RenderNodeOp& op) {
mCanvasState.clipRect(op.localClipRect.left, op.localClipRect.top,
op.localClipRect.right, op.localClipRect.bottom, SkRegion::kIntersect_Op);
- // apply RenderProperties state
- if (op.renderNode->applyViewProperties(mCanvasState)) {
- // if node not rejected based on properties, do ops...
- deferImpl(op.renderNode->getDisplayList());
- }
+ // then apply state from node properties, and defer ops
+ deferNodePropsAndOps(*op.renderNode);
+
mCanvasState.restoreToCount(count);
}
@@ -400,10 +439,8 @@ void OpReorderer::onSimpleRectsOp(const SimpleRectsOp& op) {
currentLayer().deferUnmergeableOp(mAllocator, bakedStateOp, OpBatchType::Vertices);
}
-// TODO: test rejection at defer time, where the bounds become empty
-void OpReorderer::onBeginLayerOp(const BeginLayerOp& op) {
- const uint32_t layerWidth = (uint32_t) op.unmappedBounds.getWidth();
- const uint32_t layerHeight = (uint32_t) op.unmappedBounds.getHeight();
+void OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
+ const BeginLayerOp* beginLayerOp, RenderNode* renderNode) {
mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
mCanvasState.writableSnapshot()->transform->loadIdentity();
@@ -412,18 +449,27 @@ void OpReorderer::onBeginLayerOp(const BeginLayerOp& op) {
// create a new layer, and push its index on the stack
mLayerStack.push_back(mLayerReorderers.size());
- mLayerReorderers.emplace_back(layerWidth, layerHeight);
- mLayerReorderers.back().beginLayerOp = &op;
+ mLayerReorderers.emplace_back(layerWidth, layerHeight, beginLayerOp, renderNode);
}
-void OpReorderer::onEndLayerOp(const EndLayerOp& /* ignored */) {
+void OpReorderer::restoreForLayer() {
+ // restore canvas, and pop finished layer off of the stack
mCanvasState.restore();
+ mLayerStack.pop_back();
+}
- const BeginLayerOp& beginLayerOp = *currentLayer().beginLayerOp;
+// TODO: test rejection at defer time, where the bounds become empty
+void OpReorderer::onBeginLayerOp(const BeginLayerOp& op) {
+ const uint32_t layerWidth = (uint32_t) op.unmappedBounds.getWidth();
+ const uint32_t layerHeight = (uint32_t) op.unmappedBounds.getHeight();
+ saveForLayer(layerWidth, layerHeight, &op, nullptr);
+}
- // pop finished layer off of the stack
+void OpReorderer::onEndLayerOp(const EndLayerOp& /* ignored */) {
+ const BeginLayerOp& beginLayerOp = *currentLayer().beginLayerOp;
int finishedLayerIndex = mLayerStack.back();
- mLayerStack.pop_back();
+
+ restoreForLayer();
// record the draw operation into the previous layer's list of draw commands
// uses state from the associated beginLayerOp, since it has all the state needed for drawing
diff --git a/libs/hwui/OpReorderer.h b/libs/hwui/OpReorderer.h
index 927ecfae3b9f..77be40292205 100644
--- a/libs/hwui/OpReorderer.h
+++ b/libs/hwui/OpReorderer.h
@@ -32,6 +32,7 @@ namespace uirenderer {
class BakedOpState;
class BatchBase;
+class LayerUpdateQueue;
class MergingOpBatch;
class OffscreenBuffer;
class OpBatch;
@@ -64,9 +65,14 @@ class OpReorderer : public CanvasStateClient {
*/
class LayerReorderer {
public:
+ // Create LayerReorderer for Fbo0
LayerReorderer(uint32_t width, uint32_t height)
- : width(width)
- , height(height) {}
+ : LayerReorderer(width, height, nullptr, nullptr) {};
+
+ // Create LayerReorderer for an offscreen layer, where beginLayerOp is present for a
+ // saveLayer, renderNode is present for a HW layer.
+ LayerReorderer(uint32_t width, uint32_t height,
+ const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
// iterate back toward target to see if anything drawn since should overlap the new op
// if no target, merging ops still iterate to find similar batch to insert after
@@ -92,12 +98,12 @@ class OpReorderer : public CanvasStateClient {
void dump() const;
- OffscreenBuffer* offscreenBuffer = nullptr;
- const BeginLayerOp* beginLayerOp = nullptr;
const uint32_t width;
const uint32_t height;
+ OffscreenBuffer* offscreenBuffer;
+ const BeginLayerOp* beginLayerOp;
+ const RenderNode* renderNode;
private:
-
std::vector<BatchBase*> mBatches;
/**
@@ -112,8 +118,8 @@ class OpReorderer : public CanvasStateClient {
};
public:
- // TODO: not final, just presented this way for simplicity. Layers too?
- OpReorderer(const SkRect& clip, uint32_t viewportWidth, uint32_t viewportHeight,
+ OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip,
+ uint32_t viewportWidth, uint32_t viewportHeight,
const std::vector< sp<RenderNode> >& nodes);
OpReorderer(int viewportWidth, int viewportHeight, const DisplayList& displayList);
@@ -144,8 +150,13 @@ public:
// later in the list will be drawn by earlier ones
for (int i = mLayerReorderers.size() - 1; i >= 1; i--) {
LayerReorderer& layer = mLayerReorderers[i];
- if (!layer.empty()) {
- layer.offscreenBuffer = renderer.startLayer(layer.width, layer.height);
+ if (layer.renderNode) {
+ // cached HW layer - can't skip layer if empty
+ renderer.startLayer(layer.offscreenBuffer);
+ layer.replayBakedOpsImpl((void*)&renderer, receivers);
+ renderer.endLayer();
+ } else if (!layer.empty()) { // save layer - skip entire layer if empty
+ layer.offscreenBuffer = renderer.createLayer(layer.width, layer.height);
layer.replayBakedOpsImpl((void*)&renderer, receivers);
renderer.endLayer();
}
@@ -171,12 +182,19 @@ public:
virtual GLuint getTargetFbo() const override { return 0; }
private:
+ void saveForLayer(uint32_t layerWidth, uint32_t layerHeight,
+ const BeginLayerOp* beginLayerOp, RenderNode* renderNode);
+ void restoreForLayer();
+
LayerReorderer& currentLayer() { return mLayerReorderers[mLayerStack.back()]; }
BakedOpState* tryBakeOpState(const RecordedOp& recordedOp) {
return BakedOpState::tryConstruct(mAllocator, *mCanvasState.currentSnapshot(), recordedOp);
}
+ // should always be surrounded by a save/restore pair
+ void deferNodePropsAndOps(RenderNode& node);
+
void deferImpl(const DisplayList& displayList);
void replayBakedOpsImpl(void* arg, BakedOpDispatcher* receivers);
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 4031f2e13f39..fd9ab1847f0d 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -30,6 +30,8 @@
#include "thread/Signal.h"
#include "thread/TaskProcessor.h"
+#include <cutils/properties.h>
+
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index c0c61db0f5d1..e81818679f3e 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -17,8 +17,12 @@
#include "Debug.h"
-#include <algorithm>
+#include <cutils/compiler.h>
#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include <algorithm>
+#include <cstdlib>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 74cd74bde176..1293c786a0bd 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -18,8 +18,6 @@
#define ANDROID_HWUI_PROPERTIES_H
#include <cutils/properties.h>
-#include <stdlib.h>
-#include <utils/Singleton.h>
/**
* This file contains the list of system properties used to configure
diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h
index 7874d85f249c..9ae868a9858c 100644
--- a/libs/hwui/RecordedOp.h
+++ b/libs/hwui/RecordedOp.h
@@ -20,6 +20,7 @@
#include "utils/LinearAllocator.h"
#include "Rect.h"
#include "Matrix.h"
+#include "RenderNode.h"
#include "SkXfermode.h"
@@ -136,13 +137,42 @@ struct EndLayerOp : RecordedOp {
: RecordedOp(RecordedOpId::EndLayerOp, Rect(0, 0), Matrix4::identity(), Rect(0, 0), nullptr) {}
};
+/**
+ * Draws an OffscreenBuffer.
+ *
+ * Alpha, mode, and colorfilter are embedded, since LayerOps are always dynamically generated,
+ * 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.
LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle)
- : SUPER(LayerOp)
- , layerHandle(layerHandle) {}
+ : SUPER_PAINTLESS(LayerOp)
+ , layerHandle(layerHandle)
+ , alpha(paint->getAlpha() / 255.0f)
+ , mode(PaintUtils::getXfermodeDirect(paint))
+ , colorFilter(paint->getColorFilter())
+ , destroy(true) {}
+
+ LayerOp(RenderNode& node)
+ : RecordedOp(RecordedOpId::LayerOp, Rect(node.getWidth(), node.getHeight()), Matrix4::identity(), Rect(node.getWidth(), node.getHeight()), nullptr)
+ , layerHandle(node.getLayerHandle())
+ , alpha(node.properties().layerProperties().alpha() / 255.0f)
+ , mode(node.properties().layerProperties().xferMode())
+ , colorFilter(node.properties().layerProperties().colorFilter())
+ , destroy(false) {}
+
// Records a handle to the Layer object, since the Layer itself won't be
// constructed until after this operation is constructed.
OffscreenBuffer** layerHandle;
+ const float alpha;
+ const SkXfermode::Mode mode;
+
+ // 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 273af3ac5997..7c460b1bbc1a 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -77,7 +77,6 @@ SkCanvas* RecordingCanvas::asSkCanvas() {
// ----------------------------------------------------------------------------
void RecordingCanvas::onViewportInitialized() {
-
}
void RecordingCanvas::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 454ee24cfc64..8a564758e7b1 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -26,9 +26,10 @@
#include "SkiaCanvasProxy.h"
#include "Snapshot.h"
-#include "SkDrawFilter.h"
-#include "SkPaint.h"
-#include "SkTLazy.h"
+#include <SkDrawFilter.h>
+#include <SkPaint.h>
+#include <SkTLazy.h>
+
#include <vector>
namespace android {
diff --git a/libs/hwui/RenderBufferCache.cpp b/libs/hwui/RenderBufferCache.cpp
index 8beed2540e1c..11d7a6af3a6a 100644
--- a/libs/hwui/RenderBufferCache.cpp
+++ b/libs/hwui/RenderBufferCache.cpp
@@ -14,12 +14,14 @@
* limitations under the License.
*/
-#include <utils/Log.h>
-
#include "Debug.h"
#include "Properties.h"
#include "RenderBufferCache.h"
+#include <utils/Log.h>
+
+#include <cstdlib>
+
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 39cb8e9229b1..0601944905a8 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -20,6 +20,7 @@
#include "Debug.h"
#if HWUI_NEW_OPS
#include "RecordedOp.h"
+#include "BakedOpRenderer.h"
#endif
#include "DisplayListOp.h"
#include "LayerRenderer.h"
@@ -42,11 +43,15 @@ namespace android {
namespace uirenderer {
void RenderNode::debugDumpLayers(const char* prefix) {
+#if HWUI_NEW_OPS
+ LOG_ALWAYS_FATAL("TODO: dump layer");
+#else
if (mLayer) {
ALOGD("%sNode %p (%s) has layer %p (fbo = %u, wasBuildLayered = %s)",
prefix, this, getName(), mLayer, mLayer->getFbo(),
mLayer->wasBuildLayered ? "true" : "false");
}
+#endif
if (mDisplayList) {
for (auto&& child : mDisplayList->getChildren()) {
child->renderNode->debugDumpLayers(prefix);
@@ -60,18 +65,21 @@ RenderNode::RenderNode()
, mDisplayList(nullptr)
, mStagingDisplayList(nullptr)
, mAnimatorManager(*this)
- , mLayer(nullptr)
, mParentCount(0) {
}
RenderNode::~RenderNode() {
deleteDisplayList();
delete mStagingDisplayList;
+#if HWUI_NEW_OPS
+ LOG_ALWAYS_FATAL_IF(mLayer, "layer missed detachment!");
+#else
if (mLayer) {
ALOGW("Memory Warning: Layer %p missed its detachment, held on to for far too long!", mLayer);
mLayer->postDecStrong();
mLayer = nullptr;
}
+#endif
}
void RenderNode::setStagingDisplayList(DisplayList* displayList) {
@@ -240,13 +248,29 @@ void RenderNode::prepareLayer(TreeInfo& info, uint32_t dirtyMask) {
}
}
+layer_t* createLayer(RenderState& renderState, uint32_t width, uint32_t height) {
+#if HWUI_NEW_OPS
+ return BakedOpRenderer::createOffscreenBuffer(renderState, width, height);
+#else
+ return LayerRenderer::createRenderLayer(renderState, width, height);
+#endif
+}
+
+void destroyLayer(layer_t* layer) {
+#if HWUI_NEW_OPS
+ BakedOpRenderer::destroyOffscreenBuffer(layer);
+#else
+ LayerRenderer::destroyLayer(layer);
+#endif
+}
+
void RenderNode::pushLayerUpdate(TreeInfo& info) {
LayerType layerType = properties().effectiveLayerType();
// If we are not a layer OR we cannot be rendered (eg, view was detached)
// we need to destroy any Layers we may have had previously
if (CC_LIKELY(layerType != LayerType::RenderLayer) || CC_UNLIKELY(!isRenderable())) {
if (CC_UNLIKELY(mLayer)) {
- LayerRenderer::destroyLayer(mLayer);
+ destroyLayer(mLayer);
mLayer = nullptr;
}
return;
@@ -254,14 +278,18 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
bool transformUpdateNeeded = false;
if (!mLayer) {
- mLayer = LayerRenderer::createRenderLayer(
- info.canvasContext.getRenderState(), getWidth(), getHeight());
- applyLayerPropertiesToLayer(info);
- damageSelf(info);
- transformUpdateNeeded = true;
+ mLayer = createLayer(info.canvasContext.getRenderState(), getWidth(), getHeight());
+ damageSelf(info);
+ transformUpdateNeeded = true;
+#if HWUI_NEW_OPS
+ } else if (mLayer->viewportWidth != getWidth() || mLayer->viewportHeight != getHeight()) {
+ // TODO: allow it to grow larger
+ if (getWidth() > mLayer->texture.width || getHeight() > mLayer->texture.height) {
+#else
} else if (mLayer->layer.getWidth() != getWidth() || mLayer->layer.getHeight() != getHeight()) {
if (!LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight())) {
- LayerRenderer::destroyLayer(mLayer);
+#endif
+ destroyLayer(mLayer);
mLayer = nullptr;
}
damageSelf(info);
@@ -276,7 +304,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
if (info.errorHandler) {
std::ostringstream err;
err << "Unable to create layer for " << getName();
- const int maxTextureSize = Caches::getInstance().maxTextureSize;
+ const uint32_t maxTextureSize = Caches::getInstance().maxTextureSize;
if (getWidth() > maxTextureSize || getHeight() > maxTextureSize) {
err << ", size " << getWidth() << "x" << getHeight()
<< " exceeds max size " << maxTextureSize;
@@ -292,9 +320,16 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
// update the transform in window of the layer to reset its origin wrt light source position
Matrix4 windowTransform;
info.damageAccumulator->computeCurrentTransform(&windowTransform);
+#if HWUI_NEW_OPS
+ // TODO: update layer transform (perhaps as part of enqueueLayerWithDamage)
+#else
mLayer->setWindowTransform(windowTransform);
+#endif
}
+#if HWUI_NEW_OPS
+ info.layerUpdateQueue->enqueueLayerWithDamage(this, dirty);
+#else
if (dirty.intersect(0, 0, getWidth(), getHeight())) {
dirty.roundOut(&dirty);
mLayer->updateDeferred(this, dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom);
@@ -304,6 +339,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
if (info.renderer && mLayer->deferredUpdateScheduled) {
info.renderer->pushLayerUpdate(mLayer);
}
+#endif
// There might be prefetched layers that need to be accounted for.
// That might be us, so tell CanvasContext that this layer is in the
@@ -365,7 +401,9 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) {
damageSelf(info);
info.damageAccumulator->popTransform();
syncProperties();
+#if !HWUI_NEW_OPS
applyLayerPropertiesToLayer(info);
+#endif
// We could try to be clever and only re-damage if the matrix changed.
// However, we don't need to worry about that. The cost of over-damaging
// here is only going to be a single additional map rect of this node
@@ -376,6 +414,7 @@ void RenderNode::pushStagingPropertiesChanges(TreeInfo& info) {
}
}
+#if !HWUI_NEW_OPS
void RenderNode::applyLayerPropertiesToLayer(TreeInfo& info) {
if (CC_LIKELY(!mLayer)) return;
@@ -384,6 +423,7 @@ void RenderNode::applyLayerPropertiesToLayer(TreeInfo& info) {
mLayer->setColorFilter(props.colorFilter());
mLayer->setBlend(props.needsBlending());
}
+#endif
void RenderNode::syncDisplayList() {
// Make sure we inc first so that we don't fluctuate between 0 and 1,
@@ -451,7 +491,7 @@ void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayL
void RenderNode::destroyHardwareResources() {
if (mLayer) {
- LayerRenderer::destroyLayer(mLayer);
+ destroyLayer(mLayer);
mLayer = nullptr;
}
if (mDisplayList) {
@@ -978,7 +1018,11 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
return;
}
+#if HWUI_NEW_OPS
+ const bool drawLayer = false;
+#else
const bool drawLayer = (mLayer && (&renderer != mLayer->renderer.get()));
+#endif
// If we are updating the contents of mLayer, we don't want to apply any of
// the RenderNode's properties to this issueOperations pass. Those will all
// be applied when the layer is drawn, aka when this is true.
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 57e41c611547..3500cb200a51 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -44,13 +44,22 @@ namespace android {
namespace uirenderer {
class CanvasState;
-class DisplayListOp;
class DisplayListCanvas;
+class DisplayListOp;
class OpenGLRenderer;
+class OpReorderer;
class Rect;
-class Layer;
class SkiaShader;
+
+#if HWUI_NEW_OPS
+class OffscreenBuffer;
+typedef OffscreenBuffer layer_t;
+#else
+class Layer;
+typedef Layer layer_t;
+#endif
+
class ClipRectOp;
class SaveLayerOp;
class SaveOp;
@@ -162,11 +171,11 @@ public:
return mStagingProperties;
}
- int getWidth() {
+ uint32_t getWidth() {
return properties().getWidth();
}
- int getHeight() {
+ uint32_t getHeight() {
return properties().getHeight();
}
@@ -193,9 +202,13 @@ public:
}
// Only call if RenderNode has DisplayList...
- const DisplayList& getDisplayList() const {
- return *mDisplayList;
+ const DisplayList* getDisplayList() const {
+ return mDisplayList;
}
+#if HWUI_NEW_OPS
+ OffscreenBuffer* getLayer() const { return mLayer; }
+ OffscreenBuffer** getLayerHandle() { return &mLayer; } // ugh...
+#endif
private:
typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
@@ -262,7 +275,9 @@ private:
void pushStagingPropertiesChanges(TreeInfo& info);
void pushStagingDisplayListChanges(TreeInfo& info);
void prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayList* subtree);
+#if !HWUI_NEW_OPS
void applyLayerPropertiesToLayer(TreeInfo& info);
+#endif
void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
void pushLayerUpdate(TreeInfo& info);
void deleteDisplayList();
@@ -287,7 +302,7 @@ private:
// Owned by RT. Lifecycle is managed by prepareTree(), with the exception
// being in ~RenderNode() which may happen on any thread.
- Layer* mLayer;
+ layer_t* mLayer = nullptr;
/**
* Draw time state - these properties are only set and used during rendering
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 1c3148726b63..be25516c587a 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -16,11 +16,11 @@
#ifndef TREEINFO_H
#define TREEINFO_H
-#include <string>
+#include "utils/Macros.h"
#include <utils/Timers.h>
-#include "utils/Macros.h"
+#include <string>
namespace android {
namespace uirenderer {
@@ -30,6 +30,7 @@ class CanvasContext;
}
class DamageAccumulator;
+class LayerUpdateQueue;
class OpenGLRenderer;
class RenderState;
@@ -75,9 +76,14 @@ public:
// Must not be null during actual usage
DamageAccumulator* damageAccumulator = nullptr;
+
+#if HWUI_NEW_OPS
+ LayerUpdateQueue* layerUpdateQueue = nullptr;
+#else
// The renderer that will be drawing the next frame. Use this to push any
// layer updates or similar. May be NULL.
OpenGLRenderer* renderer = nullptr;
+#endif
ErrorHandler* errorHandler = nullptr;
struct Out {
diff --git a/libs/hwui/microbench/OpReordererBench.cpp b/libs/hwui/microbench/OpReordererBench.cpp
index 43f170f54d41..7b8d0e542a2f 100644
--- a/libs/hwui/microbench/OpReordererBench.cpp
+++ b/libs/hwui/microbench/OpReordererBench.cpp
@@ -56,7 +56,9 @@ void BM_OpReorderer_defer::Run(int iters) {
BENCHMARK_NO_ARG(BM_OpReorderer_deferAndRender);
void BM_OpReorderer_deferAndRender::Run(int iters) {
- TestUtils::runOnRenderThread([this, iters](RenderState& renderState, Caches& caches) {
+ TestUtils::runOnRenderThread([this, iters](renderthread::RenderThread& thread) {
+ RenderState& renderState = thread.renderState();
+ Caches& caches = Caches::getInstance();
StartBenchmarkTiming();
for (int i = 0; i < iters; i++) {
OpReorderer reorderer(200, 200, *sReorderingDisplayList);
diff --git a/libs/hwui/renderstate/MeshState.cpp b/libs/hwui/renderstate/MeshState.cpp
index 0521f6573e39..03cb5ce8ce2e 100644
--- a/libs/hwui/renderstate/MeshState.cpp
+++ b/libs/hwui/renderstate/MeshState.cpp
@@ -100,6 +100,24 @@ bool MeshState::bindMeshBufferInternal(GLuint buffer) {
return false;
}
+void MeshState::genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size,
+ const void* data, GLenum usage) {
+ if (!*buffer) {
+ glGenBuffers(1, buffer);
+ }
+ bindMeshBuffer(*buffer);
+ glBufferData(GL_ARRAY_BUFFER, size, data, usage);
+}
+
+void MeshState::deleteMeshBuffer(GLuint buffer) {
+ if (buffer == mCurrentBuffer) {
+ // GL defines that deleting the currently bound VBO rebinds to 0 (no VBO).
+ // Reflect this in our cached value.
+ mCurrentBuffer = 0;
+ }
+ glDeleteBuffers(1, &buffer);
+}
+
///////////////////////////////////////////////////////////////////////////////
// Vertices
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/renderstate/MeshState.h b/libs/hwui/renderstate/MeshState.h
index e80f4d0d6c41..6c0fb78cae17 100644
--- a/libs/hwui/renderstate/MeshState.h
+++ b/libs/hwui/renderstate/MeshState.h
@@ -75,6 +75,9 @@ public:
*/
bool unbindMeshBuffer();
+ void genOrUpdateMeshBuffer(GLuint* buffer, GLsizeiptr size, const void* data, GLenum usage);
+ void deleteMeshBuffer(GLuint);
+
///////////////////////////////////////////////////////////////////////////////
// Vertices
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c1f667024784..b6fecb45a8ad 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -20,6 +20,7 @@
#include "Caches.h"
#include "DeferredLayerUpdater.h"
#include "EglManager.h"
+#include "LayerUpdateQueue.h"
#include "LayerRenderer.h"
#include "OpenGLRenderer.h"
#include "Properties.h"
@@ -198,7 +199,11 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
mCurrentFrameInfo->markSyncStart();
info.damageAccumulator = &mDamageAccumulator;
+#if HWUI_NEW_OPS
+ info.layerUpdateQueue = &mLayerUpdateQueue;
+#else
info.renderer = mCanvas;
+#endif
mAnimationContext->startFrame(info.mode);
for (const sp<RenderNode>& node : mRenderNodes) {
@@ -333,7 +338,8 @@ void CanvasContext::draw() {
mEglManager.damageFrame(frame, dirty);
#if HWUI_NEW_OPS
- OpReorderer reorderer(dirty, frame.width(), frame.height(), mRenderNodes);
+ OpReorderer reorderer(mLayerUpdateQueue, dirty, frame.width(), frame.height(), mRenderNodes);
+ mLayerUpdateQueue.clear();
BakedOpRenderer renderer(Caches::getInstance(), mRenderThread.renderState(), mOpaque);
// TODO: profiler().draw(mCanvas);
reorderer.replayBakedOps<BakedOpDispatcher>(renderer);
@@ -555,7 +561,11 @@ void CanvasContext::buildLayer(RenderNode* node) {
TreeInfo info(TreeInfo::MODE_FULL, *this);
info.damageAccumulator = &mDamageAccumulator;
+#if HWUI_NEW_OPS
+ info.layerUpdateQueue = &mLayerUpdateQueue;
+#else
info.renderer = mCanvas;
+#endif
info.runAnimations = false;
node->prepareTree(info);
SkRect ignore;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 30e6562526d5..d656014fdbcb 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -18,9 +18,10 @@
#define CANVASCONTEXT_H_
#include "DamageAccumulator.h"
-#include "IContextFactory.h"
#include "FrameInfo.h"
#include "FrameInfoVisualizer.h"
+#include "IContextFactory.h"
+#include "LayerUpdateQueue.h"
#include "RenderNode.h"
#include "utils/RingBuffer.h"
#include "renderthread/RenderTask.h"
@@ -83,7 +84,7 @@ public:
void draw();
void destroy();
- // IFrameCallback, Chroreographer-driven frame callback entry point
+ // IFrameCallback, Choreographer-driven frame callback entry point
virtual void doFrame() override;
void prepareAndDraw(RenderNode* node);
@@ -118,7 +119,7 @@ public:
void addRenderNode(RenderNode* node, bool placeFront) {
int pos = placeFront ? 0 : static_cast<int>(mRenderNodes.size());
- mRenderNodes.emplace( mRenderNodes.begin() + pos, node);
+ mRenderNodes.emplace(mRenderNodes.begin() + pos, node);
}
void removeRenderNode(RenderNode* node) {
@@ -166,6 +167,7 @@ private:
OpenGLRenderer* mCanvas = nullptr;
bool mHaveNewSurface = false;
DamageAccumulator mDamageAccumulator;
+ LayerUpdateQueue mLayerUpdateQueue;
std::unique_ptr<AnimationContext> mAnimationContext;
std::vector< sp<RenderNode> > mRenderNodes;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 15ccd6ac5b6b..a1107f029691 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -563,10 +563,7 @@ void RenderProxy::post(RenderTask* task) {
void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
void* retval;
task->setReturnPtr(&retval);
- SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
- AutoMutex _lock(mSyncMutex);
- mRenderThread.queue(&syncTask);
- mSyncCondition.wait(mSyncMutex);
+ mRenderThread.queueAndWait(task);
return retval;
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 338fab650876..d0e601e09be6 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -117,9 +117,6 @@ private:
DrawFrameTask mDrawFrameTask;
- Mutex mSyncMutex;
- Condition mSyncCondition;
-
void destroyContext();
void post(RenderTask* task);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 8fcd10967e17..526a84861d98 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -28,9 +28,6 @@
#include <utils/Log.h>
namespace android {
-using namespace uirenderer::renderthread;
-ANDROID_SINGLETON_STATIC_INSTANCE(RenderThread);
-
namespace uirenderer {
namespace renderthread {
@@ -136,7 +133,22 @@ public:
}
};
-RenderThread::RenderThread() : Thread(true), Singleton<RenderThread>()
+static bool gHasRenderThreadInstance = false;
+
+bool RenderThread::hasInstance() {
+ return gHasRenderThreadInstance;
+}
+
+RenderThread& RenderThread::getInstance() {
+ // This is a pointer because otherwise __cxa_finalize
+ // will try to delete it like a Good Citizen but that causes us to crash
+ // because we don't want to delete the RenderThread normally.
+ static RenderThread* sInstance = new RenderThread();
+ gHasRenderThreadInstance = true;
+ return *sInstance;
+}
+
+RenderThread::RenderThread() : Thread(true)
, mNextWakeup(LLONG_MAX)
, mDisplayEventReceiver(nullptr)
, mVsyncRequested(false)
@@ -313,13 +325,10 @@ void RenderThread::queue(RenderTask* task) {
}
void RenderThread::queueAndWait(RenderTask* task) {
- Mutex mutex;
- Condition condition;
- SignalingRenderTask syncTask(task, &mutex, &condition);
-
- AutoMutex _lock(mutex);
+ SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
+ AutoMutex _lock(mSyncMutex);
queue(&syncTask);
- condition.wait(mutex);
+ mSyncCondition.wait(mSyncMutex);
}
void RenderThread::queueAtFront(RenderTask* task) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index f3444a85a336..d8c7e61f34eb 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -25,11 +25,11 @@
#include <cutils/compiler.h>
#include <ui/DisplayInfo.h>
#include <utils/Looper.h>
-#include <utils/Mutex.h>
-#include <utils/Singleton.h>
#include <utils/Thread.h>
+#include <condition_variable>
#include <memory>
+#include <mutex>
#include <set>
namespace android {
@@ -72,7 +72,7 @@ protected:
~IFrameCallback() {}
};
-class ANDROID_API RenderThread : public Thread, protected Singleton<RenderThread> {
+class ANDROID_API RenderThread : public Thread {
public:
// RenderThread takes complete ownership of tasks that are queued
// and will delete them after they are run
@@ -100,7 +100,6 @@ protected:
virtual bool threadLoop() override;
private:
- friend class Singleton<RenderThread>;
friend class DispatchFrameCallbacks;
friend class RenderProxy;
friend class android::uirenderer::TestUtils;
@@ -108,6 +107,9 @@ private:
RenderThread();
virtual ~RenderThread();
+ static bool hasInstance();
+ static RenderThread& getInstance();
+
void initThreadLocals();
void initializeDisplayEventReceiver();
static int displayEventReceiverCallback(int fd, int events, void* data);
@@ -125,6 +127,8 @@ private:
nsecs_t mNextWakeup;
TaskQueue mQueue;
+ Mutex mSyncMutex;
+ Condition mSyncCondition;
DisplayInfo mDisplayInfo;
diff --git a/libs/hwui/tests/TreeContentAnimation.cpp b/libs/hwui/tests/TreeContentAnimation.cpp
index 2eefd37561a6..29d9803ddf9c 100644
--- a/libs/hwui/tests/TreeContentAnimation.cpp
+++ b/libs/hwui/tests/TreeContentAnimation.cpp
@@ -24,6 +24,7 @@
#include <RenderNode.h>
#include <renderthread/RenderProxy.h>
#include <renderthread/RenderTask.h>
+#include <unit_tests/TestUtils.h>
#include "Benchmark.h"
#include "TestContext.h"
@@ -401,3 +402,27 @@ static Benchmark _SaveLayer(BenchmarkInfo{
"Tests the clipped saveLayer codepath. Draws content into offscreen buffers and back again.",
TreeContentAnimation::run<SaveLayerAnimation>
});
+
+
+class HwLayerAnimation : public TreeContentAnimation {
+public:
+ sp<RenderNode> card = TestUtils::createNode<TestCanvas>(0, 0, 200, 200, [] (TestCanvas& canvas) {
+ canvas.drawColor(0xFF0000FF, SkXfermode::kSrcOver_Mode);
+ }, true);
+ void createContent(int width, int height, TestCanvas* canvas) override {
+ canvas->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode); // background
+ canvas->drawRenderNode(card.get());
+ }
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % 150;
+ card->mutateStagingProperties().setTranslationX(curFrame);
+ card->mutateStagingProperties().setTranslationY(curFrame);
+ card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+};
+static Benchmark _HwLayer(BenchmarkInfo{
+ "hwlayer",
+ "A nested pair of nodes with LAYER_TYPE_HARDWARE set on each. "
+ "Tests the hardware layer codepath.",
+ TreeContentAnimation::run<HwLayerAnimation>
+});
diff --git a/libs/hwui/unit_tests/FatVectorTests.cpp b/libs/hwui/unit_tests/FatVectorTests.cpp
index fb760ac549cd..3ef329a0d51b 100644
--- a/libs/hwui/unit_tests/FatVectorTests.cpp
+++ b/libs/hwui/unit_tests/FatVectorTests.cpp
@@ -56,6 +56,27 @@ TEST(FatVector, simpleAllocate) {
}
}
+TEST(FatVector, preSizeConstructor) {
+ {
+ FatVector<int, 4> v(32);
+ EXPECT_EQ(32u, v.capacity());
+ EXPECT_EQ(32u, v.size());
+ EXPECT_FALSE(allocationIsInternal(v));
+ }
+ {
+ FatVector<int, 4> v(4);
+ EXPECT_EQ(4u, v.capacity());
+ EXPECT_EQ(4u, v.size());
+ EXPECT_TRUE(allocationIsInternal(v));
+ }
+ {
+ FatVector<int, 4> v(2);
+ EXPECT_EQ(4u, v.capacity());
+ EXPECT_EQ(2u, v.size());
+ EXPECT_TRUE(allocationIsInternal(v));
+ }
+}
+
TEST(FatVector, shrink) {
FatVector<int, 10> v;
EXPECT_TRUE(allocationIsInternal(v));
@@ -78,9 +99,9 @@ TEST(FatVector, destructorInternal) {
FatVector<TestUtils::SignalingDtor, 0> v;
v.emplace_back(&count);
EXPECT_FALSE(allocationIsInternal(v));
- EXPECT_EQ(0, count);
+ EXPECT_EQ(0, count) << "Destruction shouldn't have happened yet";
}
- EXPECT_EQ(1, count);
+ EXPECT_EQ(1, count) << "Destruction should happen exactly once";
}
TEST(FatVector, destructorExternal) {
@@ -92,7 +113,7 @@ TEST(FatVector, destructorExternal) {
v.emplace_back(&count);
EXPECT_TRUE(allocationIsInternal(v));
}
- EXPECT_EQ(0, count);
+ EXPECT_EQ(0, count) << "Destruction shouldn't have happened yet";
}
- EXPECT_EQ(10, count);
+ EXPECT_EQ(10, count) << "Destruction should happen exactly once";
}
diff --git a/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp b/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp
new file mode 100644
index 000000000000..9d625bc62696
--- /dev/null
+++ b/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <gtest/gtest.h>
+
+#include <LayerUpdateQueue.h>
+#include <RenderNode.h>
+
+#include <unit_tests/TestUtils.h>
+
+namespace android {
+namespace uirenderer {
+
+TEST(LayerUpdateQueue, construct) {
+ LayerUpdateQueue queue;
+ EXPECT_TRUE(queue.entries().empty());
+}
+
+// sync node properties, so properties() reflects correct width and height
+static sp<RenderNode> createSyncedNode(uint32_t width, uint32_t height) {
+ sp<RenderNode> node = TestUtils::createNode(0, 0, width, height);
+ TestUtils::syncNodePropertiesAndDisplayList(node);
+ return node;
+}
+
+TEST(LayerUpdateQueue, enqueueSimple) {
+ sp<RenderNode> a = createSyncedNode(100, 100);
+ sp<RenderNode> b = createSyncedNode(200, 200);
+
+ LayerUpdateQueue queue;
+ queue.enqueueLayerWithDamage(a.get(), Rect(25, 25, 75, 75));
+ queue.enqueueLayerWithDamage(b.get(), Rect(100, 100, 300, 300));
+
+ EXPECT_EQ(2u, queue.entries().size());
+
+ EXPECT_EQ(a.get(), queue.entries()[0].renderNode);
+ EXPECT_EQ(Rect(25, 25, 75, 75), queue.entries()[0].damage);
+ EXPECT_EQ(b.get(), queue.entries()[1].renderNode);
+ EXPECT_EQ(Rect(100, 100, 200, 200), queue.entries()[1].damage); // clipped to bounds
+}
+
+TEST(LayerUpdateQueue, enqueueUnion) {
+ sp<RenderNode> a = createSyncedNode(100, 100);
+
+ LayerUpdateQueue queue;
+ queue.enqueueLayerWithDamage(a.get(), Rect(10, 10, 20, 20));
+ queue.enqueueLayerWithDamage(a.get(), Rect(30, 30, 40, 40));
+
+ EXPECT_EQ(1u, queue.entries().size());
+
+ EXPECT_EQ(a.get(), queue.entries()[0].renderNode);
+ EXPECT_EQ(Rect(10, 10, 40, 40), queue.entries()[0].damage);
+}
+
+TEST(LayerUpdateQueue, clear) {
+ sp<RenderNode> a = createSyncedNode(100, 100);
+
+ LayerUpdateQueue queue;
+ queue.enqueueLayerWithDamage(a.get(), Rect(100, 100));
+
+ EXPECT_FALSE(queue.entries().empty());
+
+ queue.clear();
+
+ EXPECT_TRUE(queue.entries().empty());
+}
+
+};
+};
diff --git a/libs/hwui/unit_tests/OpReordererTests.cpp b/libs/hwui/unit_tests/OpReordererTests.cpp
index ffb575f2ddd9..09b10c3af4f9 100644
--- a/libs/hwui/unit_tests/OpReordererTests.cpp
+++ b/libs/hwui/unit_tests/OpReordererTests.cpp
@@ -20,6 +20,7 @@
#include <OpReorderer.h>
#include <RecordedOp.h>
#include <RecordingCanvas.h>
+#include <renderthread/CanvasContext.h> // todo: remove
#include <unit_tests/TestUtils.h>
#include <unordered_map>
@@ -27,6 +28,7 @@
namespace android {
namespace uirenderer {
+LayerUpdateQueue sEmptyLayerUpdateQueue;
/**
* Virtual class implemented by each test to redirect static operation / state transitions to
@@ -42,14 +44,24 @@ namespace uirenderer {
class TestRendererBase {
public:
virtual ~TestRendererBase() {}
- virtual OffscreenBuffer* startLayer(uint32_t width, uint32_t height) { ADD_FAILURE(); return nullptr; }
- virtual void endLayer() { ADD_FAILURE(); }
+ virtual OffscreenBuffer* createLayer(uint32_t, uint32_t) {
+ ADD_FAILURE() << "Layer creation not expected in this test";
+ return nullptr;
+ }
+ virtual void startLayer(OffscreenBuffer*) {
+ ADD_FAILURE() << "Layer repaint not expected in this test";
+ }
+ virtual void endLayer() {
+ ADD_FAILURE() << "Layer updates not expected in this test";
+ }
virtual void startFrame(uint32_t width, uint32_t height) {}
virtual void endFrame() {}
// define virtual defaults for direct
#define BASE_OP_METHOD(Type) \
- virtual void on##Type(const Type&, const BakedOpState&) { ADD_FAILURE(); }
+ virtual void on##Type(const Type&, const BakedOpState&) { \
+ ADD_FAILURE() << #Type " not expected in this test"; \
+ }
MAP_OPS(BASE_OP_METHOD)
int getIndex() { return mIndex; }
@@ -192,7 +204,8 @@ TEST(OpReorderer, renderNode) {
std::vector< sp<RenderNode> > nodes;
nodes.push_back(parent.get());
- OpReorderer reorderer(SkRect::MakeWH(200, 200), 200, 200, nodes);
+ OpReorderer reorderer(sEmptyLayerUpdateQueue,
+ SkRect::MakeWH(200, 200), 200, 200, nodes);
RenderNodeTestRenderer renderer;
reorderer.replayBakedOps<TestDispatcher>(renderer);
@@ -216,7 +229,8 @@ TEST(OpReorderer, clipped) {
std::vector< sp<RenderNode> > nodes;
nodes.push_back(node.get());
- OpReorderer reorderer(SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver
+ OpReorderer reorderer(sEmptyLayerUpdateQueue,
+ SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver
200, 200, nodes);
ClippedTestRenderer renderer;
@@ -226,7 +240,7 @@ TEST(OpReorderer, clipped) {
class SaveLayerSimpleTestRenderer : public TestRendererBase {
public:
- OffscreenBuffer* startLayer(uint32_t width, uint32_t height) override {
+ OffscreenBuffer* createLayer(uint32_t width, uint32_t height) override {
EXPECT_EQ(0, mIndex++);
EXPECT_EQ(180u, width);
EXPECT_EQ(180u, height);
@@ -268,13 +282,13 @@ TEST(OpReorderer, saveLayerSimple) {
/* saveLayer1 {rect1, saveLayer2 { rect2 } } will play back as:
- * - startLayer2, rect2 endLayer2
- * - startLayer1, rect1, drawLayer2, endLayer1
+ * - createLayer2, rect2 endLayer2
+ * - createLayer1, rect1, drawLayer2, endLayer1
* - startFrame, layerOp1, endFrame
*/
class SaveLayerNestedTestRenderer : public TestRendererBase {
public:
- OffscreenBuffer* startLayer(uint32_t width, uint32_t height) override {
+ OffscreenBuffer* createLayer(uint32_t width, uint32_t height) override {
const int index = mIndex++;
if (index == 0) {
EXPECT_EQ(400u, width);
@@ -356,5 +370,162 @@ TEST(OpReorderer, saveLayerContentRejection) {
reorderer.replayBakedOps<TestDispatcher>(renderer);
}
+class HwLayerSimpleTestRenderer : public TestRendererBase {
+public:
+ void startLayer(OffscreenBuffer* offscreenBuffer) override {
+ EXPECT_EQ(0, mIndex++);
+ EXPECT_EQ(offscreenBuffer, (OffscreenBuffer*) 0x0124);
+ }
+ void onRectOp(const RectOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(1, mIndex++);
+
+ EXPECT_TRUE(state.computedState.transform.isIdentity())
+ << "Transform should be reset within layer";
+
+ EXPECT_EQ(state.computedState.clipRect, Rect(25, 25, 75, 75))
+ << "Damage rect should be used to clip layer content";
+ }
+ void endLayer() override {
+ EXPECT_EQ(2, mIndex++);
+ }
+ void startFrame(uint32_t width, uint32_t height) override {
+ EXPECT_EQ(3, mIndex++);
+ }
+ void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(4, mIndex++);
+ }
+ void endFrame() override {
+ EXPECT_EQ(5, mIndex++);
+ }
+};
+TEST(OpReorderer, hwLayerSimple) {
+ sp<RenderNode> node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, [](RecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
+ node->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
+ node->setPropertyFieldsDirty(RenderNode::GENERIC);
+ OffscreenBuffer** bufferHandle = node->getLayerHandle();
+ *bufferHandle = (OffscreenBuffer*) 0x0124;
+
+ TestUtils::syncNodePropertiesAndDisplayList(node);
+
+ std::vector< sp<RenderNode> > nodes;
+ nodes.push_back(node.get());
+
+ // only enqueue partial damage
+ LayerUpdateQueue layerUpdateQueue;
+ layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
+
+ OpReorderer reorderer(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, nodes);
+
+ HwLayerSimpleTestRenderer renderer;
+ reorderer.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(6, renderer.getIndex());
+
+ // clean up layer pointer, so we can safely destruct RenderNode
+ *bufferHandle = nullptr;
+}
+
+
+/* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as:
+ * - startLayer(child), rect(grey), endLayer
+ * - createLayer, drawLayer(child), endLayer
+ * - startLayer(parent), rect(white), drawLayer(saveLayer), endLayer
+ * - startFrame, drawLayer(parent), endLayerb
+ */
+class HwLayerComplexTestRenderer : public TestRendererBase {
+public:
+ OffscreenBuffer* createLayer(uint32_t width, uint32_t height) {
+ EXPECT_EQ(3, mIndex++); // savelayer first
+ return (OffscreenBuffer*)0xabcd;
+ }
+ void startLayer(OffscreenBuffer* offscreenBuffer) override {
+ int index = mIndex++;
+ if (index == 0) {
+ // starting inner layer
+ EXPECT_EQ((OffscreenBuffer*)0x4567, offscreenBuffer);
+ } else if (index == 6) {
+ // starting outer layer
+ EXPECT_EQ((OffscreenBuffer*)0x0123, offscreenBuffer);
+ } else { ADD_FAILURE(); }
+ }
+ void onRectOp(const RectOp& op, const BakedOpState& state) override {
+ int index = mIndex++;
+ if (index == 1) {
+ // inner layer's rect (white)
+ EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
+ } else if (index == 7) {
+ // outer layer's rect (grey)
+ EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
+ } else { ADD_FAILURE(); }
+ }
+ void endLayer() override {
+ int index = mIndex++;
+ EXPECT_TRUE(index == 2 || index == 5 || index == 9);
+ }
+ void startFrame(uint32_t width, uint32_t height) override {
+ EXPECT_EQ(10, mIndex++);
+ }
+ void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
+ int index = mIndex++;
+ if (index == 4) {
+ EXPECT_EQ((OffscreenBuffer*)0x4567, *op.layerHandle);
+ } else if (index == 8) {
+ EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle);
+ } else if (index == 11) {
+ EXPECT_EQ((OffscreenBuffer*)0x0123, *op.layerHandle);
+ } else { ADD_FAILURE(); }
+ }
+ void endFrame() override {
+ EXPECT_EQ(12, mIndex++);
+ }
+};
+TEST(OpReorderer, hwLayerComplex) {
+ sp<RenderNode> child = TestUtils::createNode<RecordingCanvas>(50, 50, 150, 150, [](RecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorWHITE);
+ canvas.drawRect(0, 0, 100, 100, paint);
+ });
+ child->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
+ child->setPropertyFieldsDirty(RenderNode::GENERIC);
+ *(child->getLayerHandle()) = (OffscreenBuffer*) 0x4567;
+
+ RenderNode* childPtr = child.get();
+ sp<RenderNode> parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, [childPtr](RecordingCanvas& canvas) {
+ SkPaint paint;
+ paint.setColor(SK_ColorDKGRAY);
+ canvas.drawRect(0, 0, 200, 200, paint);
+
+ canvas.saveLayerAlpha(50, 50, 150, 150, 128, SkCanvas::kClipToLayer_SaveFlag);
+ canvas.drawRenderNode(childPtr);
+ canvas.restore();
+ });
+ parent->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
+ parent->setPropertyFieldsDirty(RenderNode::GENERIC);
+ *(parent->getLayerHandle()) = (OffscreenBuffer*) 0x0123;
+
+ TestUtils::syncNodePropertiesAndDisplayList(child);
+ TestUtils::syncNodePropertiesAndDisplayList(parent);
+
+ std::vector< sp<RenderNode> > nodes;
+ nodes.push_back(parent.get());
+
+ LayerUpdateQueue layerUpdateQueue;
+ layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100));
+ layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200));
+
+ OpReorderer reorderer(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, nodes);
+
+ HwLayerComplexTestRenderer renderer;
+ reorderer.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(13, renderer.getIndex());
+
+ // clean up layer pointers, so we can safely destruct RenderNodes
+ *(child->getLayerHandle()) = nullptr;
+ *(parent->getLayerHandle()) = nullptr;
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/unit_tests/RecordingCanvasTests.cpp b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
index e8cdf461c783..dcf1f648a9b5 100644
--- a/libs/hwui/unit_tests/RecordingCanvasTests.cpp
+++ b/libs/hwui/unit_tests/RecordingCanvasTests.cpp
@@ -53,7 +53,7 @@ TEST(RecordingCanvas, testSimpleRectRecord) {
ASSERT_EQ(Rect(0, 0, 100, 200), op.localClipRect);
ASSERT_EQ(Rect(10, 20, 90, 180), op.unmappedBounds);
});
- ASSERT_EQ(1, count); // only one observed
+ ASSERT_EQ(1, count);
}
TEST(RecordingCanvas, backgroundAndImage) {
@@ -106,7 +106,7 @@ TEST(RecordingCanvas, backgroundAndImage) {
}
count++;
});
- ASSERT_EQ(2, count); // two draws observed
+ ASSERT_EQ(2, count);
}
TEST(RecordingCanvas, saveLayerSimple) {
@@ -121,7 +121,9 @@ TEST(RecordingCanvas, saveLayerSimple) {
switch(count++) {
case 0:
EXPECT_EQ(RecordedOpId::BeginLayerOp, op.opId);
- // TODO: add asserts
+ EXPECT_EQ(Rect(10, 20, 190, 180), op.unmappedBounds);
+ EXPECT_EQ(Rect(0, 0, 200, 200), op.localClipRect);
+ EXPECT_TRUE(op.localMatrix.isIdentity());
break;
case 1:
EXPECT_EQ(RecordedOpId::RectOp, op.opId);
@@ -132,7 +134,7 @@ TEST(RecordingCanvas, saveLayerSimple) {
break;
case 2:
EXPECT_EQ(RecordedOpId::EndLayerOp, op.opId);
- // TODO: add asserts
+ // Don't bother asserting recording state data - it's not used
break;
default:
ADD_FAILURE();
@@ -155,10 +157,8 @@ TEST(RecordingCanvas, saveLayerViewportCrop) {
if (count++ == 1) {
Matrix4 expectedMatrix;
EXPECT_EQ(RecordedOpId::RectOp, op.opId);
-
- // recorded clip rect should be intersection of
- // viewport and saveLayer bounds, in layer space
- EXPECT_EQ(Rect(0, 0, 100, 100), op.localClipRect);
+ EXPECT_EQ(Rect(0, 0, 100, 100), op.localClipRect) << "Recorded clip rect should be"
+ " intersection of viewport and saveLayer bounds, in layer space";
EXPECT_EQ(Rect(0, 0, 400, 400), op.unmappedBounds);
expectedMatrix.loadTranslate(-100, -100, 0);
EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
@@ -183,14 +183,11 @@ TEST(RecordingCanvas, saveLayerRotateUnclipped) {
int count = 0;
playbackOps(*dl, [&count](const RecordedOp& op) {
if (count++ == 1) {
- Matrix4 expectedMatrix;
EXPECT_EQ(RecordedOpId::RectOp, op.opId);
-
- // recorded rect doesn't see rotate, since recorded relative to saveLayer bounds
EXPECT_EQ(Rect(0, 0, 100, 100), op.localClipRect);
EXPECT_EQ(Rect(0, 0, 100, 100), op.unmappedBounds);
- expectedMatrix.loadIdentity();
- EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
+ EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.localMatrix)
+ << "Recorded op shouldn't see any canvas transform before the saveLayer";
}
});
EXPECT_EQ(3, count);
diff --git a/libs/hwui/unit_tests/TestUtils.h b/libs/hwui/unit_tests/TestUtils.h
index 5b09fdac4ff2..770f413352c2 100644
--- a/libs/hwui/unit_tests/TestUtils.h
+++ b/libs/hwui/unit_tests/TestUtils.h
@@ -89,15 +89,24 @@ public:
return std::unique_ptr<DisplayList>(canvas.finishRecording());
}
- template<class CanvasType>
- static sp<RenderNode> createNode(int left, int top, int right, int bottom,
- std::function<void(CanvasType& canvas)> canvasCallback) {
+ static sp<RenderNode> createNode(int left, int top, int right, int bottom, bool onLayer = false) {
sp<RenderNode> node = new RenderNode();
node->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom);
node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ if (onLayer) {
+ node->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
+ node->setPropertyFieldsDirty(RenderNode::GENERIC);
+ }
+ return node;
+ }
+
+ template<class CanvasType>
+ static sp<RenderNode> createNode(int left, int top, int right, int bottom,
+ std::function<void(CanvasType& canvas)> canvasCallback, bool onLayer = false) {
+ sp<RenderNode> node = createNode(left, top, right, bottom, onLayer);
- CanvasType canvas(
- node->stagingProperties().getWidth(), node->stagingProperties().getHeight());
+ auto&& props = node->stagingProperties(); // staging, since not sync'd yet
+ CanvasType canvas(props.getWidth(), props.getHeight());
canvasCallback(canvas);
node->setStagingDisplayList(canvas.finishRecording());
return node;
@@ -108,7 +117,7 @@ public:
node->syncDisplayList();
}
- typedef std::function<void(RenderState& state, Caches& caches)> RtCallback;
+ typedef std::function<void(renderthread::RenderThread& thread)> RtCallback;
class TestTask : public renderthread::RenderTask {
public:
@@ -120,7 +129,7 @@ public:
RenderState& renderState = renderthread::RenderThread::getInstance().renderState();
renderState.onGLContextCreated();
- rtCallback(renderState, Caches::getInstance());
+ rtCallback(renderthread::RenderThread::getInstance());
renderState.onGLContextDestroyed();
};
RtCallback rtCallback;
diff --git a/libs/hwui/utils/FatVector.h b/libs/hwui/utils/FatVector.h
index c3c16c5ae27d..315c24978a1f 100644
--- a/libs/hwui/utils/FatVector.h
+++ b/libs/hwui/utils/FatVector.h
@@ -91,6 +91,10 @@ public:
InlineStdAllocator<T, SIZE>(mAllocation)) {
this->reserve(SIZE);
}
+
+ FatVector(size_t capacity) : FatVector() {
+ this->resize(capacity);
+ }
private:
typename InlineStdAllocator<T, SIZE>::Allocation mAllocation;
};
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 7f22b8a1ab17..45529efec0d9 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -221,8 +221,9 @@ public final class AudioDeviceInfo {
* @return An array of audio encodings (e.g. {@link AudioFormat#ENCODING_PCM_16BIT},
* {@link AudioFormat#ENCODING_PCM_FLOAT}) supported by the audio device.
* <code>ENCODING_PCM_FLOAT</code> indicates the device supports more
- * than 16 bits of integer precision. Specifying <code>ENCODING_PCM_FLOAT</code>
- * with {@link AudioTrack} or {@link AudioRecord} can preserve at least 24 bits of
+ * than 16 bits of integer precision. As there is no AudioFormat constant
+ * specifically defined for 24-bit PCM, the value <code>ENCODING_PCM_FLOAT</code>
+ * indicates that {@link AudioTrack} or {@link AudioRecord} can preserve at least 24 bits of
* integer precision to that device.
*
* @see AudioFormat
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 875e7165fa81..50df55630a6a 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3199,8 +3199,10 @@ public class AudioManager {
/**
* Returns the value of the property with the specified key.
* @param key One of the strings corresponding to a property key: either
- * {@link #PROPERTY_OUTPUT_SAMPLE_RATE} or
- * {@link #PROPERTY_OUTPUT_FRAMES_PER_BUFFER}
+ * {@link #PROPERTY_OUTPUT_SAMPLE_RATE},
+ * {@link #PROPERTY_OUTPUT_FRAMES_PER_BUFFER},
+ * {@link #PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND}, or
+ * {@link #PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND}.
* @return A string representing the associated value for that property key,
* or null if there is no value for that key.
*/
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index 4019d02da330..ada7f49dbd1f 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -72,10 +72,10 @@
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingStart="@dimen/grid_padding_horiz"
- android:paddingEnd="@dimen/grid_padding_horiz"
- android:paddingTop="@dimen/grid_padding_vert"
- android:paddingBottom="@dimen/grid_padding_vert"
+ android:paddingStart="0dp"
+ android:paddingEnd="0dp"
+ android:paddingTop="0dp"
+ android:paddingBottom="0dp"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
android:drawSelectorOnTop="true"
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index b504db53b779..432205e0179d 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -58,7 +58,7 @@
<string name="root_recent" msgid="4470053704320518133">"اخیر"</string>
<string name="root_available_bytes" msgid="8568452858617033281">"<xliff:g id="SIZE">%1$s</xliff:g> آزاد"</string>
<string name="root_type_service" msgid="2178854894416775409">"خدمات ذخیره‌سازی"</string>
- <string name="root_type_shortcut" msgid="3318760609471618093">"میانبرها"</string>
+ <string name="root_type_shortcut" msgid="3318760609471618093">"میان‌برها"</string>
<string name="root_type_device" msgid="7121342474653483538">"دستگاه‌ها"</string>
<string name="root_type_apps" msgid="8838065367985945189">"برنامه‌های بیشتر"</string>
<string name="empty" msgid="7858882803708117596">"موردی موجود نیست"</string>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index a09a22a19037..3b7da78ccb8d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -66,7 +66,6 @@ import android.support.v7.widget.RecyclerView.LayoutManager;
import android.support.v7.widget.RecyclerView.OnItemTouchListener;
import android.support.v7.widget.RecyclerView.RecyclerListener;
import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.support.v7.widget.SimpleItemAnimator;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Formatter;
@@ -162,6 +161,9 @@ public class DirectoryFragment extends Fragment {
private MessageBar mMessageBar;
private View mProgressBar;
+ private int mSelectedItemColor;
+ private int mDefaultItemColor;
+
public static void showNormal(FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
show(fm, TYPE_NORMAL, root, doc, null, anim);
}
@@ -254,8 +256,7 @@ public class DirectoryFragment extends Fragment {
}
});
- // TODO: Restore transition animations. See b/24802917.
- ((SimpleItemAnimator) mRecView.getItemAnimator()).setSupportsChangeAnimations(false);
+ mRecView.setItemAnimator(new DirectoryItemAnimator(getActivity()));
// TODO: Add a divider between views (which might use RecyclerView.ItemDecoration).
if (DEBUG_ENABLE_DND) {
@@ -293,6 +294,13 @@ public class DirectoryFragment extends Fragment {
mAdapter = new DocumentsAdapter(context);
mRecView.setAdapter(mAdapter);
+ mDefaultItemColor = context.getResources().getColor(android.R.color.transparent);
+ // Get the accent color.
+ TypedValue selColor = new TypedValue();
+ context.getTheme().resolveAttribute(android.R.attr.colorAccent, selColor, true);
+ // Set the opacity to 10%.
+ mSelectedItemColor = (selColor.data & 0x00ffffff) | 0x16000000;
+
GestureDetector.SimpleOnGestureListener listener =
new GestureDetector.SimpleOnGestureListener() {
@Override
@@ -669,7 +677,7 @@ public class DirectoryFragment extends Fragment {
getActivity().getWindow().setStatusBarColor(color.data);
if (mActionMode != null) {
- mActionMode.setTitle(TextUtils.formatSelectedCount(mSelected.size()));
+ mActionMode.setTitle(String.valueOf(mSelected.size()));
}
}
@@ -897,24 +905,26 @@ public class DirectoryFragment extends Fragment {
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
- private static final class DocumentHolder
+ private final class DocumentHolder
extends RecyclerView.ViewHolder
implements View.OnKeyListener
{
- // each data item is just a string in this case
- public View view;
public String docId; // The stable document id.
private ClickListener mClickListener;
private View.OnKeyListener mKeyListener;
public DocumentHolder(View view) {
super(view);
- this.view = view;
// Setting this using android:focusable in the item layouts doesn't work for list items.
// So we set it here. Note that touch mode focus is a separate issue - see
// View.setFocusableInTouchMode and View.isInTouchMode for more info.
- this.view.setFocusable(true);
- this.view.setOnKeyListener(this);
+ view.setFocusable(true);
+ view.setOnKeyListener(this);
+ }
+
+ public void setSelected(boolean selected) {
+ itemView.setActivated(selected);
+ itemView.setBackgroundColor(selected ? mSelectedItemColor : mDefaultItemColor);
}
@Override
@@ -943,10 +953,10 @@ public class DirectoryFragment extends Fragment {
checkState(mKeyListener == null);
mKeyListener = listener;
}
+ }
- interface ClickListener {
- public void onClick(DocumentHolder doc);
- }
+ interface ClickListener {
+ public void onClick(DocumentHolder doc);
}
void showEmptyView() {
@@ -1005,6 +1015,24 @@ public class DirectoryFragment extends Fragment {
return holder;
}
+ /**
+ * Deal with selection changed events by using a custom ItemAnimator that just changes the
+ * background color. This works around focus issues (otherwise items lose focus when their
+ * selection state changes) but also optimizes change animations for selection.
+ */
+ @Override
+ public void onBindViewHolder(DocumentHolder holder, int position, List<Object> payload) {
+ final View itemView = holder.itemView;
+
+ if (payload.contains(MultiSelectManager.SELECTION_CHANGED_MARKER)) {
+ final boolean selected = isSelected(position);
+ itemView.setActivated(selected);
+ return;
+ } else {
+ onBindViewHolder(holder, position);
+ }
+ }
+
@Override
public void onBindViewHolder(DocumentHolder holder, int position) {
@@ -1030,8 +1058,9 @@ public class DirectoryFragment extends Fragment {
final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE);
holder.docId = docId;
- final View itemView = holder.view;
- itemView.setActivated(isSelected(position));
+ final View itemView = holder.itemView;
+
+ holder.setSelected(isSelected(position));
final View line1 = itemView.findViewById(R.id.line1);
final View line2 = itemView.findViewById(R.id.line2);
@@ -1959,7 +1988,7 @@ public class DirectoryFragment extends Fragment {
}
}
- private class ItemClickListener implements DocumentHolder.ClickListener {
+ private class ItemClickListener implements ClickListener {
@Override
public void onClick(DocumentHolder doc) {
final int position = doc.getAdapterPosition();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryItemAnimator.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryItemAnimator.java
new file mode 100644
index 000000000000..0eb1ea55895e
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryItemAnimator.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.documentsui;
+
+import android.animation.Animator;
+import android.animation.ArgbEvaluator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.support.v4.util.ArrayMap;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.RecyclerView;
+import android.util.TypedValue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Performs change animations on Items in DirectoryFragment's RecyclerView. This class overrides
+ * the way selection animations are normally performed - instead of cross fading the old Item with a
+ * new Item, this class manually animates a background color change. This enables selected Items to
+ * correctly maintain focus.
+ */
+class DirectoryItemAnimator extends DefaultItemAnimator {
+ private final List<ColorAnimation> mPendingAnimations = new ArrayList<>();
+ private final Map<RecyclerView.ViewHolder, ColorAnimation> mRunningAnimations =
+ new ArrayMap<>();
+ private final Integer mDefaultColor;
+ private final Integer mSelectedColor;
+
+ public DirectoryItemAnimator(Context context) {
+ mDefaultColor = context.getResources().getColor(android.R.color.transparent);
+ // Get the accent color.
+ TypedValue selColor = new TypedValue();
+ context.getTheme().resolveAttribute(android.R.attr.colorAccent, selColor, true);
+ // Set the opacity to 10%.
+ mSelectedColor = (selColor.data & 0x00ffffff) | 0x16000000;
+ }
+
+ @Override
+ public void runPendingAnimations() {
+ super.runPendingAnimations();
+ for (ColorAnimation anim: mPendingAnimations) {
+ anim.start();
+ mRunningAnimations.put(anim.viewHolder, anim);
+ }
+ mPendingAnimations.clear();
+ }
+
+ @Override
+ public void endAnimation(RecyclerView.ViewHolder vh) {
+ super.endAnimation(vh);
+
+ for (int i = mPendingAnimations.size() - 1; i >= 0; --i) {
+ ColorAnimation anim = mPendingAnimations.get(i);
+ if (anim.viewHolder == vh) {
+ mPendingAnimations.remove(i);
+ anim.end();
+ }
+ }
+
+ ColorAnimation anim = mRunningAnimations.get(vh);
+ if (anim != null) {
+ anim.cancel();
+ }
+ }
+
+ @Override
+ public ItemHolderInfo recordPreLayoutInformation(
+ RecyclerView.State state,
+ RecyclerView.ViewHolder viewHolder,
+ @AdapterChanges int changeFlags,
+ List<Object> payloads) {
+ ItemInfo info = (ItemInfo) super.recordPreLayoutInformation(state,
+ viewHolder, changeFlags, payloads);
+ info.isActivated = viewHolder.itemView.isActivated();
+ return info;
+ }
+
+
+ @Override
+ public ItemHolderInfo recordPostLayoutInformation(
+ RecyclerView.State state, RecyclerView.ViewHolder viewHolder) {
+ ItemInfo info = (ItemInfo) super.recordPostLayoutInformation(state,
+ viewHolder);
+ info.isActivated = viewHolder.itemView.isActivated();
+ return info;
+ }
+
+ @Override
+ public boolean animateChange(final RecyclerView.ViewHolder oldHolder,
+ RecyclerView.ViewHolder newHolder, ItemHolderInfo preInfo,
+ ItemHolderInfo postInfo) {
+ if (oldHolder != newHolder) {
+ return super.animateChange(oldHolder, newHolder, preInfo, postInfo);
+ }
+
+ ItemInfo pre = (ItemInfo)preInfo;
+ ItemInfo post = (ItemInfo)postInfo;
+
+ if (pre.isActivated == post.isActivated) {
+ dispatchAnimationFinished(oldHolder);
+ return false;
+ } else {
+ Integer startColor = pre.isActivated ? mSelectedColor : mDefaultColor;
+ Integer endColor = post.isActivated ? mSelectedColor : mDefaultColor;
+ oldHolder.itemView.setBackgroundColor(startColor);
+ mPendingAnimations.add(new ColorAnimation(oldHolder, startColor, endColor));
+ }
+ return true;
+ }
+
+ @Override
+ public ItemHolderInfo obtainHolderInfo() {
+ return new ItemInfo();
+ }
+
+ @Override
+ public boolean canReuseUpdatedViewHolder(RecyclerView.ViewHolder vh) {
+ return true;
+ }
+
+ class ItemInfo extends DefaultItemAnimator.ItemHolderInfo {
+ boolean isActivated;
+ };
+
+ /**
+ * Animates changes in background color.
+ */
+ class ColorAnimation
+ implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
+ ValueAnimator mValueAnimator;
+ final RecyclerView.ViewHolder viewHolder;
+ int mEndColor;
+
+ public ColorAnimation(RecyclerView.ViewHolder vh, int startColor, int endColor)
+ {
+ viewHolder = vh;
+ mValueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), startColor, endColor);
+ mValueAnimator.addUpdateListener(this);
+ mValueAnimator.addListener(this);
+
+ mEndColor = endColor;
+ }
+
+ public void start() {
+ mValueAnimator.start();
+ }
+
+ public void cancel() {
+ mValueAnimator.cancel();
+ }
+
+ public void end() {
+ mValueAnimator.end();
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animator) {
+ viewHolder.itemView.setBackgroundColor((Integer)animator.getAnimatedValue());
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ viewHolder.itemView.setBackgroundColor(mEndColor);
+ mRunningAnimations.remove(viewHolder);
+ dispatchAnimationFinished(viewHolder);
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ dispatchAnimationStarted(viewHolder);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {}
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {}
+ };
+};
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
index 14a33f9c1cc1..26a373403d80 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
@@ -34,6 +34,7 @@ import android.provider.DocumentsContract;
import android.support.design.widget.Snackbar;
import android.util.Log;
import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.widget.BaseAdapter;
import android.widget.Spinner;
@@ -49,7 +50,6 @@ import java.util.Arrays;
import java.util.List;
public class ManageRootActivity extends BaseActivity {
- private static final int CODE_FORWARD = 42;
private static final String TAG = "ManageRootsActivity";
private Toolbar mToolbar;
@@ -140,6 +140,21 @@ public class ManageRootActivity extends BaseActivity {
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
+
+ final MenuItem advanced = menu.findItem(R.id.menu_advanced);
+ final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
+ final MenuItem newWindow = menu.findItem(R.id.menu_new_window);
+ final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
+ final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
+ final MenuItem search = menu.findItem(R.id.menu_search);
+
+ advanced.setVisible(false);
+ createDir.setVisible(false);
+ pasteFromCb.setEnabled(false);
+ newWindow.setEnabled(false);
+ fileSize.setVisible(false);
+ search.setVisible(false);
+
Menus.disableHiddenItems(menu);
return true;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
index ef53d53c2f78..4fde6ff74fea 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
@@ -76,6 +76,9 @@ public final class MultiSelectManager implements View.OnKeyListener {
private Adapter<?> mAdapter;
private boolean mSingleSelect;
+ // Payloads for notifyItemChange to distinguish between selection and other events.
+ public static final String SELECTION_CHANGED_MARKER = "Selection-Changed";
+
@Nullable private BandController mBandManager;
/**
@@ -460,7 +463,7 @@ public final class MultiSelectManager implements View.OnKeyListener {
for (int i = lastListener; i > -1; i--) {
mCallbacks.get(i).onItemStateChanged(position, selected);
}
- mAdapter.notifyItemChanged(position);
+ mAdapter.notifyItemChanged(position, SELECTION_CHANGED_MARKER);
}
/**
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index d75b6fdf77bc..beff196509b2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -16,6 +16,8 @@
package com.android.documentsui;
+import static com.android.documentsui.Shared.DEBUG;
+
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
@@ -30,6 +32,7 @@ import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.format.Formatter;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -56,12 +59,13 @@ import java.util.Objects;
*/
public class RootsFragment extends Fragment {
+ private static final String TAG = "RootsFragment";
+ private static final String EXTRA_INCLUDE_APPS = "includeApps";
+
private ListView mList;
private RootsAdapter mAdapter;
-
private LoaderCallbacks<Collection<RootInfo>> mCallbacks;
- private static final String EXTRA_INCLUDE_APPS = "includeApps";
public static void show(FragmentManager fm, Intent includeApps) {
final Bundle args = new Bundle();
@@ -180,6 +184,8 @@ public class RootsFragment extends Fragment {
} else if (item instanceof AppItem) {
DocumentsActivity activity = DocumentsActivity.get(RootsFragment.this);
activity.onAppPicked(((AppItem) item).info);
+ } else if (item instanceof SpacerItem) {
+ if (DEBUG) Log.d(TAG, "Ignoring click on spacer item.");
} else {
throw new IllegalStateException("Unknown root: " + item);
}
diff --git a/packages/DocumentsUI/tests/Android.mk b/packages/DocumentsUI/tests/Android.mk
index 2a540d4d77e9..b65ac98d0193 100644
--- a/packages/DocumentsUI/tests/Android.mk
+++ b/packages/DocumentsUI/tests/Android.mk
@@ -8,7 +8,7 @@ LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target guava ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target ub-uiautomator
LOCAL_PACKAGE_NAME := DocumentsUITests
LOCAL_INSTRUMENTATION_FOR := DocumentsUI
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java
index fc42c3b12545..6f1a89baf525 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java
@@ -28,6 +28,7 @@ import android.net.Uri;
import android.os.Parcelable;
import android.os.RemoteException;
import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Document;
import android.test.MoreAsserts;
import android.test.ServiceTestCase;
import android.test.mock.MockContentResolver;
@@ -36,6 +37,7 @@ import android.util.Log;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.RootInfo;
+
import com.google.common.collect.Lists;
import libcore.io.IoUtils;
@@ -52,70 +54,19 @@ import java.util.concurrent.TimeoutException;
public class CopyTest extends ServiceTestCase<CopyService> {
- /**
- * A test resolver that enables this test suite to listen for notifications that mark when copy
- * operations are done.
- */
- class TestContentResolver extends MockContentResolver {
- private CountDownLatch mReadySignal;
- private CountDownLatch mNotificationSignal;
-
- public TestContentResolver() {
- mReadySignal = new CountDownLatch(1);
- }
-
- /**
- * Wait for the given number of files to be copied to destination. Times out after 1 sec.
- */
- public void waitForChanges(int count) throws Exception {
- // Wait for no more than 1 second by default.
- waitForChanges(count, 1000);
- }
-
- /**
- * Wait for files to be copied to destination.
- *
- * @param count Number of files to wait for.
- * @param timeOut Timeout in ms. TimeoutException will be thrown if this function times out.
- */
- public void waitForChanges(int count, int timeOut) throws Exception {
- mNotificationSignal = new CountDownLatch(count);
- // Signal that the test is now waiting for files.
- mReadySignal.countDown();
- if (!mNotificationSignal.await(timeOut, TimeUnit.MILLISECONDS)) {
- throw new TimeoutException("Timed out waiting for file operations to complete.");
- }
- }
-
- @Override
- public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
- // Wait until the test is ready to receive file notifications.
- try {
- mReadySignal.await();
- } catch (InterruptedException e) {
- Log.d(TAG, "Interrupted while waiting for file copy readiness");
- Thread.currentThread().interrupt();
- }
- if (DocumentsContract.isDocumentUri(mContext, uri)) {
- Log.d(TAG, "Notification: " + uri);
- // Watch for document URI change notifications - this signifies the end of a copy.
- mNotificationSignal.countDown();
- }
- }
- };
-
public CopyTest() {
super(CopyService.class);
}
private static String AUTHORITY = "com.android.documentsui.stubprovider";
- private static String DST = "sd1";
- private static String SRC = "sd0";
+ private static String SRC_ROOT = StubProvider.ROOT_0_ID;
+ private static String DST_ROOT = StubProvider.ROOT_1_ID;
private static String TAG = "CopyTest";
- private List<RootInfo> mRoots;
+
private Context mContext;
private TestContentResolver mResolver;
private ContentProviderClient mClient;
+ private DocumentsProviderHelper mDocHelper;
private StubProvider mStorage;
private Context mSystemContext;
@@ -129,18 +80,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
// Reset the stub provider's storage.
mStorage.clearCacheAndBuildRoots();
- mRoots = Lists.newArrayList();
- Uri queryUri = DocumentsContract.buildRootsUri(AUTHORITY);
- Cursor cursor = null;
- try {
- cursor = mClient.query(queryUri, null, null, null, null);
- while (cursor.moveToNext()) {
- mRoots.add(RootInfo.fromRootsCursor(AUTHORITY, cursor));
- }
- } finally {
- IoUtils.closeQuietly(cursor);
- }
-
+ mDocHelper = new DocumentsProviderHelper(AUTHORITY, mClient);
}
@Override
@@ -154,7 +94,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
*/
public void testCopyFile() throws Exception {
String srcPath = "/test0.txt";
- Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
+ Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain",
"The five boxing wizards jump quickly".getBytes());
assertDstFileCountEquals(0);
@@ -172,7 +112,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
public void testMoveFile() throws Exception {
String srcPath = "/test0.txt";
String testContent = "The five boxing wizards jump quickly";
- Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain", testContent.getBytes());
+ Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain", testContent.getBytes());
assertDstFileCountEquals(0);
@@ -185,9 +125,9 @@ public class CopyTest extends ServiceTestCase<CopyService> {
// Verify that one file was moved; check file contents.
assertDstFileCountEquals(1);
- assertDoesNotExist(SRC, srcPath);
+ assertDoesNotExist(SRC_ROOT, srcPath);
- byte[] dstContent = readFile(DST, srcPath);
+ byte[] dstContent = readFile(DST_ROOT, srcPath);
MoreAsserts.assertEquals("Moved file contents differ", testContent.getBytes(), dstContent);
}
@@ -206,9 +146,9 @@ public class CopyTest extends ServiceTestCase<CopyService> {
"/test2.txt"
};
List<Uri> testFiles = Lists.newArrayList(
- mStorage.createFile(SRC, srcPaths[0], "text/plain", testContent[0].getBytes()),
- mStorage.createFile(SRC, srcPaths[1], "text/plain", testContent[1].getBytes()),
- mStorage.createFile(SRC, srcPaths[2], "text/plain", testContent[2].getBytes()));
+ mStorage.createFile(SRC_ROOT, srcPaths[0], "text/plain", testContent[0].getBytes()),
+ mStorage.createFile(SRC_ROOT, srcPaths[1], "text/plain", testContent[1].getBytes()),
+ mStorage.createFile(SRC_ROOT, srcPaths[2], "text/plain", testContent[2].getBytes()));
assertDstFileCountEquals(0);
@@ -226,7 +166,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
public void testCopyEmptyDir() throws Exception {
String srcPath = "/emptyDir";
- Uri testDir = mStorage.createFile(SRC, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
+ Uri testDir = mStorage.createFile(SRC_ROOT, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
null);
assertDstFileCountEquals(0);
@@ -239,13 +179,13 @@ public class CopyTest extends ServiceTestCase<CopyService> {
assertDstFileCountEquals(1);
// Verify that the dst exists and is a directory.
- File dst = mStorage.getFile(DST, srcPath);
+ File dst = mStorage.getFile(DST_ROOT, srcPath);
assertTrue(dst.isDirectory());
}
public void testMoveEmptyDir() throws Exception {
String srcPath = "/emptyDir";
- Uri testDir = mStorage.createFile(SRC, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
+ Uri testDir = mStorage.createFile(SRC_ROOT, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
null);
assertDstFileCountEquals(0);
@@ -260,11 +200,11 @@ public class CopyTest extends ServiceTestCase<CopyService> {
assertDstFileCountEquals(1);
// Verify that the dst exists and is a directory.
- File dst = mStorage.getFile(DST, srcPath);
+ File dst = mStorage.getFile(DST_ROOT, srcPath);
assertTrue(dst.isDirectory());
// Verify that the src was cleaned up.
- assertDoesNotExist(SRC, srcPath);
+ assertDoesNotExist(SRC_ROOT, srcPath);
}
public void testMovePopulatedDir() throws Exception {
@@ -280,11 +220,11 @@ public class CopyTest extends ServiceTestCase<CopyService> {
srcDir + "/test2.txt"
};
// Create test dir; put some files in it.
- Uri testDir = mStorage.createFile(SRC, srcDir, DocumentsContract.Document.MIME_TYPE_DIR,
+ Uri testDir = mStorage.createFile(SRC_ROOT, srcDir, DocumentsContract.Document.MIME_TYPE_DIR,
null);
- mStorage.createFile(SRC, srcFiles[0], "text/plain", testContent[0].getBytes());
- mStorage.createFile(SRC, srcFiles[1], "text/plain", testContent[1].getBytes());
- mStorage.createFile(SRC, srcFiles[2], "text/plain", testContent[2].getBytes());
+ mStorage.createFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
+ mStorage.createFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
+ mStorage.createFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());
Intent moveIntent = createCopyIntent(Lists.newArrayList(testDir));
moveIntent.putExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_MOVE);
@@ -295,24 +235,24 @@ public class CopyTest extends ServiceTestCase<CopyService> {
mResolver.waitForChanges(11);
// Check the content of the moved files.
- File dst = mStorage.getFile(DST, srcDir);
+ File dst = mStorage.getFile(DST_ROOT, srcDir);
assertTrue(dst.isDirectory());
for (int i = 0; i < testContent.length; ++i) {
- byte[] dstContent = readFile(DST, srcFiles[i]);
+ byte[] dstContent = readFile(DST_ROOT, srcFiles[i]);
MoreAsserts.assertEquals("Copied file contents differ", testContent[i].getBytes(),
dstContent);
}
// Check that the src files were removed.
- assertDoesNotExist(SRC, srcDir);
+ assertDoesNotExist(SRC_ROOT, srcDir);
for (String srcFile : srcFiles) {
- assertDoesNotExist(SRC, srcFile);
+ assertDoesNotExist(SRC_ROOT, srcFile);
}
}
public void testCopyFileWithReadErrors() throws Exception {
String srcPath = "/test0.txt";
- Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
+ Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain",
"The five boxing wizards jump quickly".getBytes());
assertDstFileCountEquals(0);
@@ -330,7 +270,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
public void testMoveFileWithReadErrors() throws Exception {
String srcPath = "/test0.txt";
- Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
+ Uri testFile = mStorage.createFile(SRC_ROOT, srcPath, "text/plain",
"The five boxing wizards jump quickly".getBytes());
assertDstFileCountEquals(0);
@@ -352,7 +292,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
} finally {
// Verify that the failed copy was cleaned up, and the src file wasn't removed.
assertDstFileCountEquals(0);
- assertExists(SRC, srcPath);
+ assertExists(SRC_ROOT, srcPath);
}
// The asserts above didn't fail, but the CopyService did something unexpected.
fail("Extra file operations were detected");
@@ -371,12 +311,12 @@ public class CopyTest extends ServiceTestCase<CopyService> {
srcDir + "/test2.txt"
};
// Create test dir; put some files in it.
- Uri testDir = mStorage.createFile(SRC, srcDir, DocumentsContract.Document.MIME_TYPE_DIR,
+ Uri testDir = mStorage.createFile(SRC_ROOT, srcDir, DocumentsContract.Document.MIME_TYPE_DIR,
null);
- mStorage.createFile(SRC, srcFiles[0], "text/plain", testContent[0].getBytes());
+ mStorage.createFile(SRC_ROOT, srcFiles[0], "text/plain", testContent[0].getBytes());
Uri errFile = mStorage
- .createFile(SRC, srcFiles[1], "text/plain", testContent[1].getBytes());
- mStorage.createFile(SRC, srcFiles[2], "text/plain", testContent[2].getBytes());
+ .createFile(SRC_ROOT, srcFiles[1], "text/plain", testContent[1].getBytes());
+ mStorage.createFile(SRC_ROOT, srcFiles[2], "text/plain", testContent[2].getBytes());
mStorage.simulateReadErrorsForFile(errFile);
@@ -391,22 +331,22 @@ public class CopyTest extends ServiceTestCase<CopyService> {
// Check that both the src and dst dirs exist. The src dir shouldn't have been removed,
// because it should contain the one errFile.
- assertTrue(mStorage.getFile(SRC, srcDir).isDirectory());
- assertTrue(mStorage.getFile(DST, srcDir).isDirectory());
+ assertTrue(mStorage.getFile(SRC_ROOT, srcDir).isDirectory());
+ assertTrue(mStorage.getFile(DST_ROOT, srcDir).isDirectory());
// Check the content of the moved files.
MoreAsserts.assertEquals("Copied file contents differ", testContent[0].getBytes(),
- readFile(DST, srcFiles[0]));
+ readFile(DST_ROOT, srcFiles[0]));
MoreAsserts.assertEquals("Copied file contents differ", testContent[2].getBytes(),
- readFile(DST, srcFiles[2]));
+ readFile(DST_ROOT, srcFiles[2]));
// Check that the src files were removed.
- assertDoesNotExist(SRC, srcFiles[0]);
- assertDoesNotExist(SRC, srcFiles[2]);
+ assertDoesNotExist(SRC_ROOT, srcFiles[0]);
+ assertDoesNotExist(SRC_ROOT, srcFiles[2]);
// Check that the error file was not copied over.
- assertDoesNotExist(DST, srcFiles[1]);
- assertExists(SRC, srcFiles[1]);
+ assertDoesNotExist(DST_ROOT, srcFiles[1]);
+ assertExists(SRC_ROOT, srcFiles[1]);
}
/**
@@ -414,13 +354,14 @@ public class CopyTest extends ServiceTestCase<CopyService> {
*
* @throws FileNotFoundException
*/
- private Intent createCopyIntent(List<Uri> srcs) throws FileNotFoundException {
+ private Intent createCopyIntent(List<Uri> srcs) throws Exception {
final ArrayList<DocumentInfo> srcDocs = Lists.newArrayList();
for (Uri src : srcs) {
srcDocs.add(DocumentInfo.fromUri(mResolver, src));
}
- final Uri dst = DocumentsContract.buildDocumentUri(AUTHORITY, mRoots.get(1).documentId);
+ RootInfo root = mDocHelper.getRoot(DST_ROOT);
+ final Uri dst = DocumentsContract.buildDocumentUri(AUTHORITY, root.documentId);
DocumentStack stack = new DocumentStack();
stack.push(DocumentInfo.fromUri(mResolver, dst));
final Intent copyIntent = new Intent(mContext, CopyService.class);
@@ -435,8 +376,9 @@ public class CopyTest extends ServiceTestCase<CopyService> {
* Returns a count of the files in the given directory.
*/
private void assertDstFileCountEquals(int expected) throws RemoteException {
+ RootInfo dest = mDocHelper.getRoot(DST_ROOT);
final Uri queryUri = DocumentsContract.buildChildDocumentsUri(AUTHORITY,
- mRoots.get(1).documentId);
+ dest.documentId);
Cursor c = null;
int count = 0;
try {
@@ -474,8 +416,8 @@ public class CopyTest extends ServiceTestCase<CopyService> {
}
private void assertCopied(String path) throws Exception {
- MoreAsserts.assertEquals("Copied file contents differ", readFile(SRC, path),
- readFile(DST, path));
+ MoreAsserts.assertEquals("Copied file contents differ", readFile(SRC_ROOT, path),
+ readFile(DST_ROOT, path));
}
/**
@@ -509,4 +451,56 @@ public class CopyTest extends ServiceTestCase<CopyService> {
mStorage.attachInfo(mContext, info);
mResolver.addProvider(AUTHORITY, mStorage);
}
+
+ /**
+ * A test resolver that enables this test suite to listen for notifications that mark when copy
+ * operations are done.
+ */
+ class TestContentResolver extends MockContentResolver {
+ private CountDownLatch mReadySignal;
+ private CountDownLatch mNotificationSignal;
+
+ public TestContentResolver() {
+ mReadySignal = new CountDownLatch(1);
+ }
+
+ /**
+ * Wait for the given number of files to be copied to destination. Times out after 1 sec.
+ */
+ public void waitForChanges(int count) throws Exception {
+ // Wait for no more than 1 second by default.
+ waitForChanges(count, 1000);
+ }
+
+ /**
+ * Wait for files to be copied to destination.
+ *
+ * @param count Number of files to wait for.
+ * @param timeOut Timeout in ms. TimeoutException will be thrown if this function times out.
+ */
+ public void waitForChanges(int count, int timeOut) throws Exception {
+ mNotificationSignal = new CountDownLatch(count);
+ // Signal that the test is now waiting for files.
+ mReadySignal.countDown();
+ if (!mNotificationSignal.await(timeOut, TimeUnit.MILLISECONDS)) {
+ throw new TimeoutException("Timed out waiting for file operations to complete.");
+ }
+ }
+
+ @Override
+ public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
+ // Wait until the test is ready to receive file notifications.
+ try {
+ mReadySignal.await();
+ } catch (InterruptedException e) {
+ Log.d(TAG, "Interrupted while waiting for file copy readiness");
+ Thread.currentThread().interrupt();
+ }
+ if (DocumentsContract.isDocumentUri(mContext, uri)) {
+ Log.d(TAG, "Notification: " + uri);
+ // Watch for document URI change notifications - this signifies the end of a copy.
+ mNotificationSignal.countDown();
+ }
+ }
+ };
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java b/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
new file mode 100644
index 000000000000..7abc99c99a5a
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/DocumentsProviderHelper.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.documentsui;
+
+import static com.android.documentsui.model.DocumentInfo.getCursorString;
+
+import android.content.ContentProviderClient;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
+
+import com.android.documentsui.model.RootInfo;
+
+import libcore.io.IoUtils;
+
+/**
+ * Provides support for creation of documents in a test settings.
+ */
+public class DocumentsProviderHelper {
+
+ private final ContentProviderClient mClient;
+ private final String mAuthority;
+
+ public DocumentsProviderHelper(String authority, ContentProviderClient client) {
+ mClient = client;
+ mAuthority = authority;
+ }
+
+ public RootInfo getRoot(String id) throws RemoteException {
+ final Uri rootsUri = DocumentsContract.buildRootsUri(mAuthority);
+
+ Cursor cursor = null;
+ try {
+ cursor = mClient.query(rootsUri, null, null, null, null);
+ while (cursor.moveToNext()) {
+ if (id.equals(getCursorString(cursor, Root.COLUMN_ROOT_ID))) {
+ return RootInfo.fromRootsCursor(mAuthority, cursor);
+ }
+ }
+ throw new IllegalArgumentException("Can't find matching root for id=" + id);
+ } catch (Exception e) {
+ throw new RuntimeException("Can't load root for id=" + id , e);
+ } finally {
+ IoUtils.closeQuietly(cursor);
+ }
+ }
+
+ public Uri createDocument(Uri parentUri, String mimeType, String name) {
+ if (name.contains("/")) {
+ throw new IllegalArgumentException("Name and mimetype probably interposed.");
+ }
+ try {
+ return DocumentsContract.createDocument(mClient, parentUri, mimeType, name);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Couldn't create document: " + name + " with mimetype " + mimeType, e);
+ }
+ }
+
+ public Uri createFolder(Uri parentUri, String name) {
+ return createDocument(parentUri, Document.MIME_TYPE_DIR, name);
+ }
+
+ public Uri createDocument(RootInfo root, String mimeType, String name) {
+ Uri rootUri = DocumentsContract.buildDocumentUri(mAuthority, root.documentId);
+ return createDocument(rootUri, mimeType, name);
+ }
+
+ public Uri createFolder(RootInfo root, String name) {
+ return createDocument(root, Document.MIME_TYPE_DIR, name);
+ }
+}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index 1f4b751abc85..906051640c6a 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -16,83 +16,158 @@
package com.android.documentsui;
+import static com.android.documentsui.StubProvider.DEFAULT_AUTHORITY;
+import static com.android.documentsui.StubProvider.ROOT_0_ID;
+import static com.android.documentsui.StubProvider.ROOT_1_ID;
+
+import android.app.Instrumentation;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.os.RemoteException;
import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.Configurator;
import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.test.InstrumentationTestCase;
+import android.util.Log;
import android.view.MotionEvent;
-import java.util.concurrent.TimeoutException;
+import com.android.documentsui.model.RootInfo;
public class FilesActivityUiTest extends InstrumentationTestCase {
+ private static final int TIMEOUT = 5000;
private static final String TAG = "FilesActivityUiTest";
private static final String TARGET_PKG = "com.android.documentsui";
private static final String LAUNCHER_PKG = "com.android.launcher";
- private static final int ONE_SECOND = 1000;
- private static final int FIVE_SECONDS = 5 * ONE_SECOND;
- private ActionBar mBar;
+ private UiBot mBot;
private UiDevice mDevice;
private Context mContext;
+ private ContentResolver mResolver;
+ private DocumentsProviderHelper mDocsHelper;
+ private ContentProviderClient mClient;
+ private RootInfo mRoot_0;
+ private RootInfo mRoot_1;
- public void setUp() throws TimeoutException {
+ public void setUp() throws Exception {
// Initialize UiDevice instance.
- mDevice = UiDevice.getInstance(getInstrumentation());
+ Instrumentation instrumentation = getInstrumentation();
+
+ mDevice = UiDevice.getInstance(instrumentation);
Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
// Start from the home screen.
mDevice.pressHome();
- mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), FIVE_SECONDS);
+ mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), TIMEOUT);
+
+ // NOTE: Must be the "target" context, else security checks in content provider will fail.
+ mContext = instrumentation.getTargetContext();
+ mResolver = mContext.getContentResolver();
+
+ mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
+ mDocsHelper = new DocumentsProviderHelper(DEFAULT_AUTHORITY, mClient);
// Launch app.
- mContext = getInstrumentation().getContext();
Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(TARGET_PKG);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
mContext.startActivity(intent);
// Wait for the app to appear.
- mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), FIVE_SECONDS);
+ mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), TIMEOUT);
+ mDevice.waitForIdle();
+
+ mBot = new UiBot(mDevice, TIMEOUT);
+
+ resetStorage(); // Just incase a test failed and tearDown didn't happen.
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ Log.d(TAG, "Resetting storage from setUp");
+ resetStorage();
+ mClient.release();
+ }
+
+ private void resetStorage() throws RemoteException {
+ mClient.call("clear", null, null);
+ // TODO: Would be nice to have an event to wait on here.
mDevice.waitForIdle();
+ }
+
+ private void initTestFiles() throws RemoteException {
+ mRoot_0 = mDocsHelper.getRoot(ROOT_0_ID);
+ mRoot_1 = mDocsHelper.getRoot(ROOT_1_ID);
+
+ mDocsHelper.createDocument(mRoot_0, "text/plain", "file0.log");
+ mDocsHelper.createDocument(mRoot_0, "image/png", "file1.png");
+ mDocsHelper.createDocument(mRoot_0, "text/csv", "file2.csv");
+
+ mDocsHelper.createDocument(mRoot_1, "text/plain", "anotherFile0.log");
+ mDocsHelper.createDocument(mRoot_1, "text/plain", "poodles.text");
+ }
- mBar = new ActionBar();
+ public void testRootsListed() throws Exception {
+ initTestFiles();
+
+ mBot.openRoot(ROOT_0_ID);
+
+ // Should also have Drive, but that requires pre-configuration of devices
+ // We omit for now.
+ mBot.assertHasRoots(
+ "Images",
+ "Videos",
+ "Audio",
+ "Downloads",
+ ROOT_0_ID,
+ ROOT_1_ID);
+ }
+
+ public void testFilesListed() throws Exception {
+ initTestFiles();
+
+ mBot.openRoot(ROOT_0_ID);
+ mBot.assertHasDocuments("file0.log", "file1.png", "file2.csv");
}
- public void testSwitchMode() throws Exception {
- UiObject2 mode = mBar.gridMode(100);
- if (mode != null) {
- mode.click();
- assertNotNull(mBar.listMode(ONE_SECOND));
- } else {
- mBar.listMode(100).click();
- assertNotNull(mBar.gridMode(ONE_SECOND));
- }
+ public void testFilesList_LiveUpdate() throws Exception {
+ initTestFiles();
+
+ mBot.openRoot(ROOT_0_ID);
+ mDocsHelper.createDocument(mRoot_0, "yummers/sandwich", "Ham & Cheese.sandwich");
+ mBot.assertHasDocuments("file0.log", "file1.png", "file2.csv", "Ham & Cheese.sandwich");
}
- private class ActionBar {
-
- public UiObject2 gridMode(int timeout) {
- // Note that we're using By.desc rather than By.res, because of b/25285770
- BySelector selector = By.desc("Grid view");
- if (timeout > 0) {
- mDevice.wait(Until.findObject(selector), timeout);
- }
- return mDevice.findObject(selector);
- }
-
- public UiObject2 listMode(int timeout) {
- // Note that we're using By.desc rather than By.res, because of b/25285770
- BySelector selector = By.desc("List view");
- if (timeout > 0) {
- mDevice.wait(Until.findObject(selector), timeout);
- }
- return mDevice.findObject(selector);
- }
+ public void testDeleteDocument() throws Exception {
+ initTestFiles();
+
+ mBot.openRoot(ROOT_0_ID);
+
+ mBot.clickDocument("file1.png");
+ mDevice.waitForIdle();
+ mBot.menuDelete().click();
+
+ mBot.waitForDeleteSnackbar();
+ assertFalse(mBot.hasDocuments("file1.png"));
+
+ mBot.waitForDeleteSnackbarGone();
+ assertFalse(mBot.hasDocuments("file1.png"));
+
+ // Now delete from another root.
+ mBot.openRoot(ROOT_1_ID);
+
+ mBot.clickDocument("poodles.text");
+ mDevice.waitForIdle();
+ mBot.menuDelete().click();
+
+ mBot.waitForDeleteSnackbar();
+ assertFalse(mBot.hasDocuments("poodles.text"));
+
+ mBot.waitForDeleteSnackbarGone();
+ assertFalse(mBot.hasDocuments("poodles.text"));
}
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
index 6a2e03a3b809..2d42ddc4e6b5 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
@@ -50,12 +50,17 @@ import java.util.HashMap;
import java.util.Map;
public class StubProvider extends DocumentsProvider {
+
+ public static final String DEFAULT_AUTHORITY = "com.android.documentsui.stubprovider";
+ public static final String ROOT_0_ID = "TEST_ROOT_0";
+ public static final String ROOT_1_ID = "TEST_ROOT_1";
+
+ private static final String TAG = "StubProvider";
private static final String EXTRA_SIZE = "com.android.documentsui.stubprovider.SIZE";
private static final String EXTRA_ROOT = "com.android.documentsui.stubprovider.ROOT";
private static final String STORAGE_SIZE_KEY = "documentsui.stubprovider.size";
- private static int DEFAULT_SIZE = 1024 * 1024; // 1 MB.
- private static final String TAG = "StubProvider";
- private static final String MY_ROOT_ID = "sd0";
+ private static int DEFAULT_ROOT_SIZE = 1024 * 1024 * 100; // 100 MB.
+
private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID,
Root.COLUMN_AVAILABLE_BYTES
@@ -65,11 +70,12 @@ public class StubProvider extends DocumentsProvider {
Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
};
- private HashMap<String, StubDocument> mStorage = new HashMap<String, StubDocument>();
- private Object mWriteLock = new Object();
- private String mAuthority;
+ private final Map<String, StubDocument> mStorage = new HashMap<>();
+ private final Map<String, RootInfo> mRoots = new HashMap<>();
+ private final Object mWriteLock = new Object();
+
+ private String mAuthority = DEFAULT_AUTHORITY;
private SharedPreferences mPrefs;
- private Map<String, RootInfo> mRoots;
private String mSimulateReadErrors;
@Override
@@ -86,20 +92,18 @@ public class StubProvider extends DocumentsProvider {
@VisibleForTesting
public void clearCacheAndBuildRoots() {
- final File cacheDir = getContext().getCacheDir();
- removeRecursively(cacheDir);
+ Log.d(TAG, "Resetting storage.");
+ removeChildrenRecursively(getContext().getCacheDir());
mStorage.clear();
mPrefs = getContext().getSharedPreferences(
"com.android.documentsui.stubprovider.preferences", Context.MODE_PRIVATE);
Collection<String> rootIds = mPrefs.getStringSet("roots", null);
if (rootIds == null) {
- rootIds = Arrays.asList(new String[] {
- "sd0", "sd1"
- });
+ rootIds = Arrays.asList(new String[] { ROOT_0_ID, ROOT_1_ID });
}
- // Create new roots.
- mRoots = new HashMap<>();
+
+ mRoots.clear();
for (String rootId : rootIds) {
final RootInfo rootInfo = new RootInfo(rootId, getSize(rootId));
mRoots.put(rootId, rootInfo);
@@ -111,7 +115,7 @@ public class StubProvider extends DocumentsProvider {
*/
private long getSize(String rootId) {
final String key = STORAGE_SIZE_KEY + "." + rootId;
- return mPrefs.getLong(key, DEFAULT_SIZE);
+ return mPrefs.getLong(key, DEFAULT_ROOT_SIZE);
}
@Override
@@ -125,7 +129,7 @@ public class StubProvider extends DocumentsProvider {
row.add(Root.COLUMN_ROOT_ID, id);
row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD);
row.add(Root.COLUMN_TITLE, id);
- row.add(Root.COLUMN_DOCUMENT_ID, info.rootDocument.documentId);
+ row.add(Root.COLUMN_DOCUMENT_ID, info.document.documentId);
row.add(Root.COLUMN_AVAILABLE_BYTES, info.getRemainingCapacity());
}
return result;
@@ -152,28 +156,48 @@ public class StubProvider extends DocumentsProvider {
}
@Override
- public String createDocument(String parentDocumentId, String mimeType, String displayName)
+ public String createDocument(String parentId, String mimeType, String displayName)
throws FileNotFoundException {
- final StubDocument parentDocument = mStorage.get(parentDocumentId);
- if (parentDocument == null || !parentDocument.file.isDirectory()) {
- throw new FileNotFoundException();
+
+ final StubDocument parent = mStorage.get(parentId);
+ if (parent == null) {
+ throw new IllegalArgumentException(
+ "Can't create file " + displayName + " in null parent.");
+ }
+ if (!parent.file.isDirectory()) {
+ throw new IllegalArgumentException(
+ "Can't create file " + displayName + " inside non-directory parent "
+ + parent.file.getName());
}
- final File file = new File(parentDocument.file, displayName);
+
+ final File file = new File(parent.file, displayName);
+ if (file.exists()) {
+ throw new FileNotFoundException(
+ "Duplicate file names not supported for " + file);
+ }
+
if (mimeType.equals(Document.MIME_TYPE_DIR)) {
if (!file.mkdirs()) {
- throw new FileNotFoundException();
+ throw new FileNotFoundException(
+ "Failed to create directory(s): " + file);
}
+ Log.i(TAG, "Created new directory: " + file);
} else {
+ boolean created = false;
try {
- if (!file.createNewFile()) {
- throw new IllegalStateException("The file " + file.getPath() + " already exists");
- }
+ created = file.createNewFile();
} catch (IOException e) {
- throw new FileNotFoundException();
+ // We'll throw an FNF exception later :)
+ Log.e(TAG, "createnewFile operation failed for file: " + file, e);
+ }
+ if (!created) {
+ throw new FileNotFoundException(
+ "createNewFile operation failed for: " + file);
}
+ Log.i(TAG, "Created new file: " + file);
}
- final StubDocument document = new StubDocument(file, mimeType, parentDocument);
+ final StubDocument document = new StubDocument(file, mimeType, parent);
Log.d(TAG, "Created document " + document.documentId);
notifyParentChanged(document.parentId);
getContext().getContentResolver().notifyChange(
@@ -349,7 +373,7 @@ public class StubProvider extends DocumentsProvider {
private void configure(String arg, Bundle extras) {
Log.d(TAG, "Configure " + arg);
- String rootName = extras.getString(EXTRA_ROOT, MY_ROOT_ID);
+ String rootName = extras.getString(EXTRA_ROOT, ROOT_0_ID);
long rootSize = extras.getLong(EXTRA_SIZE, 1) * 1024 * 1024;
setSize(rootName, rootSize);
}
@@ -379,10 +403,10 @@ public class StubProvider extends DocumentsProvider {
row.add(Document.COLUMN_LAST_MODIFIED, document.file.lastModified());
}
- private void removeRecursively(File file) {
+ private void removeChildrenRecursively(File file) {
for (File childFile : file.listFiles()) {
if (childFile.isDirectory()) {
- removeRecursively(childFile);
+ removeChildrenRecursively(childFile);
}
childFile.delete();
}
@@ -411,8 +435,8 @@ public class StubProvider extends DocumentsProvider {
@VisibleForTesting
public Uri createFile(String rootId, String path, String mimeType, byte[] content)
throws FileNotFoundException, IOException {
- Log.d(TAG, "Creating file " + rootId + ":" + path);
- StubDocument root = mRoots.get(rootId).rootDocument;
+ Log.d(TAG, "Creating test file " + rootId + ":" + path);
+ StubDocument root = mRoots.get(rootId).document;
if (root == null) {
throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
}
@@ -445,7 +469,7 @@ public class StubProvider extends DocumentsProvider {
@VisibleForTesting
public File getFile(String rootId, String path) throws FileNotFoundException {
- StubDocument root = mRoots.get(rootId).rootDocument;
+ StubDocument root = mRoots.get(rootId).document;
if (root == null) {
throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
}
@@ -461,7 +485,7 @@ public class StubProvider extends DocumentsProvider {
final class RootInfo {
public final String name;
- public final StubDocument rootDocument;
+ public final StubDocument document;
public long capacity;
public long size;
@@ -469,9 +493,11 @@ public class StubProvider extends DocumentsProvider {
this.name = name;
this.capacity = 1024 * 1024;
// Make a subdir in the cache dir for each root.
- File rootDir = new File(getContext().getCacheDir(), name);
- rootDir.mkdir();
- this.rootDocument = new StubDocument(rootDir, Document.MIME_TYPE_DIR, this);
+ File file = new File(getContext().getCacheDir(), name);
+ if (file.mkdir()) {
+ Log.i(TAG, "Created new root directory @ " + file.getPath());
+ }
+ this.document = new StubDocument(file, Document.MIME_TYPE_DIR, this);
this.capacity = capacity;
this.size = 0;
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java b/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java
new file mode 100644
index 000000000000..5c09794a3e28
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/UiBot.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.documentsui;
+
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiScrollable;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * A test helper class that provides support for controlling DocumentsUI activities
+ * programmatically, and making assertions against the state of the UI.
+ */
+class UiBot {
+
+ private static final String TAG = "UiBot";
+
+ private static final BySelector SNACK_DELETE =
+ By.desc(Pattern.compile("^Deleting [0-9]+ file.+"));
+
+ private UiDevice mDevice;
+ private int mTimeout;
+
+ public UiBot(UiDevice device, int timeout) {
+ mDevice = device;
+ mTimeout = timeout;
+ }
+
+ UiObject findRoot(String label) throws UiObjectNotFoundException {
+ final UiSelector rootsList = new UiSelector().resourceId(
+ "com.android.documentsui:id/container_roots").childSelector(
+ new UiSelector().resourceId("android:id/list"));
+
+ // We might need to expand drawer if not visible
+ if (!new UiObject(rootsList).waitForExists(mTimeout)) {
+ Log.d(TAG, "Failed to find roots list; trying to expand");
+ final UiSelector hamburger = new UiSelector().resourceId(
+ "com.android.documentsui:id/toolbar").childSelector(
+ new UiSelector().className("android.widget.ImageButton").clickable(true));
+ new UiObject(hamburger).click();
+ }
+
+ // Wait for the first list item to appear
+ new UiObject(rootsList.childSelector(new UiSelector())).waitForExists(mTimeout);
+
+ // Now scroll around to find our item
+ new UiScrollable(rootsList).scrollIntoView(new UiSelector().text(label));
+ return new UiObject(rootsList.childSelector(new UiSelector().text(label)));
+ }
+
+ void openRoot(String label) throws UiObjectNotFoundException {
+ findRoot(label).click();
+ mDevice.waitForIdle();
+ }
+
+ void assertHasRoots(String... labels) throws UiObjectNotFoundException {
+ List<String> missing = new ArrayList<>();
+ for (String label : labels) {
+ if (!findRoot(label).exists()) {
+ missing.add(label);
+ }
+ }
+ if (!missing.isEmpty()) {
+ Assert.fail(
+ "Expected roots " + Arrays.asList(labels) + ", but missing " + missing);
+ }
+ }
+
+ UiObject findDocument(String label) throws UiObjectNotFoundException {
+ final UiSelector docList = new UiSelector().resourceId(
+ "com.android.documentsui:id/container_directory").childSelector(
+ new UiSelector().resourceId("com.android.documentsui:id/list"));
+
+ // Wait for the first list item to appear
+ new UiObject(docList.childSelector(new UiSelector())).waitForExists(mTimeout);
+
+ // new UiScrollable(docList).scrollIntoView(new UiSelector().text(label));
+ return mDevice.findObject(docList.childSelector(new UiSelector().text(label)));
+ }
+
+ boolean hasDocuments(String... labels) throws UiObjectNotFoundException {
+ for (String label : labels) {
+ if (!findDocument(label).exists()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void assertHasDocuments(String... labels) throws UiObjectNotFoundException {
+ List<String> missing = new ArrayList<>();
+ for (String label : labels) {
+ if (!findDocument(label).exists()) {
+ missing.add(label);
+ }
+ }
+ if (!missing.isEmpty()) {
+ Assert.fail(
+ "Expected documents " + Arrays.asList(labels) + ", but missing " + missing);
+ }
+ }
+
+ void clickDocument(String label) throws UiObjectNotFoundException {
+ findDocument(label).click();
+ }
+
+ void waitForDeleteSnackbar() {
+ mDevice.wait(Until.findObject(SNACK_DELETE), mTimeout);
+ }
+
+ void waitForDeleteSnackbarGone() {
+ // wait a little longer for snackbar to go away, as it disappears after a timeout.
+ mDevice.wait(Until.gone(SNACK_DELETE), mTimeout * 2);
+ }
+
+ void switchViewMode() {
+ UiObject2 mode = menuGridMode();
+ if (mode != null) {
+ mode.click();
+ } else {
+ menuListMode().click();
+ }
+ }
+
+ UiObject2 menuGridMode() {
+ // Note that we're using By.desc rather than By.res, because of b/25285770
+ return find(By.desc("Grid view"));
+ }
+
+ UiObject2 menuListMode() {
+ // Note that we're using By.desc rather than By.res, because of b/25285770
+ return find(By.desc("List view"));
+ }
+
+ UiObject2 menuDelete() {
+ return find(By.res("com.android.documentsui:id/menu_delete"));
+ }
+
+ private UiObject2 find(BySelector selector) {
+ mDevice.wait(Until.findObject(selector), mTimeout);
+ return mDevice.findObject(selector);
+ }
+}
diff --git a/packages/Keyguard/res/values-hu/strings.xml b/packages/Keyguard/res/values-hu/strings.xml
index 6f8f189bf39f..55cf24f9923a 100644
--- a/packages/Keyguard/res/values-hu/strings.xml
+++ b/packages/Keyguard/res/values-hu/strings.xml
@@ -24,11 +24,11 @@
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Írja be a PIN kódot"</string>
<string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Írja be a SIM kártya PUK kódját, majd az új PIN kódot"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM kártya PUK kódja"</string>
- <string name="keyguard_password_enter_pin_prompt" msgid="3201151840570492538">"Új PIN kód a SIM kártyához"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="3201151840570492538">"Új PIN-kód a SIM kártyához"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"Érintsen jelszó megadásához"</font></string>
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"A feloldáshoz írja be a jelszót"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Feloldáshoz írja be a PIN kódot"</string>
- <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Helytelen PIN kód."</string>
+ <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Helytelen PIN-kód."</string>
<string name="keyguard_charged" msgid="3272223906073492454">"Feltöltve"</string>
<string name="keyguard_plugged_in" msgid="9087497435553252863">"Töltés"</string>
<string name="keyguard_plugged_in_charging_fast" msgid="6671162730167305479">"Gyors töltés folyamatban"</string>
@@ -51,8 +51,8 @@
<string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Feloldás jelszóval"</string>
<string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mintaterület"</string>
<string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Csúsztatási terület"</string>
- <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN kód területe"</string>
- <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN kód területe"</string>
+ <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-kód területe"</string>
+ <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN-kód területe"</string>
<string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK kód területe"</string>
<string name="keyguard_accessibility_next_alarm" msgid="7269583073750518672">"A következő riasztás beállított ideje: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
<string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Delete"</string>
@@ -60,7 +60,7 @@
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Elfelejtett minta"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"Helytelen minta"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"Helytelen jelszó"</string>
- <string name="kg_wrong_pin" msgid="1131306510833563801">"Helytelen PIN kód"</string>
+ <string name="kg_wrong_pin" msgid="1131306510833563801">"Helytelen PIN-kód"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Próbálkozzon újra <xliff:g id="NUMBER">%d</xliff:g> másodperc múlva."</string>
<string name="kg_pattern_instructions" msgid="398978611683075868">"Rajzolja le a mintát"</string>
<string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Adja meg a SIM kártya PIN kódját"</string>
@@ -69,8 +69,8 @@
<string name="kg_password_instructions" msgid="5753646556186936819">"Írja be a jelszót"</string>
<string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"A SIM kártya le van tiltva. A folytatáshoz adja meg a PUK kódot. A részletekért vegye fel a kapcsolatot szolgáltatójával."</string>
<string name="kg_puk_enter_puk_hint_multi" msgid="363822494559783025">"A(z) „<xliff:g id="CARRIER">%1$s</xliff:g>” SIM kártyát a rendszer letiltotta. A folytatáshoz adja meg a PUK kódot. A részletekért vegye a fel a kapcsolatot szolgáltatójával."</string>
- <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Kívánt PIN kód megadása"</string>
- <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Kívánt PIN kód megerősítése"</string>
+ <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Kívánt PIN-kód megadása"</string>
+ <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Kívánt PIN-kód megerősítése"</string>
<string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM kártya feloldása..."</string>
<string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4–8 számjegyű PIN kódot írjon be."</string>
<string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"A PUK kód legalább 8 számjegyből kell, hogy álljon."</string>
@@ -94,7 +94,7 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4951507352869831265">"<xliff:g id="NUMBER">%d</xliff:g> alkalommal próbálkozott sikertelenül a telefon zárolásának feloldásával. A rendszer eltávolítja munkahelyi profilját, és összes profiladata törlődik."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a táblagépét.\n\n Kérjük, próbálja újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"<xliff:g id="NUMBER_0">%d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a telefonját.\n\n Kérjük, próbálja újra <xliff:g id="NUMBER_2">%d</xliff:g> másodperc múlva."</string>
- <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Helytelen PIN kód a SIM kártyához; vegye fel a kapcsolatot szolgáltatójával az eszköz feloldásához."</string>
+ <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"Helytelen PIN-kód a SIM kártyához; vegye fel a kapcsolatot szolgáltatójával az eszköz feloldásához."</string>
<plurals name="kg_password_wrong_pin_code" formatted="false" msgid="6721575017538162249">
<item quantity="other">A SIM kártya PIN kódja helytelen. <xliff:g id="NUMBER_1">%d</xliff:g> próbálkozás maradt.</item>
<item quantity="one">A SIM kártya PIN kódja helytelen. <xliff:g id="NUMBER_0">%d</xliff:g> próbálkozás maradt. Utána a szolgáltatótól kell feloldást kérnie.</item>
@@ -114,7 +114,7 @@
<string name="kg_prompt_reason_restart_pin" msgid="994878216570694974">"Ha újraindítja az eszközt, meg kell adnia a PIN kódot."</string>
<string name="kg_prompt_reason_restart_password" msgid="2375742919528461664">"Ha újraindítja az eszközt, meg kell adnia a jelszót."</string>
<string name="kg_prompt_reason_timeout_pattern" msgid="8930047492617900785">"Minta szükséges a nagyobb biztonság érdekében."</string>
- <string name="kg_prompt_reason_timeout_pin" msgid="7470468607947726377">"PIN kód szükséges a nagyobb biztonság érdekében."</string>
+ <string name="kg_prompt_reason_timeout_pin" msgid="7470468607947726377">"PIN-kód szükséges a nagyobb biztonság érdekében."</string>
<string name="kg_prompt_reason_timeout_password" msgid="1177412542773936957">"Jelszó szükséges a nagyobb biztonság érdekében."</string>
<string name="kg_prompt_reason_switch_profiles_pattern" msgid="3802056699323773969">"Ha vált a profilok között, meg kell adnia a mintát."</string>
<string name="kg_prompt_reason_switch_profiles_pin" msgid="8108020184731052246">"Ha vált a profilok között, meg kell adnia a PIN kódot."</string>
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 05343136cca7..8568da0fb37b 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -84,8 +84,7 @@ class MtpDatabase {
DocumentsContract.Document.COLUMN_DOCUMENT_ID + " = ?";
private static final String SELECTION_ROOT_DOCUMENTS =
COLUMN_DEVICE_ID + " = ? AND " + COLUMN_PARENT_DOCUMENT_ID + " IS NULL";
- private static final String SELECTION_ROOT_DOCUMENTS_WITH_STATE =
- SELECTION_ROOT_DOCUMENTS + " AND " + COLUMN_ROW_STATE + " = ?";
+ private static final String SELECTION_CHILD_DOCUMENTS = COLUMN_PARENT_DOCUMENT_ID + " = ?";
static class ParentNotFoundException extends Exception {}
@@ -136,7 +135,7 @@ class MtpDatabase {
}
@VisibleForTesting
- Cursor queryChildDocuments(String[] columnNames) {
+ Cursor queryRootDocuments(String[] columnNames) {
return database.query(
TABLE_DOCUMENTS,
columnNames,
@@ -159,84 +158,27 @@ class MtpDatabase {
null);
}
- /**
- * Puts the roots into the database.
- * If the database found another unmapped document that shares the same name with the root,
- * the document may be merged into the unmapped document. In that case, the database marks the
- * root as 'mapping' and wait for {@link #resolveRootDocuments(int)} is invoked.
- * @param deviceId Device ID of roots.
- * @param resources Resources used to get localized root name.
- * @param roots Roots added to the database.
- */
@VisibleForTesting
void putRootDocuments(int deviceId, Resources resources, MtpRoot[] roots) {
- database.beginTransaction();
- try {
- // Add roots to database.
- final ContentValues values = new ContentValues();
- for (int i = 0; i < roots.length; i++) {
- getRootDocumentValues(values, resources, roots[i]);
- final String displayName =
- values.getAsString(DocumentsContract.Document.COLUMN_DISPLAY_NAME);
- final long numUnmapped = DatabaseUtils.queryNumEntries(
- database,
- TABLE_DOCUMENTS,
- SELECTION_ROOT_DOCUMENTS_WITH_STATE + " AND " +
- DocumentsContract.Document.COLUMN_DISPLAY_NAME + " = ?",
- strings(deviceId, ROW_STATE_UNMAPPED, displayName));
- if (numUnmapped != 0) {
- values.put(COLUMN_ROW_STATE, ROW_STATE_MAPPING);
- }
- database.insert(TABLE_DOCUMENTS, null, values);
+ final ContentValues[] valuesList = new ContentValues[roots.length];
+ for (int i = 0; i < roots.length; i++) {
+ if (roots[i].mDeviceId != deviceId) {
+ throw new IllegalArgumentException();
}
- database.setTransactionSuccessful();
- } finally {
- database.endTransaction();
+ valuesList[i] = new ContentValues();
+ getRootDocumentValues(valuesList[i], resources, roots[i]);
}
+ putDocuments(valuesList, SELECTION_ROOT_DOCUMENTS, Integer.toString(deviceId));
}
@VisibleForTesting
- void putDocument(int deviceId, MtpObjectInfo info) throws Exception {
- database.beginTransaction();
- try {
- final String mimeType = CursorHelper.formatTypeToMimeType(info.getFormat());
-
- int flag = 0;
- if (info.getProtectionStatus() == 0) {
- flag |= DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
- DocumentsContract.Document.FLAG_SUPPORTS_WRITE;
- if (mimeType == DocumentsContract.Document.MIME_TYPE_DIR) {
- flag |= DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE;
- }
- }
- if (info.getThumbCompressedSize() > 0) {
- flag |= DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL;
- }
-
- final ContentValues values = new ContentValues();
- values.put(COLUMN_DEVICE_ID, deviceId);
- values.put(COLUMN_STORAGE_ID, info.getStorageId());
- values.put(COLUMN_OBJECT_HANDLE, info.getObjectHandle());
- // TODO: Specify correct document ID.
- values.putNull(COLUMN_PARENT_DOCUMENT_ID);
- values.put(COLUMN_ROW_STATE, ROW_STATE_MAPPED);
- values.put(Document.COLUMN_MIME_TYPE, mimeType);
- values.put(Document.COLUMN_DISPLAY_NAME, info.getName());
- values.putNull(Document.COLUMN_SUMMARY);
- values.put(
- Document.COLUMN_LAST_MODIFIED,
- info.getDateModified() != 0 ? info.getDateModified() : null);
- values.putNull(Document.COLUMN_ICON);
- values.put(Document.COLUMN_FLAGS, flag);
- values.put(Document.COLUMN_SIZE, info.getCompressedSize());
- if (database.insert(TABLE_DOCUMENTS, null, values) == -1) {
- throw new Exception("Failed to add document.");
- }
-
- database.setTransactionSuccessful();
- } finally {
- database.endTransaction();
+ void putChildDocuments(int deviceId, String parentId, MtpObjectInfo[] documents) {
+ final ContentValues[] valuesList = new ContentValues[documents.length];
+ for (int i = 0; i < documents.length; i++) {
+ valuesList[i] = new ContentValues();
+ getChildDocumentValues(valuesList[i], deviceId, parentId, documents[i]);
}
+ putDocuments(valuesList, SELECTION_CHILD_DOCUMENTS, parentId);
}
/**
@@ -261,15 +203,59 @@ class MtpDatabase {
}
}
+ @VisibleForTesting
+ void resolveRootDocuments(int deviceId) {
+ resolveDocuments(SELECTION_ROOT_DOCUMENTS, Integer.toString(deviceId));
+ }
+
+ @VisibleForTesting
+ void resolveChildDocuments(String parentId) {
+ resolveDocuments(SELECTION_CHILD_DOCUMENTS, parentId);
+ }
+
+ /**
+ * Puts the documents into the database.
+ * If the database found another unmapped document that shares the same name and parent,
+ * the document may be merged into the unmapped document. In that case, the database marks the
+ * root as 'mapping' and wait for {@link #resolveRootDocuments(int)} is invoked.
+ * @param valuesList Values that are stored in the database.
+ * @param selection SQL where closure to select rows that shares the same parent.
+ * @param arg Argument for selection SQL.
+ */
+ private void putDocuments(ContentValues[] valuesList, String selection, String arg) {
+ database.beginTransaction();
+ try {
+ for (final ContentValues values : valuesList) {
+ final String displayName =
+ values.getAsString(DocumentsContract.Document.COLUMN_DISPLAY_NAME);
+ final long numUnmapped = DatabaseUtils.queryNumEntries(
+ database,
+ TABLE_DOCUMENTS,
+ selection + " AND " +
+ COLUMN_ROW_STATE + " = ? AND " +
+ DocumentsContract.Document.COLUMN_DISPLAY_NAME + " = ?",
+ strings(arg, ROW_STATE_UNMAPPED, displayName));
+ if (numUnmapped != 0) {
+ values.put(COLUMN_ROW_STATE, ROW_STATE_MAPPING);
+ }
+ database.insert(TABLE_DOCUMENTS, null, values);
+ }
+
+ database.setTransactionSuccessful();
+ } finally {
+ database.endTransaction();
+ }
+ }
+
/**
* Maps 'unmapped' document and 'mapping' document that don't have document but shares the same
* name.
* If the database does not find corresponding 'mapping' document, it just removes 'unmapped'
* document from the database.
- * @param deviceId Device ID of roots which the method tries to resolve.
+ * @param selection Query to select rows for resolving.
+ * @param arg Argument for selection SQL.
*/
- @VisibleForTesting
- void resolveRootDocuments(int deviceId) {
+ private void resolveDocuments(String selection, String arg) {
database.beginTransaction();
try {
// Get 1-to-1 mapping of unmapped document and mapping document.
@@ -290,8 +276,8 @@ class MtpDatabase {
"group_concat(" + unmappedIdQuery + ")",
"group_concat(" + mappingIdQuery + ")"
},
- SELECTION_ROOT_DOCUMENTS,
- strings(deviceId),
+ selection,
+ strings(arg),
DocumentsContract.Document.COLUMN_DISPLAY_NAME,
"count(" + unmappedIdQuery + ") = 1 AND count(" + mappingIdQuery + ") = 1",
null);
@@ -335,8 +321,8 @@ class MtpDatabase {
// Delete all unmapped rows that cannot be mapped.
database.delete(
TABLE_DOCUMENTS,
- SELECTION_ROOT_DOCUMENTS_WITH_STATE,
- strings(deviceId, ROW_STATE_UNMAPPED));
+ COLUMN_ROW_STATE + " = ? AND " + selection,
+ strings(ROW_STATE_UNMAPPED, arg));
// The database cannot find old document ID for the mapping rows.
// Turn the all mapping rows into mapped state, which means the rows become to be
@@ -346,8 +332,8 @@ class MtpDatabase {
database.update(
TABLE_DOCUMENTS,
values,
- SELECTION_ROOT_DOCUMENTS_WITH_STATE,
- strings(deviceId, ROW_STATE_MAPPING));
+ COLUMN_ROW_STATE + " = ? AND " + selection,
+ strings(ROW_STATE_MAPPING, arg));
database.setTransactionSuccessful();
} finally {
database.endTransaction();
@@ -379,6 +365,44 @@ class MtpDatabase {
}
/**
+ * Gets {@link ContentValues} for the given MTP object.
+ * @param values {@link ContentValues} that receives values.
+ * @param deviceId Device ID of the object.
+ * @param parentId Parent document ID of the object.
+ * @param info MTP object info.
+ */
+ private void getChildDocumentValues(
+ ContentValues values, int deviceId, String parentId, MtpObjectInfo info) {
+ values.clear();
+ final String mimeType = CursorHelper.formatTypeToMimeType(info.getFormat());
+ int flag = 0;
+ if (info.getProtectionStatus() == 0) {
+ flag |= DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
+ DocumentsContract.Document.FLAG_SUPPORTS_WRITE;
+ if (mimeType == DocumentsContract.Document.MIME_TYPE_DIR) {
+ flag |= DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE;
+ }
+ }
+ if (info.getThumbCompressedSize() > 0) {
+ flag |= DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL;
+ }
+ values.put(COLUMN_DEVICE_ID, deviceId);
+ values.put(COLUMN_STORAGE_ID, info.getStorageId());
+ values.put(COLUMN_OBJECT_HANDLE, info.getObjectHandle());
+ values.put(COLUMN_PARENT_DOCUMENT_ID, parentId);
+ values.put(COLUMN_ROW_STATE, ROW_STATE_MAPPED);
+ values.put(Document.COLUMN_MIME_TYPE, mimeType);
+ values.put(Document.COLUMN_DISPLAY_NAME, info.getName());
+ values.putNull(Document.COLUMN_SUMMARY);
+ values.put(
+ Document.COLUMN_LAST_MODIFIED,
+ info.getDateModified() != 0 ? info.getDateModified() : null);
+ values.putNull(Document.COLUMN_ICON);
+ values.put(Document.COLUMN_FLAGS, flag);
+ values.put(Document.COLUMN_SIZE, info.getCompressedSize());
+ }
+
+ /**
* Converts values into string array.
* @param args Values converted into string array.
* @return String array.
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index e7d84815dce3..7bc9972ece3d 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -46,7 +46,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
MtpDatabase.deleteDatabase(getContext());
}
- public void testPutRootDocument() throws Exception {
+ public void testPutRootDocuments() throws Exception {
final MtpDatabase database = new MtpDatabase(getContext());
database.putRootDocuments(0, resources, new MtpRoot[] {
new MtpRoot(0, 1, "Device", "Storage", 1000, 2000, ""),
@@ -54,7 +54,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
new MtpRoot(0, 3, "Device", "/@#%&<>Storage", 1000, 2000,"")
});
- final Cursor cursor = database.queryChildDocuments(COLUMN_NAMES);
+ final Cursor cursor = database.queryRootDocuments(COLUMN_NAMES);
assertEquals(3, cursor.getCount());
cursor.moveToNext();
@@ -81,25 +81,34 @@ public class MtpDatabaseTest extends AndroidTestCase {
cursor.close();
}
- public void testPutDocument() throws Exception {
- final MtpDatabase database = new MtpDatabase(getContext());
+ private MtpObjectInfo createDocument(int objectHandle, String name, int format, int size) {
final MtpObjectInfo.Builder builder = new MtpObjectInfo.Builder();
- builder.setObjectHandle(100);
- builder.setName("test.txt");
- builder.setStorageId(5);
- builder.setFormat(MtpConstants.FORMAT_TEXT);
- builder.setCompressedSize(1000);
- database.putDocument(0, builder.build());
-
- final Cursor cursor = database.queryChildDocuments(COLUMN_NAMES);
- assertEquals(1, cursor.getCount());
+ builder.setObjectHandle(objectHandle);
+ builder.setName(name);
+ builder.setFormat(format);
+ builder.setCompressedSize(size);
+ return builder.build();
+ }
+
+ public void testPutChildDocuments() throws Exception {
+ final MtpDatabase database = new MtpDatabase(getContext());
+
+ database.putChildDocuments(0, "parentId", new MtpObjectInfo[] {
+ createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
+ createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
+ });
+
+ final Cursor cursor = database.queryChildDocuments(COLUMN_NAMES, "parentId");
+ assertEquals(3, cursor.getCount());
+
cursor.moveToNext();
assertEquals("documentId", 1, cursor.getInt(0));
assertEquals("deviceId", 0, cursor.getInt(1));
- assertEquals("storageId", 5, cursor.getInt(2));
+ assertEquals("storageId", 0, cursor.getInt(2));
assertEquals("objectHandle", 100, cursor.getInt(3));
assertEquals("mimeType", "text/plain", cursor.getString(4));
- assertEquals("displayName", "test.txt", cursor.getString(5));
+ assertEquals("displayName", "note.txt", cursor.getString(5));
assertTrue("summary", cursor.isNull(6));
assertTrue("lastModified", cursor.isNull(7));
assertTrue("icon", cursor.isNull(8));
@@ -108,7 +117,43 @@ public class MtpDatabaseTest extends AndroidTestCase {
DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
cursor.getInt(9));
- assertEquals("size", 1000, cursor.getInt(10));
+ assertEquals("size", 1024, cursor.getInt(10));
+
+ cursor.moveToNext();
+ assertEquals("documentId", 2, cursor.getInt(0));
+ assertEquals("deviceId", 0, cursor.getInt(1));
+ assertEquals("storageId", 0, cursor.getInt(2));
+ assertEquals("objectHandle", 101, cursor.getInt(3));
+ assertEquals("mimeType", "image/jpeg", cursor.getString(4));
+ assertEquals("displayName", "image.jpg", cursor.getString(5));
+ assertTrue("summary", cursor.isNull(6));
+ assertTrue("lastModified", cursor.isNull(7));
+ assertTrue("icon", cursor.isNull(8));
+ assertEquals(
+ "flag",
+ DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
+ DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
+ cursor.getInt(9));
+ assertEquals("size", 2 * 1024 * 1024, cursor.getInt(10));
+
+ cursor.moveToNext();
+ assertEquals("documentId", 3, cursor.getInt(0));
+ assertEquals("deviceId", 0, cursor.getInt(1));
+ assertEquals("storageId", 0, cursor.getInt(2));
+ assertEquals("objectHandle", 102, cursor.getInt(3));
+ assertEquals("mimeType", "audio/mpeg", cursor.getString(4));
+ assertEquals("displayName", "music.mp3", cursor.getString(5));
+ assertTrue("summary", cursor.isNull(6));
+ assertTrue("lastModified", cursor.isNull(7));
+ assertTrue("icon", cursor.isNull(8));
+ assertEquals(
+ "flag",
+ DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
+ DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
+ cursor.getInt(9));
+ assertEquals("size", 3 * 1024 * 1024, cursor.getInt(10));
+
+ cursor.close();
}
public void testRestoreIdForRootDocuments() throws Exception {
@@ -124,7 +169,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
});
{
- final Cursor cursor = database.queryChildDocuments(columns);
+ final Cursor cursor = database.queryRootDocuments(columns);
assertEquals(2, cursor.getCount());
cursor.moveToNext();
assertEquals("documentId", 1, cursor.getInt(0));
@@ -140,7 +185,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
database.clearMapping();
{
- final Cursor cursor = database.queryChildDocuments(columns);
+ final Cursor cursor = database.queryRootDocuments(columns);
assertEquals(2, cursor.getCount());
cursor.moveToNext();
assertEquals("documentId", 1, cursor.getInt(0));
@@ -159,7 +204,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
});
{
- final Cursor cursor = database.queryChildDocuments(columns);
+ final Cursor cursor = database.queryRootDocuments(columns);
assertEquals(3, cursor.getCount());
cursor.moveToNext();
assertEquals("documentId", 1, cursor.getInt(0));
@@ -179,7 +224,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
database.resolveRootDocuments(0);
{
- final Cursor cursor = database.queryChildDocuments(columns);
+ final Cursor cursor = database.queryRootDocuments(columns);
assertEquals(2, cursor.getCount());
cursor.moveToNext();
assertEquals("documentId", 1, cursor.getInt(0));
@@ -193,6 +238,78 @@ public class MtpDatabaseTest extends AndroidTestCase {
}
}
+ public void testRestoreIdForChildDocuments() throws Exception {
+ final MtpDatabase database = new MtpDatabase(getContext());
+ final String[] columns = new String[] {
+ DocumentsContract.Document.COLUMN_DOCUMENT_ID,
+ MtpDatabase.COLUMN_OBJECT_HANDLE,
+ DocumentsContract.Document.COLUMN_DISPLAY_NAME
+ };
+ database.putChildDocuments(0, "parentId", new MtpObjectInfo[] {
+ createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ createDocument(101, "image.jpg", MtpConstants.FORMAT_EXIF_JPEG, 2 * 1024 * 1024),
+ createDocument(102, "music.mp3", MtpConstants.FORMAT_MP3, 3 * 1024 * 1024)
+ });
+ database.clearMapping();
+
+ {
+ final Cursor cursor = database.queryChildDocuments(columns, "parentId");
+ assertEquals(3, cursor.getCount());
+
+ cursor.moveToNext();
+ assertEquals("documentId", 1, cursor.getInt(0));
+ assertTrue("objectHandle", cursor.isNull(1));
+ assertEquals("name", "note.txt", cursor.getString(2));
+
+ cursor.moveToNext();
+ assertEquals("documentId", 2, cursor.getInt(0));
+ assertTrue("objectHandle", cursor.isNull(1));
+ assertEquals("name", "image.jpg", cursor.getString(2));
+
+ cursor.moveToNext();
+ assertEquals("documentId", 3, cursor.getInt(0));
+ assertTrue("objectHandle", cursor.isNull(1));
+ assertEquals("name", "music.mp3", cursor.getString(2));
+
+ cursor.close();
+ }
+
+ database.putChildDocuments(0, "parentId", new MtpObjectInfo[] {
+ createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ createDocument(203, "video.mp4", MtpConstants.FORMAT_MP4_CONTAINER, 1024),
+ });
+
+ {
+ final Cursor cursor = database.queryChildDocuments(columns, "parentId");
+ assertEquals(4, cursor.getCount());
+
+ cursor.moveToPosition(3);
+ assertEquals("documentId", 5, cursor.getInt(0));
+ assertEquals("objectHandle", 203, cursor.getInt(1));
+ assertEquals("name", "video.mp4", cursor.getString(2));
+
+ cursor.close();
+ }
+
+ database.resolveChildDocuments("parentId");
+
+ {
+ final Cursor cursor = database.queryChildDocuments(columns, "parentId");
+ assertEquals(2, cursor.getCount());
+
+ cursor.moveToNext();
+ assertEquals("documentId", 1, cursor.getInt(0));
+ assertEquals("objectHandle", 200, cursor.getInt(1));
+ assertEquals("name", "note.txt", cursor.getString(2));
+
+ cursor.moveToNext();
+ assertEquals("documentId", 5, cursor.getInt(0));
+ assertEquals("objectHandle", 203, cursor.getInt(1));
+ assertEquals("name", "video.mp4", cursor.getString(2));
+ cursor.close();
+ }
+ }
+
public void testRestoreIdForDifferentDevices() throws Exception {
final MtpDatabase database = new MtpDatabase(getContext());
final String[] columns = new String[] {
@@ -208,7 +325,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
});
{
- final Cursor cursor = database.queryChildDocuments(columns);
+ final Cursor cursor = database.queryRootDocuments(columns);
assertEquals(2, cursor.getCount());
cursor.moveToNext();
assertEquals("documentId", 1, cursor.getInt(0));
@@ -231,8 +348,9 @@ public class MtpDatabaseTest extends AndroidTestCase {
});
database.resolveRootDocuments(0);
database.resolveRootDocuments(1);
+
{
- final Cursor cursor = database.queryChildDocuments(columns);
+ final Cursor cursor = database.queryRootDocuments(columns);
assertEquals(2, cursor.getCount());
cursor.moveToNext();
assertEquals("documentId", 1, cursor.getInt(0));
@@ -246,6 +364,45 @@ public class MtpDatabaseTest extends AndroidTestCase {
}
}
+ public void testRestoreIdForDifferentParents() throws Exception {
+ final MtpDatabase database = new MtpDatabase(getContext());
+ final String[] columns = new String[] {
+ DocumentsContract.Document.COLUMN_DOCUMENT_ID,
+ MtpDatabase.COLUMN_OBJECT_HANDLE
+ };
+ database.putChildDocuments(0, "parentId1", new MtpObjectInfo[] {
+ createDocument(100, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ });
+ database.putChildDocuments(0, "parentId2", new MtpObjectInfo[] {
+ createDocument(101, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ });
+ database.clearMapping();
+ database.putChildDocuments(0, "parentId1", new MtpObjectInfo[] {
+ createDocument(200, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ });
+ database.putChildDocuments(0, "parentId2", new MtpObjectInfo[] {
+ createDocument(201, "note.txt", MtpConstants.FORMAT_TEXT, 1024),
+ });
+ database.resolveChildDocuments("parentId1");
+
+ {
+ final Cursor cursor = database.queryChildDocuments(columns, "parentId1");
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals("documentId", 1, cursor.getInt(0));
+ assertEquals("objectHandle", 200, cursor.getInt(1));
+ cursor.close();
+ }
+ {
+ final Cursor cursor = database.queryChildDocuments(columns, "parentId2");
+ assertEquals(1, cursor.getCount());
+ cursor.moveToNext();
+ assertEquals("documentId", 2, cursor.getInt(0));
+ assertTrue("objectHandle", cursor.isNull(1));
+ cursor.close();
+ }
+ }
+
public void testClearMtpIdentifierBeforeResolveRootDocuments() {
final MtpDatabase database = new MtpDatabase(getContext());
final String[] columns = new String[] {
@@ -266,7 +423,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
});
database.resolveRootDocuments(0);
{
- final Cursor cursor = database.queryChildDocuments(columns);
+ final Cursor cursor = database.queryRootDocuments(columns);
assertEquals(1, cursor.getCount());
cursor.moveToNext();
assertEquals("documentId", 1, cursor.getInt(0));
@@ -293,7 +450,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
});
database.resolveRootDocuments(0);
{
- final Cursor cursor = database.queryChildDocuments(columns);
+ final Cursor cursor = database.queryRootDocuments(columns);
assertEquals(2, cursor.getCount());
cursor.moveToNext();
assertEquals("documentId", 2, cursor.getInt(0));
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 73c82fdd2198..549c0425b9bb 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Gebruiker: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Sommige verstekke gestel"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Geen verstekke gestel nie"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Teks-na-spraak-instellings"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Teks-na-spraak-uitset"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Spraaktempo"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Spoed waarteen die teks gepraat word"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Taal"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Gebruik stelseltaal"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Taal nie gekies nie"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Stel die taalspesifieke stem vir gesproke teks"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Luister na \'n voorbeeld"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Speel \'n kort demonstrasie van spraaksintese"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Installeer stemdata"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Installeer die stemdata vereis vir spraaksintese"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Hierdie spraaksintese-enjin kan dalk al die teks versamel wat uitgespreek sal word, insluitend persoonlike data soos wagwoorde en kredietkaartnommers. Dit kom van die <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> enjin. Aktiveer die gebruik van hierdie spraaksintese-enjin?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Hierdie taal vereis \'n werkende netwerkverbinding vir teks-na-spraak-uitvoer."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Dit is \'n voorbeeld van spraaksintese"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Verstek taalstatus"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> word ten volle ondersteun"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> vereis netwerkverbinding"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> word nie ondersteun nie"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Instellings vir <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Lanseer enjin-instellings"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Voorkeur-enjin"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Algemeen"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 4e94d8743f64..eebd8196af9b 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"ተጠቃሚ፦ <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"አንዳንድ ነባሪዎ ተዘጋጅተዋል"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"ምንም ነባሪዎች አልተዘጋጁም"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"ፅሁፍ-ወደ-ንግግር ቅንብሮች"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"የፅሁፍ- ወደ- ንግግር ውፅዓት"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">" የንግግር ደረጃ"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"የተነገረበትን ፅሁፍ አፍጥን"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ቋንቋ"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"የስርዓት ቋንቋ ተጠቀም"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"ቋንቋ አልተመረጠም"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"ለሚነገረው ፅሁፍ ቋንቋ-ተኮር ድምፅ አዘጋጅ"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"ምሳሌውን አዳምጥ"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"አጭር የንግግር ልምምድ ማሳያ አጫውት"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"የድምፅ ውሂብ ጫን"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"ለንግግር ልምምድ የሚጠየቀውን የድምፅ ውሂብ ጫን"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"ይህ የንግግር ልምምድ አንቀሳቃሽ የሚነገረውን ፅሁፍ ሁሉ እንደ ይለፍ ቃል እና የዱቤ ካርድ ቁጥሮች፣ የግል ውሂብ ጨምሮ ለመሰብሰብ ይችል ይሆናል። ከ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> አንቀሳቃሽ ይመጣል። የዚህን የንግግር ልምምድ አንቀሳቃሽ አጠቃቀም ይንቃ?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"ይህ ቋንቋ የጽሑፍ-ወደ-ንግግር ውጽዓት እንዲኖረው የሚሰራ የአውታረ መረብ ግንኙነት ያስፈልገዋል።"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"ይህ የተሰራ ንግግር ምሳሌ ነው"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"የነባሪ ቋንቋ ሁኔታ"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> ሙሉ ለሙሉ ይደገፋል"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> የአውታረ መረብ ግንኙነት ያስፈልጋል"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> አይደገፍም"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"የ<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> ቅንብሮች"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"የፍርግም ቅንብሮችን ያስጀምሩ"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"የተመረጠ ፍርግም"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"አጠቃላይ"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 3710f7b285e1..948b37f94e87 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"المستخدم: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"تم تعيين بعض الإعدادات الافتراضية"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"لم يتم تعيين إعدادات افتراضية"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"إعدادات تحويل النص إلى كلام"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"إخراج تحويل النص إلى كلام"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"معدل سرعة الكلام"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"سرعة نطق الكلام"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"اللغة"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"استخدام لغة النظام"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"اللغة غير محددة"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"تعيين الصوت الخاص بلغة النص المنطوق"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"الاستماع إلى مثال"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"تشغيل عرض توضيحي قصير لتجميع الكلام"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"تثبيت البيانات الصوتية"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"تثبيت البيانات الصوتية المطلوبة لتجميع الكلام"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"ربما يمكن لمحرك اصطناع الحديث جمع كل النص التي سيتم نطقه، بما في ذلك البيانات الشخصية مثل كلمات المرور وأرقام بطاقة الائتمان. يتم إحضار ذلك من المحرك <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. هل تريد تمكين استخدام محرك اصطناع الحديث هذا؟"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"تتطلب هذه اللغة اتصال شبكة سليمًا لتحويل النص إلى كلام."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"هذا مثال لتركيب الكلام"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"حالة اللغة الافتراضية"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> متوافقة تمامًا"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> تتطلب اتصالاً بالشبكة"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> غير متوافقة"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"إعدادات <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"تشغيل إعدادات المحرك"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"المحرك المفضل"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"عامة"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml
index 9f46424be1de..e95684376750 100644
--- a/packages/SettingsLib/res/values-az-rAZ/strings.xml
+++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"İstifadəçi: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Bəzi susmaya görələr təyin edilib"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Susmaya görələr təyin edilməyib."</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Mətndən-danışığa parametrləri"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Mətndən-nitqə çıxışı"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Nitq diapazonu"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Mətnin səsləndirilmə sürəti"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Dil"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Sistem dili işlədin"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Dil seçilməyib"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Danışılan oxunulan mətnə dil üçün spesifik səs ayarlayır"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Nümunə dinləyin"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Nitq sintezindən nümunə göstərin"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Səs datasını quraşdırın"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Nitq sintezi üçün səs datası quraşdırın"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Bu nitq sitnez mühərriki danışılan bütün mətni, həmçinin parollarınızı və kredir kart nömrələrinizi toplaya bilər. <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> mühərrikindən gəlir. Nitq sintez mühərriki istifadə olunsun?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Bu dil mətnin nitqə çıxışı üçün şəbəkə bağlantısı tələb edir."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Bu, bir nitq sintez nümunəsidir."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Defolt dil statusu"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> tam dəstəklənir"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> şəbəkə bağlantısı tələb edir"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> dəstəklənmir"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"Yoxlanılır..."</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> üçün ayarlar"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Mühərrik parametrlərini başladın"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Tərcih olunmuş mühərrik"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Ümumi"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"Çox yavaş"</item>
+ <item msgid="4795095314303559268">"Yavaş"</item>
+ <item msgid="8903157781070679765">"Normal"</item>
+ <item msgid="164347302621392996">"Sürətli"</item>
+ <item msgid="5794028588101562009">"Daha sürətli"</item>
+ <item msgid="7163942783888652942">"Çox sürətli"</item>
+ <item msgid="7831712693748700507">"Tez"</item>
+ <item msgid="5194774745031751806">"Çox tez"</item>
+ <item msgid="9085102246155045744">"Ən sürətli"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 5938f1443863..afba42150180 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Потребител: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Зададени са някои стандартни настройки"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Няма зададени стандартни настройки"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Настройки за синтезиран говор"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Синтезиран говор"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Скорост на речта"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Скорост, с която се изговаря текстът"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Език"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Използване на системния език"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Езикът не е избран"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Задава глас за конкретен език за изговорения текст"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Чуйте пример"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Възпроизвеждане на кратка демонстрация на синтезиране на реч"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Инсталиране на гласови данни"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Инсталиране на гласови данни, нужни за синтезиране на реч"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Тази машина за синтезиране на реч може да събира всички изговорено от вас, включително лични данни като пароли и номера на кредитни карти. Тя произлиза от машината <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Искате ли да я активирате?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Този език изисква работеща връзка с мрежата за синтезирания говор."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Това е пример за синтезиране на говор"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Състояние на основния език"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> се поддържа напълно"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"За <xliff:g id="LOCALE">%1$s</xliff:g> се изисква връзка с мрежа"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> не се поддържа"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Настройки за <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Стартиране на настройките на машината"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Предпочитана машина"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Общи"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index 612f68473912..00aeac9bad0b 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"ব্যবহারকারী: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"কিছু ডিফল্ট সেট করা রয়েছে"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"কোনো ডিফল্ট সেট করা নেই"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"পাঠ্য থেকে ভাষ্য আউটপুট সেটিংস"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"লেখিত-থেকে-ভাষ্য"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"ভাষ্য হার"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"যে গতিতে পাঠ্য উচ্চারিত হয়"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ভাষা"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"সিস্টেমের ভাষা ব্যবহার করুন"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"ভাষা নির্বাচন করা নেই"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"কথ্য পাঠ্যের জন্য ভাষা-নির্দিষ্ট ভয়েস সেট করে"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"একটি উদাহরণ শুনুন"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"কথন সংশ্লেষণের উপর একটি ছোট ডেমো প্লে করুন"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"ভয়েস ডেটা ইনস্টল করুন"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"বিবৃতি সংশ্লেষণের জন্য প্রয়োজনীয় ভয়েস ডেটা ইনস্টল করুন"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"এই বিবৃতি সংশ্লেষণ ইঞ্জিন হয়তো পাসওয়ার্ড এবং ক্রেডিট কার্ড নম্বর সহ কথ্য সমস্ত পাঠ্য সংগ্রহ করতে সক্ষম হতে পারে। এটি <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ইঞ্জিন থেকে আসে। এই বিবৃতি সংশ্লেষণ ইঞ্জিন সক্ষম করবেন?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"পাঠ্য থেকে ভাষ্য আউটপুটের জন্য এই ভাষার একটি কাজ করছে এমন নেটওয়ার্ক সংযোগ প্রয়োজন।"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"এটি হল ভাষ্য সংশ্লেষণের একটি উদাহরণ"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"ডিফল্ট ভাষা স্থিতি"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> সম্পূর্ণ সমর্থিত"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> এর নেটওয়ার্ক সংযোগের প্রয়োজন"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> সমর্থিত নয়"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> জন্য সেটিংস"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"ইঞ্জিন সেটিংস লঞ্চ করুন"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"পছন্দের ইঞ্জিন"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"সাধারণ"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 81a7cb985313..9536b7f210a5 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Usuari: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"S\'han definit alguns valors predeterminats"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"No s\'ha definit cap valor predeterminat"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Configuració de síntesi de veu"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Síntesi de veu"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocitat de veu"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocitat de lectura del text"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilitza l\'idioma del sistema"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"No has seleccionat cap idioma"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Defineix la llengua utilitzada per a la síntesi de veu"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Vull escoltar un exemple"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Reprodueix una breu demostració de síntesi de veu"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instal·la dades de veu"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instal·la les dades de veu necessàries per a la síntesi de veu"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Pot ser que aquest motor de síntesi de la parla pugui recopilar tot el text que es dirà en veu alta, incloses les dades personals, com ara les contrasenyes i els números de les targetes de crèdit. Ve del motor <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Voleu activar l\'ús d\'aquest motor de síntesi de la parla?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Aquest idioma requereix una connexió de xarxa activa per a la sortida de síntesi de veu."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Això és un exemple de síntesi de veu"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Estat de l\'idioma predeterminat"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> és totalment compatible"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"Es necessita una connexió de xarxa per a <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> no és compatible"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Configuració de: <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Obre la configuració del motor"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motor preferit"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"General"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 663ed08c6d78..693f954ad365 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Uživatel: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Je nastaveno několik výchozích hodnot"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nejsou nastaveny žádné výchozí hodnoty"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Nastavení převodu textu na řeč"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Převod textu na řeč"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Rychlost řeči"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Rychlost mluveného textu"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Jazyk"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Použít jazyk systému"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nebyl vybrán jazyk"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Nastavení jazyka hlasu pro mluvený text"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Poslechnout příklad"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Přehrát krátkou ukázku syntézy řeči"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Nainstalovat hlasová data"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Nainstalovat hlasová data pro syntézu řeči"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Modul pro syntézu řeči může shromažďovat veškerý mluvený text, včetně osobních dat jako jsou hesla nebo čísla kreditních karet. Je založen na modulu <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Chcete modul pro syntézu řeči aktivovat?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Pro tento jazyk je k převodu textu na hlasový výstup potřeba připojení k síti."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Toto je příklad syntézy řeči"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Stav výchozího jazyka"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"Jazyk <xliff:g id="LOCALE">%1$s</xliff:g> je plně podporován"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"Jazyk <xliff:g id="LOCALE">%1$s</xliff:g> vyžaduje připojení k síti"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Jazyk <xliff:g id="LOCALE">%1$s</xliff:g> není podporován"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Spustit vyhledávač"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Preferovaný modul"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Obecné"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 333ed050df60..3d4c8d42fd48 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Bruger: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Der er angivet nogle standarder"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Der er ikke angivet nogen standarder"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Indstillinger for oplæsning"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Oplæsning"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Talehastighed"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Oplæsningshastighed for tekst"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Sprog"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Brug systemsprog"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Der er ikke valgt sprog"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Angiver det sprog, der skal bruges til oplæsning af tekst"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Lyt til et eksempel"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Afspil en kort demonstration af talesyntese"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Installer stemmedata"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Installer de påkrævede stemmedata for talesyntese"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Denne funktion kan indsamle al den tekst, der læses op, inklusive personlige data såsom adgangskoder og kreditkortnumre. Den kommer fra <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>-maskinen. Vil du aktivere brug af denne talesyntesemaskine?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Oplæsning på dette sprog fungerer kun, når der findes en aktiv netværksforbindelse."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Dette er et eksempel på talesyntese."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status for standardsprog"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> er fuldt understøttet"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> kræver netværksforbindelse"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> understøttes ikke"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Indstillinger for <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Åbn indstillinger for maskinen"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Foretrukken maskine"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Generelt"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index cc0990d10453..6d1c8991818c 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Nutzer: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Einige Standardeinstellungen festgelegt"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Keine Standardeinstellungen festgelegt"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Text-in-Sprache"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Text-in-Sprache-Ausgabe"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Sprechgeschwindigkeit"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Geschwindigkeit, mit der der Text gesprochen wird"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Sprache"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Systemsprache verwenden"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Keine Sprache ausgewählt"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Legt die sprachspezifische Stimme für den gesprochenen Text fest"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Beispiel anhören"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Kurzes Beispiel der Sprachsynthese abspielen"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Sprachdaten installieren"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Sprachdaten für Sprachsynthese installieren"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Dieses Sprachsynthesemodul kann den gesamten gesprochenen Text erfassen, einschließlich personenbezogener Daten wie Passwörter und Kreditkartennummern. Es ist Teil der App \"<xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>\". Möchten Sie dieses Sprachsynthesemodul aktivieren?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Für diese Sprache ist zur Text-in-Sprache-Ausgabe eine aktive Netzwerkverbindung erforderlich."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Dies ist ein Beispiel für Sprachsynthese."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status der Standardsprache"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> wird vollständig unterstützt."</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> erfordert eine Netzwerkverbindung."</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> wird nicht unterstützt."</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Einstellungen für <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Einstellungen der Suchmaschine starten"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Bevorzugtes Modul"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Allgemein"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 1d1c5643d192..e3d19afb58d7 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Χρήστης: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Έχουν οριστεί κάποιες προεπιλογές"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Δεν έχουν οριστεί προεπιλογές"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Ρυθμίσεις μετατροπής κειμένου σε ομιλία"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Έξοδος μετατροπής κειμένου σε ομιλία"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Ταχύτητα λόγου"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Ταχύτητα με την οποία εκφωνείται το κείμενο"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Γλώσσα"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Χρήση γλώσσας συστήματος"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Δεν έχει επιλεγεί γλώσσα"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Ορίζει τη φωνή που σχετίζεται με τη γλώσσα για το κείμενο ομιλίας"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Ακούστε ένα παράδειγμα"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Αναπαραγωγή μιας σύντομης αναπαράστασης σύνθεσης λόγου"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Εγκατάσταση δεδομένων φωνής"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Εγκατάσταση δεδομένων ήχου που απαιτούνται για τη σύνθεση ήχου"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Αυτή η μηχανή σύνθεσης ομιλίας μπορεί να συγκεντρώσει όλο το κείμενο που θα εκφωνηθεί, συμπεριλαμβανομένων προσωπικών δεδομένων όπως οι κωδικοί πρόσβασης και οι αριθμοί πιστωτικών καρτών. Προέρχεται από τη μηχανή <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Να ενεργοποιηθεί η μηχανή σύνθεσης ομιλίας;"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Αυτή η γλώσσα απαιτεί μια ενεργή σύνδεση δικτύου για τη μετατροπή κειμένου σε ομιλία."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Αυτό είναι ένα παράδειγμα σύνθεσης λόγου"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Κατάσταση προεπιλεγμένης γλώσσας"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"Τα <xliff:g id="LOCALE">%1$s</xliff:g> υποστηρίζονται πλήρως"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"Τα <xliff:g id="LOCALE">%1$s</xliff:g> απαιτούν σύνδεση δικτύου"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Δεν υποστηρίζονται τα <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Ρυθμίσεις για: <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Εκκίνηση ρυθμίσεων μηχανής"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Προτεινόμενη μηχανή"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Γενικά"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 99fd61eaa512..113877933f60 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"User: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Some defaults set"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"No defaults set"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Text-to-speech settings"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Text-to-speech output"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Speech rate"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Speed at which the text is spoken"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Language"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Use system language"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Language not selected"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Sets the language-specific voice for the spoken text"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Listen to an example"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Play a short demonstration of speech synthesis"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Install voice data"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Install the voice data required for speech synthesis"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"This speech synthesis engine may be able to collect all the text that will be spoken, including personal data like passwords and credit card numbers. It comes from the <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> engine. Enable the use of this speech synthesis engine?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"This language requires a working network connection for text-to-speech output."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"This is an example of speech synthesis"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Default language status"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> is fully supported"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> requires network connection"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> is not supported"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Settings for <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Launch engine settings"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Preferred engine"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"General"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 99fd61eaa512..113877933f60 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"User: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Some defaults set"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"No defaults set"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Text-to-speech settings"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Text-to-speech output"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Speech rate"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Speed at which the text is spoken"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Language"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Use system language"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Language not selected"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Sets the language-specific voice for the spoken text"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Listen to an example"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Play a short demonstration of speech synthesis"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Install voice data"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Install the voice data required for speech synthesis"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"This speech synthesis engine may be able to collect all the text that will be spoken, including personal data like passwords and credit card numbers. It comes from the <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> engine. Enable the use of this speech synthesis engine?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"This language requires a working network connection for text-to-speech output."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"This is an example of speech synthesis"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Default language status"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> is fully supported"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> requires network connection"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> is not supported"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Settings for <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Launch engine settings"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Preferred engine"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"General"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 99fd61eaa512..113877933f60 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"User: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Some defaults set"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"No defaults set"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Text-to-speech settings"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Text-to-speech output"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Speech rate"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Speed at which the text is spoken"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Language"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Use system language"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Language not selected"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Sets the language-specific voice for the spoken text"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Listen to an example"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Play a short demonstration of speech synthesis"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Install voice data"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Install the voice data required for speech synthesis"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"This speech synthesis engine may be able to collect all the text that will be spoken, including personal data like passwords and credit card numbers. It comes from the <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> engine. Enable the use of this speech synthesis engine?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"This language requires a working network connection for text-to-speech output."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"This is an example of speech synthesis"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Default language status"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> is fully supported"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> requires network connection"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> is not supported"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Settings for <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Launch engine settings"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Preferred engine"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"General"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index a912db2cb0ad..3a6ca108abaa 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Usuario: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Hay algunas configuraciones predeterminadas establecidas."</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"No hay configuraciones predeterminadas establecidas."</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Configuración de texto a voz"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Salida de texto a voz"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidad de voz"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidad en la que se habla el texto"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar el idioma del sistema"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma no seleccionado"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Establece la voz específica de un idioma para el texto hablado"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Escuchar un ejemplo"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Reproducir una pequeña demostración de síntesis de voz"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalar datos de voz"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalar los datos de voz necesarios para la síntesis de voz"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Es posible que este motor de síntesis de voz pueda recopilar todo el texto que se hablará, incluidos los datos personales como las contraseñas y los números de tarjetas de crédito. Proviene del motor <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. ¿Deseas activar el uso de este motor de síntesis de voz?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma necesita una conexión de red en funcionamiento para la salida de texto a voz."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Ejemplo de síntesis de voz"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Estado del idioma predeterminado"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"El idioma <xliff:g id="LOCALE">%1$s</xliff:g> es totalmente compatible."</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"El idioma <xliff:g id="LOCALE">%1$s</xliff:g> requiere una conexión de red."</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"El idioma <xliff:g id="LOCALE">%1$s</xliff:g> no es compatible."</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Configuración de <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Iniciar configuración de motor"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motor preferido"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"General"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index b6dcb9e60560..9bd8462f0b5c 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Usuario: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Se han establecido algunos valores predeterminados"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"No se han establecido valores predeterminados"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Configuración síntesis voz"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Síntesis de voz"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidad de la voz"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidad a la que se lee el texto"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma del sistema"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma no seleccionado"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Establecer la voz del idioma específico para el texto hablado"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Escuchar un ejemplo"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Reproducir una breve demostración de síntesis de voz"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalar archivos de voz"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalar los archivos de datos de voz necesarios para la síntesis de voz"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Es posible que este motor de síntesis de voz recopile todo el texto hablado, incluidos datos personales, como contraseñas y números de tarjeta de crédito. Procede del motor <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. ¿Quieres habilitar el uso de este motor de síntesis de voz?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma requiere una conexión de red activa para la salida de síntesis de voz."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Este es un ejemplo de síntesis de voz"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Estado del idioma predeterminado"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"El <xliff:g id="LOCALE">%1$s</xliff:g> se admite completamente"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"El idioma <xliff:g id="LOCALE">%1$s</xliff:g> requiere conexión a Internet"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"No se admite el <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"Comprobando..."</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Ajustes de <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Iniciar configuración de motor"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motor preferido"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"General"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"Muy lenta"</item>
+ <item msgid="4795095314303559268">"Lenta"</item>
+ <item msgid="8903157781070679765">"Normal"</item>
+ <item msgid="164347302621392996">"Rápida"</item>
+ <item msgid="5794028588101562009">"Más rápida"</item>
+ <item msgid="7163942783888652942">"Muy rápida"</item>
+ <item msgid="7831712693748700507">"Superrápida"</item>
+ <item msgid="5194774745031751806">"Hiperrrápida"</item>
+ <item msgid="9085102246155045744">"La más rápida"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index ee9207863144..820c7014a104 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Kasutaja: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Määratud on mõned vaikevalikud"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Ühtegi vaikevalikut pole määratud"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Kõnesünteesi seaded"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Kõnesünteesi väljund"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Kõnekiirus"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Teksti rääkimise kiirus"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Keel"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Süsteemi keele kasutamine"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Keelt pole valitud"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Määrab räägitud teksti keelespetsiifilise hääle"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Kuulake näidet"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Esita lühike kõnesünteesi demo"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Installi hääleandmed"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Installi kõnesünteesi jaoks vajalikud hääleandmed"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"See kõnesünteesimootor võib koguda kogu kõneldud teksti, sh isiklikke andmeid, nagu paroolid ja krediitkaardinumbrid. Selle aluseks on mootor <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Kas lubada kõnesünteesimootori kasutamine?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Selle keele puhul on kõnesünteesi väljundi jaoks vaja toimivat võrguühendust."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"See on kõnesünteesi näide"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Vaikekeele olek"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> on täielikult toetatud"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> vajab võrguühendust"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> pole toetatud"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"Kontrollimine ..."</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Seaded: <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Käivita mootori seaded"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Eelistatud mootor"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Üldine"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"Väga aeglane"</item>
+ <item msgid="4795095314303559268">"Aeglane"</item>
+ <item msgid="8903157781070679765">"Tavaline"</item>
+ <item msgid="164347302621392996">"Kiire"</item>
+ <item msgid="5794028588101562009">"Kiirem"</item>
+ <item msgid="7163942783888652942">"Väga kiire"</item>
+ <item msgid="7831712693748700507">"Tormakas"</item>
+ <item msgid="5194774745031751806">"Väga tormakas"</item>
+ <item msgid="9085102246155045744">"Kõige kiirem"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index 9b931113c892..990960da49a6 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Erabiltzailea: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Hobespen lehenetsi batzuk ezarrita daude"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Ez dago hobespen lehenetsirik ezarrita"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Testua ahots bihurtzeko eginbidearen ezarpenak"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Testua ahots bihurtzeko eginbidearen irteera"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Hizketa-abiadura"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Testua zer abiaduran esaten den"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Hizkuntza"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Erabili sistemaren hizkuntza"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Ez da hizkuntza hautatu"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Esandako testuaren ahotsa hizkuntzaren arabera ezartzen du"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Entzun adibide bat"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Erreproduzitu hizketa-sintesiaren demostrazio laburra"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalatu ahotsaren datuak"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalatu hizketaren sintesirako behar diren ahots-datuak"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Hizketaren sintesi-motorrak idazten duzun testu guztia bil dezake, pasahitzak eta kreditu-txarteleko zenbakiak bezalako datu pertsonalak barne. <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> motorrak egin du eskaera. Hizketaren sintesi-motor hori erabili nahi duzu?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Testua ahots bihurtzeko eginbidea erabiltzeko, hizkuntza honek sareko konexioa behar du."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Hizketa-sintesiaren adibide bat da hau"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Hizkuntza lehenetsiaren egoera"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> guztiz onartzen da."</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> eskualde-ezarpenak sareko konexioa behar du"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Ez da <xliff:g id="LOCALE">%1$s</xliff:g> onartzen"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> motorraren ezarpenak"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Abiarazi motorraren ezarpenak"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motor hobetsia"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Orokorra"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 081c77619468..387a43e8d7ba 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"کاربر: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"بعضی پیش‌فرض‌ها تنظیم شده‌اند"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"هیچ پیش‌فرضی تنظیم نشده است"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"تنظیمات متن به گفتار"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"خروجی تبدیل متن به گفتار"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"سرعت گفتار"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"سرعتی که متن خوانده می‌شود"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"زبان"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"استفاده از زبان سیستم"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"زبان انتخاب نشده است"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"صدای خاص یک زبان را برای متن گفتاری تنظیم می‌کند"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"به نمونه‌ای گوش کنید"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"قسمت کوتاهی از ترکیب گفتار پخش شود"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"نصب داده‌های صوتی"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"نصب داده‌های صوتی مورد نیاز برای ترکیب گفتار"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"این موتور ترکیب صوتی ممکن است بتواند تمام متن گفته شده را جمع‌آوری کند، از جمله اطلاعات شخصی مانند رمزهای ورود و شماره‌های کارت اعتباری. این کارها توسط موتور<xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> انجام می‌شود. استفاده از این موتور ترکیب صوتی را فعال می‌کنید؟"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"این زبان به یک اتصال شبکه فعال برای خروجی نوشتار به گفتار نیاز دارد."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"این نمونه‌ای از ترکیب گفتار است"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"وضعیت زبان پیش‌فرض"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> کاملاً پشتیبانی می‌شود"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> به اتصال شبکه نیاز دارد"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> پشتیبانی نمی‌شود"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"تنظیمات برای <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"راه‌اندازی تنظیمات موتور"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"موتور ترجیحی"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"کلی"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 29bcf119eaff..e6400c3270fa 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Käyttäjä: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Joitakin oletuksia on asetettu."</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Oletuksia ei asetettu."</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Tekstistä puheeksi -asetukset"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Tekstistä puheeksi -toisto"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Puheen nopeus"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Tekstin puhumisnopeus"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Kieli"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Käytä järjestelmän kieltä"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Kieltä ei ole valittu"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Asettaa puhutulle tekstille kielikohtaisen äänen"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Kuuntele esimerkki"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Toista lyhyt esittely puhesynteesistä"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Asenna äänitiedot"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Asenna puhesynteesiin tarvittavat äänitiedot"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Tämä puhesynteesimoottori saattaa kerätä kaiken puhutun tekstin, mukaan lukien henkilökohtaiset tiedot kuten salasanat ja luottokorttinumerot. Se on lähtöisin moottorista <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Haluatko ottaa tämän puhesynteesimoottorin käyttöön?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Tämä kieli vaatii verkkoyhteyden, jotta tekstistä puheeksi muuntaminen toimii."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Tämä on esimerkki puhesynteesistä."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Oletuskieliasetus"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"Kieltä <xliff:g id="LOCALE">%1$s</xliff:g> tuetaan"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"Kieli <xliff:g id="LOCALE">%1$s</xliff:g> tarvitsee yhteyden verkostoon"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Kieltä <xliff:g id="LOCALE">%1$s</xliff:g> ei tueta"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Asetukset: <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Käynnistä moottorin asetukset"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Ensisijainen kone"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Yleiset"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 6760af626ad9..9e1a5a0c5ad2 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Utilisateur : <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Certaines préférences par défaut définies"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Aucune préférence par défaut définie"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Synthèse vocale"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Sortie de la synthèse vocale"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Cadence"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Vitesse à laquelle le texte est énoncé"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Langue"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Utiliser la langue du système"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Langue non sélectionnée"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Définit la langue utilisée par la syntèse vocale"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Écouter un échantillon"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Lire une courte démonstration de la synthèse vocale"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Installer les données vocales"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Installer les données nécessaires à la synthèse vocale"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Ce moteur de synthèse vocale est susceptible d\'enregistrer tout ce que vous direz, y compris des données personnelles telles que les mots de passe et les numéros de carte de paiement. Il provient du moteur <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Voulez-vous l\'activer?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Une connexion réseau est nécessaire pour la synthèse vocale dans cette langue."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Voici un échantillon de synthèse vocale"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"État de la langue par défaut"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"Les paramètres régionaux <xliff:g id="LOCALE">%1$s</xliff:g> sont compatibles"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"Les paramètres régionaux <xliff:g id="LOCALE">%1$s</xliff:g> nécessitent une connexion réseau"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Les paramètres régionaux <xliff:g id="LOCALE">%1$s</xliff:g> ne sont pas compatibles"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Paramètres de <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Lancer les paramètres du moteur"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Moteur préféré"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Général"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index fff50c9f1c46..0e3265fa0aab 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Utilisateur : <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Certains paramètres par défaut définis"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Aucun paramètre par défaut défini"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Paramètres de la synthèse vocale"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Synthèse vocale"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Cadence"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Vitesse à laquelle le texte est énoncé"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Langue"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Utiliser la langue du système"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Langue non sélectionnée"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Définir la langue utilisée par la synthèse vocale"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Écouter un échantillon"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Lire une courte démonstration de la synthèse vocale"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Installer les données vocales"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Installer les données nécessaires à la synthèse vocale"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Ce moteur de synthèse vocale est susceptible de collecter tout ce qui sera lu, y compris les données personnelles comme les mots de passe et les numéros de carte de paiement. Il provient du moteur <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Voulez-vous activer son utilisation ?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Une connexion réseau est nécessaire pour la synthèse vocale dans cette langue."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Voici un échantillon de synthèse vocale."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"État de la langue par défaut"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"Les paramètres régionaux <xliff:g id="LOCALE">%1$s</xliff:g> sont compatibles."</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"Les paramètres régionaux <xliff:g id="LOCALE">%1$s</xliff:g> nécessitent une connexion réseau."</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Les paramètres régionaux <xliff:g id="LOCALE">%1$s</xliff:g> ne sont pas compatibles."</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Paramètres de <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Lancer les paramètres du moteur"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Moteur préféré"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Paramètres généraux"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index ec0e5cb4960f..7c6c5023a8cb 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Usuario: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Definíronse algúns valores predeterminados"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Non se definiu ningún valor predeterminado"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Configuración da síntese de voz"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Síntese de voz"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidade da fala"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade á que se di o texto"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizar idioma do sistema"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma non seleccionado"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Define a voz específica do idioma para o texto falado"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Escoitar un exemplo"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Reproduce unha breve demostración da síntese de voz"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalar datos de voz"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instala os datos de voz necesarios para a síntese de voz"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"É posible que este motor de síntese de voz poida recompilar todo o texto falado, incluídos datos persoais como contrasinais e números de tarxetas de crédito. Provén do motor <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Queres activar o uso deste motor de síntese de voz?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma precisa dispoñer dunha conexión de rede que funcione para emitir a síntese de voz."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Este é un exemplo da síntese de voz"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Estado do idioma predeterminado"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> é completamente compatible"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> require unha conexión de rede"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Non se admite <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Configuración de <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Iniciar configuración do motor"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motor preferido"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Xeral"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml
index 0fcf219b3fc7..cdecea9505d2 100644
--- a/packages/SettingsLib/res/values-gu-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"વપરાશકર્તા: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"કેટલાંક ડિફોલ્ટ્સ સેટ કરેલ છે"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"કોઇ ડિફોલ્ટ્સ સેટ કરેલ નથી"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"ટેક્સ્ટ-ટુ-સ્પીચ સેટિંગ્સ"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"ટેક્સ્ટ ટુ સ્પીચ આઉટપુટ"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"વાણી દર"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"ટેક્સ્ટ બોલાયેલ છે તે ઝડપ"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ભાષા"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"સિસ્ટમ ભાષાનો ઉપયોગ કરો"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"ભાષા પસંદ કરેલ નથી"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"બોલાયેલ ટેક્સ્ટ માટે ભાષા-વિશિષ્ટ વૉઇસ સેટ કરે છે"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"એક ઉદાહરણ સાંભળો"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"વાણી સંશ્લેષણનું એક ટૂંકુ પ્રદર્શન ચલાવો"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"વૉઇસ ડેટા ઇન્સ્ટોલ કરો"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"વાણી સંશ્લેષણ માટે જરૂરી વૉઇસ ડેટા ઇન્સ્ટોલ કરો"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"આ વાણી સંશ્લેષણ એન્જિન પાસવર્ડ્સ અને ક્રેડિટ કાર્ડ નંબર જેવી વ્યક્તિગત માહિતી સહિત બોલવામાં આવશે તે તમામ ટેક્સ્ટને એકત્રિત કરવા માટે સક્ષમ હોઈ શકે છે. તે <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> એન્જિન પરથી આવે છે. આ વાણી સંશ્લેષણ એન્જિનના ઉપયોગને સક્ષમ કરીએ?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"આ ભાષાને ટેક્સ્ટ ટુ સ્પીચ આઉટપુટ માટે ચાલુ નેટવર્કની આવશ્યકતા છે."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"આ વાણી સંશ્લેષણનું એક ઉદાહરણ છે"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"ડીફોલ્ટ ભાષા સ્થિતિ"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> સંપૂર્ણપણે સમર્થિત છે"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> નેટવર્ક કનેક્શનની આવશ્યકતા છે"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> સમર્થિત નથી"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"તપાસી રહ્યું છે..."</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> માટેની સેટિંગ્સ"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"એન્જિન સેટિંગ્સ લોંચ કરો"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"મનપસંદ એન્જિન"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"સામાન્ય"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"ખૂબ જ ધીમી"</item>
+ <item msgid="4795095314303559268">"ધીમી"</item>
+ <item msgid="8903157781070679765">"સામાન્ય"</item>
+ <item msgid="164347302621392996">"ઝડપી"</item>
+ <item msgid="5794028588101562009">"વધુ ઝડપી"</item>
+ <item msgid="7163942783888652942">"ખૂબ ઝડપી"</item>
+ <item msgid="7831712693748700507">"તીવ્ર"</item>
+ <item msgid="5194774745031751806">"ખૂબ જ તીવ્ર"</item>
+ <item msgid="9085102246155045744">"સૌથી ઝડપી"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 8d5a16b4198e..bab59aafabc9 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"उपयोगकर्ता: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"कुछ डिफ़ॉल्‍ट सेट हैं"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"कोई डिफ़ॉल्‍ट सेट नहीं है"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"लेख से बोली सेटिंग"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"लेख को सुनें"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"बोली दर"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"बोलने की गति तय करें"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"भाषा"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"सिस्‍टम भाषा का उपयोग करें"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"भाषा नहीं चुनी गई है"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"बोले गए लेख के लिए भाषा-विशिष्ट ध्‍वनि सेट करता है"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"एक उदाहरण सुनें"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"बोली संश्लेषण का एक संक्षिप्त प्रदर्शन चलाएं"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"ध्‍वनि डेटा इंस्टॉल करें"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"बोली-संश्लेषण के लिए आवश्‍यक ध्‍वनि डेटा इंस्‍टॉल करें"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"यह बोली संश्लेषण इंजन पासवर्ड और क्रेडिट कार्ड नंबर जैसे निजी डेटा समेत आपके द्वारा बोले जाने वाले सभी लेख को एकत्र कर सकता है. यह <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इंजन से आता है. इस बोली संश्लेषण इंजन के उपयोग को सक्षम करें?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"लेख-से-बोली आउटपुट के लिए इस भाषा को क्रियाशील नेटवर्क कनेक्शन की आवश्यकता है."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"यह बोली संश्लेषण का एक उदाहरण है"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"डिफ़ॉल्ट भाषा स्थिति"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> पूरी तरह से समर्थित है"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> के लिए नेटवर्क कनेक्शन की आवश्यकता है"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> समर्थित नहीं है"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"जांच की जा रही है..."</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> के लिए सेटिंग"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"इंजन सेटिंग लॉन्‍च करें"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"पसंदीदा इंजन"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"सामान्य"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"अत्‍यधिक धीमा"</item>
+ <item msgid="4795095314303559268">"धीमा"</item>
+ <item msgid="8903157781070679765">"सामान्य"</item>
+ <item msgid="164347302621392996">"तेज़"</item>
+ <item msgid="5794028588101562009">"अधिक तेज़"</item>
+ <item msgid="7163942783888652942">"अत्‍यधिक तेज़"</item>
+ <item msgid="7831712693748700507">"त्वरित"</item>
+ <item msgid="5194774745031751806">"अत्यधिक तीव्र"</item>
+ <item msgid="9085102246155045744">"सबसे तेज़"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index e497d3a0532a..77c3d2621361 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Korisnik: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Postavljene su neke zadane postavke"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nema zadanih postavki"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Postavke za tekst u govor"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Pretvaranje teksta u govor"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Brzina govora"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Brzina kojom se izgovara tekst"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"upotrijebi jezik sustava"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik nije odabran"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Postavlja jezik govora"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Poslušajte primjer"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Poslušajte primjer sinteze zvuka"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instaliraj glasovne podatke"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instaliraj glasovne podatke potrebne za sintezu govora"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Alat za sintezu govora može prikupljati izgovoreni sadržaj, uključujući osobne podatke kao što su zaporke i brojevi kreditnih kartica. To omogućuje alat <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Želite li omogućiti alat za sintezu govora?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Da bi se dobili izlazni podaci pretvaranja teksta u govor za taj jezik, potrebna je aktivna veza s mrežom."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Ovo je primjer sinteze govora"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status zadanog jezika"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> je u potpunosti podržan"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> zahtijeva mrežnu vezu"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> nije podržan"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Postavke za <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Postavke pokretanja alata"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Željeni alat"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Opće"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index aefc45f3c8bd..e3ecdcc43013 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -74,7 +74,7 @@
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Mégse"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"A párosítás hozzáférést biztosít a névjegyekhez és híváselőzményekhez összekapcsolt állapotban."</string>
<string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Nem lehet párosítani a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközzel."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"A párosítás sikertelen volt a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközzel hibás PIN kód vagy jelszó miatt."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"A párosítás sikertelen volt a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközzel hibás PIN-kód vagy jelszó miatt."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Nem lehet kommunikálni a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszközzel."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"A(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> eszköz elutasította a párosítást."</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi kikapcsolva."</string>
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Felhasználó: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Van néhány alapbeállítás"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nincs alapbeállítás"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Szöveg-beszéd átalakítás beállításai"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Szövegfelolvasás"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Beszéd sebessége"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"A szöveg kimondásának sebessége"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Nyelv"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"A rendszer nyelvének használata"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nincs nyelv kiválasztva"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Beállítja a beszélt szöveg nyelvspecifikus hangját"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Példa meghallgatása"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Beszédszintézis rövid bemutatása"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Hangadatok telepítése"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"A beszédszintetizáláshoz szükséges hangadatok telepítése"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Ez a beviteli módszer alkalmas lehet az elhangzott szövegek -- köztük az olyan személyes adatok, mint a jelszavak és a hitelkártyaszámok -- összegyűjtésére. A(z) <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> motor kapcsolta be. Engedélyezi ennek a beszédszintetizáló motornak a használatát?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Ez a nyelv működő hálózati kapcsolatot igényel a szövegfelolvasáshoz."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Ez egy példa a beszédszintézisre"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Alapértelmezett nyelv állapota"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"A(z) <xliff:g id="LOCALE">%1$s</xliff:g> nyelv teljes támogatást élvez"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"A(z) <xliff:g id="LOCALE">%1$s</xliff:g> nyelv használatához hálózati kapcsolatra van szükség"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"A(z) <xliff:g id="LOCALE">%1$s</xliff:g> nyelvet nem támogatja a rendszer"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"A(z) <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> beállításai"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Keresőmotor beállításainak indítása"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Preferált motor"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Általános"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml
index 7df405a4f1aa..2819ebbe79fb 100644
--- a/packages/SettingsLib/res/values-hy-rAM/strings.xml
+++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Օգտվող՝ <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Որոշ կանխադրված կարգավորումներ կան"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Կանխադրված կարգավորումներ չկան"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Տեքստից-խոսք կարգավորումներ"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Գրվածքից խոսք ելք"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Խոսքի գնահատական"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Տեքստի արտասանման արագությունը"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Լեզու"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Օգտագործել համակարգի լեզուն"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Լեզուն ընտրված չէ"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Կարգավորում է լեզվին բնորոշ ձայնը արտասանվող տեքստի համար"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Լսել օրինակը"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Կարճ հնչեցնել խոսքի սինթեզը"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Տեղադրել ձայնային տվյալները"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Տեղադրել անհրաժեշտ ձայնային տվյալները` խոսքը սինթեզելու համար"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Այս խոսքային սինթեզի գործիքը կարող է հավաքագրել այն ամենը, ինչ արտասանված է, այդ թվում` անձնական տվյալներ, ինչպիսիք են գաղտնաբառն ու բանկային քարտի համարները: Սկզբնաբյուրը <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> շարժիչն է: Միացնե՞լ խոսքի սինթեզի շարժիչի օգտագործումը:"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Այս լեզուն պահանջում է աշխատող ցանցային կապ գրվածքից խոսք ելքի համար:"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Սա խոսքային սինթեզի մի նմուշ է:"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Լռելյայն լեզվի կարգավիճակը"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g>-ը լիովին աջակցվում է"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g>-ը պահանջում է ցանցային կապ"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g>-ը չի աջակցվում"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Կարգավորումներ <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>-ի համար"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Գործարկման շարժիչի կարգավորումներ"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Նախընտրած շարժիչը"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Ընդհանուր"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 32dfa0371af2..bc1f0e899644 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Pengguna: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Beberapa setelan default"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Tidak ada setelan default"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Setelan text-to-speech"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Keluaran text-to-speech"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Laju bicara"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Kecepatan teks diucapkan"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Bahasa"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Gunakan bahasa sistem"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Bahasa tidak dipilih"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Menyetel suara spesifik bahasa untuk teks lisan"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Dengarkan contoh"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Putar demonstrasi singkat dari sintesis suara"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Pasang data suara"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Pasang data suara yang dibutuhkan untuk sintesis suara"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Mesin sintesis suara ini mungkin dapat mengumpulkan semua teks yang akan diucapkan, termasuk di antaranya data pribadi seperti sandi dan nomor kartu kredit. Berasal dari <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> aplikasi. Gunakan metode masukan ini?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Bahasa ini perlu sambungan jaringan yang bekerja untuk keluaran text-to-speech."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Ini adalah contoh sintesis suara"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status bahasa default"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> didukung sepenuhnya"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> membutuhkan sambungan jaringan"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> tidak didukung"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Setelan untuk <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Luncurkan setelan mesin"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Mesin yang dipilih"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Umum"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index a3dd8c4b1b26..458463d38d19 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Notandi: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Einhver sjálfgildi valin"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Engin sjálfgildi valin"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Stillingar upplesturs"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Úttak upplesturs"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Talhraði"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Hraði talaðs texta"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Tungumál"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Nota tungumál kerfis"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Tungumál ekki valið"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Velur rödd hvers tungumáls fyrir lesinn texta"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Hlusta á dæmi"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Spila stutta kynningu á talgervli"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Setja upp raddgögn"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Setja upp nauðsynleg raddgögn fyrir talgervil"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Þessi talgervilsvél getur hugsanlega skráð allan texta sem lesin er upp, þ. á m. persónuupplýsingar á borð við aðgangsorð og kreditkortanúmer. Hún kemur frá vélinni <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Viltu gera þessa talgervilsvél virka?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Þetta tungumál þarf nettengingu til að hægt sé að nota talgervil."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Þetta er dæmi um talgervil"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Staða sjálfgefins tungumáls"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> er með fullan stuðning"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> krefst nettengingar"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> er ekki studd"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Stillingar fyrir <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Stillingar vélarræsingar"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Valin vél"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Almennt"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index d5b4a159b39b..4042c6fabf00 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Utente: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Alcune opzioni predefinite impostate"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nessuna applicazione predefinita impostata"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Impostazioni di sintesi vocale"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Output sintesi vocale"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocità voce"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocità di pronuncia del testo"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Lingua"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Usa lingua di sistema"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Lingua non selezionata"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Imposta la voce specifica della lingua per il testo parlato"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Ascolta un esempio"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Riproduci una breve dimostrazione della sintesi vocale"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Installa dati vocali"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Installa i dati vocali richiesti per la sintesi vocale"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Questo motore di sintesi vocale potrebbe essere in grado di raccogliere tutto il testo pronunciato, inclusi dati personali come password e numeri di carte di credito. Deriva dal motore <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Abilitare l\'uso di questo motore di sintesi vocale?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Questa lingua richiede una connessione di rete funzionante per l\'output di sintesi vocale."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Questo è un esempio di sintesi vocale"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Stato della lingua predefinita"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> completamente supportato"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> richiede connessione di rete"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> non supportato"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Impostazioni per <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Avvia impostazioni del motore"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motore preferito"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Generali"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 6780d1e3b106..cf055ae70163 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"משתמש: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"הוגדרו כמה ברירת מחדל"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"לא הוגדרו ברירות מחדל"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"הגדרות טקסט לדיבור"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"פלט טקסט לדיבור"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"קצב דיבור"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"המהירות שבה הטקסט נאמר"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"שפה"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"שימוש בשפת המערכת"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"לא נבחרה שפה"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"מגדיר קול ספציפי לשפה עבור הטקסט הנאמר"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"האזן לדוגמה"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"הפעל הדגמה קצרה של סינתזת דיבור"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"התקן נתוני קול"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"התקן את הנתונים הקוליים הדרושים לסינתזת דיבור"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"ייתכן שמנוע סינתזת דיבור זה יכול לאסוף את כל הטקסט המדובר, כולל נתונים אישיים כגון סיסמאות ומספרי כרטיסי אשראי. הוא מגיע מהמנוע <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. להפוך את השימוש במנוע סינתזת דיבור זה לפעיל?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"שפה זו דורשת חיבור רשת פעיל עבור פלט טקסט לדיבור."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"זוהי דוגמה לסינתזת דיבור"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"ברירת המחדל לסטטוס שפה"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> נתמכת באופן מלא"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> מצריכה חיבור לרשת"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> אינה נתמכת"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"הגדרות עבור <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"השק הגדרות מנוע"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"מנוע מועדף"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"כללי"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index ceaaf137f89a..9622df482c17 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"ユーザー: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"一部デフォルトを設定"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"既定の設定なし"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"テキスト読み上げの設定"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"テキスト読み上げの出力"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"音声の速度"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"テキストの読み上げ速度"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"言語"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"システムの言語を使用"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"言語が選択されていません"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"テキスト読み上げに使用する言語固有の音声を設定する"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"サンプルを再生"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"音声合成の短いサンプルを再生する"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"音声データをインストール"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"音声合成に必要な音声データをインストールする"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"この音声合成エンジンを使用すると、読み上げるすべてのテキストの収集をエンジン(<xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>)に許可することになります。これにはパスワードやクレジットカード番号などの個人情報も含まれます。この音声合成エンジンを有効にしますか?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"この言語でテキスト読み上げを出力するには、ネットワーク接続が正常に機能している必要があります。"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"これは音声合成のサンプルです"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"デフォルトの言語のステータス"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g>は完全サポート対象です"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g>ではネットワーク接続が必要です"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g>はサポート対象ではありません"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>の設定"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"エンジン設定を起動"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"優先するエンジン"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"全般"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml
index 286c7099f86d..8803e5945d9f 100644
--- a/packages/SettingsLib/res/values-ka-rGE/strings.xml
+++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"მომხმარებელი: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"ზოგიერთი ნაგულისხმევი პარამეტრი დაყენებულია"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"ნაგულისხმევი პარამეტრები არ არის დაყენებული."</string>
+ <string name="tts_settings" msgid="8186971894801348327">"ტექსტის გახმოვანების პარამეტრები"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"მეტყველების სინთეზი"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"მეტყველების ტემპი"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"ტექსტის თხრობის სიჩქარე"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ენა"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"სისტემის ენის გამოყენება"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"ენა არჩეული არ არის"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"ენის შესაფერი ხმის დაყენება"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"მოუსმინეთ მაგალითს"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"სინთეზირებული მეტყველების მოკლე ნაწყვეტის აღწარმოება"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"ხმის მონაცემების დაყენება"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Install the voice data required for speech synthesis"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"მეტყველების სინთეზის მოცემულ სისტემას შეუძლია ჩაიწეროს წარმოთქმული სიტყვები, მათ შორის პირადი მონაცემები, როგორიცაა პაროლები და საკრედიტო ბარათების ნომრები. ამას ახორციელებს <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> სისტემა. გამოვიყენოთ მეტყველების სინთეზიზს მოცემული სისტემა?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"ეს ენა ტექსტის ამოკითხვისთვის მოითხოვს აქტიურ ინტერნეტ კავშირს."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"ეს არის მეტყველების სინთეზის მაგალითი."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"ენის ნაგულისხმევი სტატუსი"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> სრულად მხარდაჭერილია"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> ითხოვს ქსელის კავშირს"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> არ არის მხარდაჭერილი"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> პარამეტრები"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"ძრავის პარამეტრების გაშვება"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"რჩეული ძრავი"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"ზოგადი"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
index 7d89c809cb1e..2e5add7b109b 100644
--- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml
+++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Пайдаланушы: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Кейбір әдепкі параметрлер орнатылған"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Әдепкі параметрлер орнатылмаған"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Мәтіннен-сөйлеуге параметрлері"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Мәтінді тілге айналдыру"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Сөйлеу жылдамдығы"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Мәтіннің оқылу жылдамдығы"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Тіл"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Жүйелік тілді пайдалану"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Тіл таңдалған жоқ"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Сөйлеу мәтіні үшін тілге тән дауыс орнатады"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Үлгіні тыңдау"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Сөйлеу синтезінің қысқа көрсетілімін ойнату"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Дауыс дерекқорын орнату"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Тілді синтездеуге қажетті дауыс дерегін орнату"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Бұл сөйлеуді синтездеу қозғалтқышы айтылған барлық мәтіндерді, кілтсөз және кредит карта нөмірлері сияқты жеке ақпаратты қоса, жинауы мүмкін. Ол <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> қозғалқышы арқылы жадбықталған. Осы сөйлеуді синтездеу қозғалтқышын пайдалану қосылсын ба?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Бұл тіл мәтіннен-сөйлеуге шығысы үшін қосылып тұрған желі байланысын қажет етеді."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Бұл сөйлеу синтезінің мысалы"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Бастапқы тіл күйі"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> тілінің қолдауы бар"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> желі байланысын қажет етеді"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> үшін қолдау ұсынылмаған"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> параметрлері"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Қозғалтқыш параметрлерін қосу"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Қалаулы қозғалтқыш"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Жалпы"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml
index 59f18dbf1496..57389a13cbd9 100644
--- a/packages/SettingsLib/res/values-km-rKH/strings.xml
+++ b/packages/SettingsLib/res/values-km-rKH/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"អ្នកប្រើ៖ <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"លំនាំដើមមួយចំនួនត្រូវបានកំណត់"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"គ្មានការកំណត់លំនាំដើម"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"ការ​កំណត់​អត្ថបទ​ទៅ​ជា​កា​និយាយ"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"លទ្ធផល​អត្ថបទ​ទៅ​ការ​និយាយ"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"អត្រា​និយាយ"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"ល្បឿន​ពេល​អាន​​អត្ថបទ"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ភាសា"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"ប្រើ​ភាសា​ប្រព័ន្ធ"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"មិន​បាន​ជ្រើស​ភាសា"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"កំណត់​សំឡេង​ភាសា​ជាក់លាក់​សម្រាប់​អត្ថបទ​បាន​និយាយ"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"ស្ដាប់​​ឧទាហរណ៍"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"ចាក់​ការ​បង្ហាញ​ខ្លី​នៃ​ការ​សំយោគ​ការ​និយាយ"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"ដំឡើង​ទិន្នន័យ​សំឡេង"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"ដំឡើង​ទិន្នន័យ​សំឡេង​ដែល​ទាមទារ​សម្រាប់​ការ​សំយោគ​សំដី"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"ម៉ាស៊ីន​សំយោគ​ការ​និយាយ​អាច​ប្រមូល​អត្ថបទ​ទាំងអស់​ដែល​នឹង​ត្រូវ​និយាយ​ រួមមាន​ទិន្នន័យ​ផ្ទាល់​ខ្លួន ដូច​ជា​ពាក្យ​សម្ងាត់ និង​លេខ​កាត​ឥណទាន។ វា​បាន​មក​ពី​ម៉ាស៊ីន <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ។បើក​​ការ​ប្រើ​ម៉ាស៊ីន​សំយោគ​ការ​និយាយ​នេះ?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"ភាសា​នេះ​ទាមទារ​ការ​តភ្ជាប់​បណ្ដាញ​​ដែល​ដំណើរការ​សម្រាប់​លទ្ធផល​អត្ថបទ​ត្រូវ​និយាយ។"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"នេះ​ជា​ឧទាហរណ៍​នៃ​ការ​សំយោគ​ការ​និយាយ។"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"ស្ថានភាព​ភាសា​លំនាំដើម"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"បាន​គាំទ្រ​ពេញលេញ <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> ទាមទារ​ការ​ភ្ជាប់​បណ្ដាញ"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"មិន​គាំទ្រ <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"ការ​កំណត់​សម្រាប់ <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"ចាប់ផ្ដើម​ការកំណត់​ម៉ាស៊ីន​ផ្សេង"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"ម៉ាស៊ីន​ដែល​ពេញ​ចិត្ត"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"ទូទៅ"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml
index ef05366af1a2..1b53bfea61ba 100644
--- a/packages/SettingsLib/res/values-kn-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"ಬಳಕೆದಾರ: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"ಕೆಲವು ಡೀಫಾಲ್ಟ್‌ಗಳನ್ನು ಹೊಂದಿಸಲಾಗಿದೆ"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"ಡೀಫಾಲ್ಟ್‌ಗಳನ್ನು ಹೊಂದಿಸಲಾಗಿಲ್ಲ"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"ಪಠ್ಯದಿಂದ ಧ್ವನಿಗೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"ಧ್ವನಿಗೆ-ಪಠ್ಯದ ಔಟ್‌ಪುಟ್‌"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"ಧ್ವನಿಯ ದರ"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"ಪಠ್ಯವನ್ನು ಹೇಳಿದ ವೇಗ"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ಭಾಷೆ"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"ಸಿಸ್ಟಂ ಭಾಷೆಯನ್ನು ಬಳಸು"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"ಭಾಷೆಯನ್ನು ಆಯ್ಕೆಮಾಡಲಾಗಿಲ್ಲ"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"ಮಾತಿನ ಪಠ್ಯಕ್ಕೆ ಭಾಷಾ-ನಿರ್ದಿಷ್ಟ ಧ್ವನಿಯನ್ನು ಹೊಂದಿಸುತ್ತದೆ"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"ಉದಾಹರಣೆಯೊಂದನ್ನು ಆಲಿಸಿ"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"ಧ್ವನಿ ಸಮನ್ವಯದ ಕಿರು ಪ್ರಾತ್ಯಕ್ಷಿಕೆಯನ್ನು ಪ್ಲೇ ಮಾಡು"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"ಧ್ವನಿ ಡೇಟಾವನ್ನು ಸ್ಥಾಪಿಸಿ"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"ಧ್ವನಿ ಸಮನ್ವಯಕ್ಕಾಗಿ ಅಗತ್ಯವಿರುವ ಧ್ವನಿ ಡೇಟಾ ಸ್ಥಾಪಿಸಿ"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಕ್ರೆಡಿಟ್‌ ಕಾರ್ಡ್‌ ಸಂಖ್ಯೆಗಳಂತಹ ವೈಯಕ್ತಿಕ ಡೇಟಾ ಒಳಗೊಂಡಂತೆ ಮಾತನಾಡುವ ಎಲ್ಲ ಪಠ್ಯವನ್ನು ಸಂಗ್ರಹಿಸಲು ಈ ಧ್ವನಿ ಸಮನ್ವಯ ಎಂಜಿನ್‌ಗೆ ಸಾಧ್ಯವಾಗಬಹುದು. ಇದು <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ಎಂಜಿನ್‌ನಿಂದ ಬರುತ್ತದೆ. ಈ ಧ್ವನಿ ಸಮನ್ವಯ ಎಂಜಿನ್ ಬಳಕೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುವುದೇ?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"ಪಠ್ಯದಿಂದ ಧ್ವನಿ ಔಟ್‌ಪುಟ್‌‌ಗಾಗಿ ಈ ಭಾಷೆಗೆ ಕಾರ್ಯನಿರತವಾದ ನೆಟ್‌ವರ್ಕ್‌ನ ಅಗತ್ಯವಿದೆ."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"ಇದು ಧ್ವನಿ ಸಮನ್ವಯದ ಒಂದು ಉದಾಹರಣೆಯಾಗಿದೆ"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"ಡೀಫಾಲ್ಟ್ ಭಾಷೆಯ ಸ್ಥಿತಿ"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> ಸಂಪೂರ್ಣವಾಗಿ ಬೆಂಬಲಿತವಾಗಿದೆ"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> ನೆಟ್‌ವರ್ಕ್ ಸಂಪರ್ಕದ ಅಗತ್ಯವಿದೆ"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> ಬೆಂಬಲಿತವಾಗಿಲ್ಲ"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> ಗಾಗಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"ಎಂಜಿನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಪ್ರಾರಂಭಿಸು"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"ಪ್ರಾಶಸ್ತ್ಯದ ಎಂಜಿನ್"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"ಸಾಮಾನ್ಯ"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 75396cb6f6ac..f0ff60f7ed84 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"사용자: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"일부 기본값이 설정됨"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"기본값이 설정되지 않음"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"TTS 설정"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"TTS 출력"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"말하는 속도"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"텍스트를 읽어주는 속도"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"언어"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"시스템 언어 사용"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"언어가 선택되지 않음"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"발음된 텍스트에 대해 언어별로 음성 설정"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"예제 듣기"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"짧은 음성 합성 데모 재생"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"음성 데이터 설치"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"음성 합성을 사용하려면 음성 데이터를 설치해야 함"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"이 음성 합성 엔진은 비밀번호와 신용카드 번호 등의 개인 데이터를 비롯한 모든 음성 데이터를 수집할 수 있습니다. 이것은 <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> 엔진의 기능입니다. 음성 합성 엔진을 사용하도록 설정하시겠습니까?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"이 언어로 TTS(Text-to-speech)를 출력하려면 네트워크 연결이 작동해야 합니다."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"음성 합성의 예입니다."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"기본 언어 상태"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g>은(는) 완전하게 지원됩니다."</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g>은(는) 네트워크 연결이 필요합니다."</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g>은(는) 지원되지 않습니다."</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>에 대한 설정"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"엔진 설정 실행"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"기본 엔진"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"기본설정"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index 258b8eb7e441..430c8e28456b 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Колдонуучу: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Айрым демейкилер коюлду"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Демейкилер коюлган жок"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Кеп синтезаторунун жөндөөлөрү"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Текстти-оозекилөө"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Кеп ылдамдыгы"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Текст айтылчу ылдамдык"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Тил"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Тутум тилин колдонуу"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Тил тандалган жок"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Айтылган текст боюнча тилге тиешелүү үндү коёт"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Үлгүнү угуу"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Кепти синтездөөнүн кыскача көргөзмөсүн ойнотуу"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Үн дайындарын орнотуу"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Кеп синтезине керектүү үн дайындарын орнотуңуз"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Бул кепти синтездөө каражаты бардык айтыла турган текстти, анын ичинде сырсөздөр жана насыя карточкасынын номери сыяктуу жеке маалыматты, топтошу мүмкүн. Ал <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> каражатынан алынат. Бул кепти синтездөө каражаты колдонулсунбу?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Бул тилде текстти-оозекилөө үчүн иштеп турган интернет-байланыш керек."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Бул айтылганды синтездөөнүн мисалы"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Абалкы тилдин абалы"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> толук колдоого алынган"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> желеге туташууну талап кылат"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> колдоого алынган эмес"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> жөндөөлөрдү"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Жарак тууралоолорун ачуу"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Тандалган жарак"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Жалпы"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml
index ba29eabb9bdc..29b27b380f45 100644
--- a/packages/SettingsLib/res/values-lo-rLA/strings.xml
+++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"ຜູ່ໃຊ້: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"ຕັ້ງ​ບາງ​ຄ່າ​ເລີ່ມ​ຕົ້ນ​ແລ້ວ"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"ບໍ່ໄດ້ຕັ້ງຄ່າເລີ່ມຕົ້ນເທື່ອ"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"ການຕັ້ງຄ່າການປ່ຽນຂໍ້ຄວາມເປັນສຽງເວົ້າ"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"ການປ່ຽນຂໍ້ຄວາມເປັນສຽງ"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"ອັດຕາການເວົ້າ"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"ຄວາມໄວໃນການເວົ້າຂໍ້ຄວາມ"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ພາສາ"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"​ໃຊ້​ພາ​ສາ​ຂອງ​ລະ​ບົບ"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"ບໍ່ໄດ້ເລືອກພາສາ"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"ຕັ້ງຄ່າສຽງໃນພາສາທີ່ລະບຸສຳລັບຂໍ້ຄວາມທີ່ເວົ້າ"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"ຟັງຕົວຢ່າງ"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"ສະແດງການສາທິດສັ້ນໆກ່ຽວກັບການສັງເຄາະສຽງ"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"ຕິດຕັ້ງຂໍ້ມູນສຽງ"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"ຕິດຕັ້ງຂໍ້ມູນສຽງທີ່ຕ້ອງໃຊ້ສຳລັບການວິເຄາະສຽງ"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"ລະບົບການສັງເຄາະສຽງນີ້ ອາດເກັບກຳຂໍ້ຄວາມທຸກຢ່າງທີ່ຖືກປ່ຽນເປັນສຽງເວົ້າ ຮວມທັງຂໍ້ມູນສ່ວນໂຕເຊັ່ນ: ລະຫັດຜ່ານ ແລະໝາຍເລກບັດເຄຣດິດນຳ. ມັນມາຈາກລະບົບ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. ເປີດການນຳໃຊ້ລະບົບສັງເຄາະສຽງໂຕນີ້ບໍ່?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"ພາສານີ້ຕ້ອງໃຊ້ການເຊື່ອມຕໍ່ອິນເຕີເນັດ ເພື່ອການປ່ຽນຂໍ້ຄວາມເປັນສຽງເວົ້າ."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"ນີ້ແມ່ນຕົວຢ່າງການສັງເຄາະສຽງ"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"ສະຖານະພາສາເລີ່ມຕົ້ນ"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"ຮອງຮັບ <xliff:g id="LOCALE">%1$s</xliff:g> ເຕັມຮູບແບບ"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> ຕ້ອງການການເຊື່ອມຕໍ່ອິນເຕີເນັດ"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"ບໍ່ຮອງຮັບ <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"ການຕັ້ງຄ່າສຳລັບ <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"ເປີດການຕັ້ງຄ່າລະບົບສະເຄາະສຽງ"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"ລະບົບທີ່ຕ້ອງການ"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"ທົ່ວໄປ"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index c1758b0d54ed..32648388e26f 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Naudotojas: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Nustatyti kai kurie numatytieji nustatymai"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nenustatyta jokių numatytųjų nustatymų"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"„Teksto į kalbą“ nustatymai"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"„Teksto į kalbą“ išvestis"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Kalbėjimo greitis"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Greitis, kuriuo sakomas tekstas"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Kalba"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Naudoti sistemos kalbą"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Kalba nepasirinkta"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Nustato konkrečiai kalbai būdingą sakomo teksto balsą"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Klausytis pavyzdžio"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Paleisti trumpą kalbos sintezės demonstraciją"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Įdiegti balso duomenis"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Įdiegti balso duomenis, reikalingus kalbos sintezei"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Šis kalbos sintezės variklis gali rinkti visą įvedamą tekstą, įskaitant asmeninius duomenis, pvz., kredito kortelės numerius, išskyrus slaptažodžius. Tai vyksta dėl variklio <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Įgalinti šio kalbos sintezės variklio naudojimą?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Pasirinkus šią kalbą, teksto vertimo kalba išvesčiai būtinas veikiantis tinklo ryšys."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Tai yra kalbos sintezės pavyzdys"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Numatytoji kalbos būsena"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> visiškai palaikoma"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> būtinas tinklo ryšys"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> nepalaikoma"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"Tikrinama…"</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"„<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>“ nustatymai"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Paleisti variklio nustatymus"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Pageidaujamas variklis"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Bendra"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"Labai lėtas"</item>
+ <item msgid="4795095314303559268">"Lėtas"</item>
+ <item msgid="8903157781070679765">"Įprastas"</item>
+ <item msgid="164347302621392996">"Greitas"</item>
+ <item msgid="5794028588101562009">"Greitesnis"</item>
+ <item msgid="7163942783888652942">"Labai greitas"</item>
+ <item msgid="7831712693748700507">"Spartus"</item>
+ <item msgid="5194774745031751806">"Labai spartus"</item>
+ <item msgid="9085102246155045744">"Greičiausias"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 8dc762a8717a..6fbc46a01a1c 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Lietotājs: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Iestatīti daži noklusējumi"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nav iestatīti noklusējumi"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Teksta-runas iestatījumi"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Teksta-runas izvade"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Runas ātrums"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Teksta ierunāšanas ātrums"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Valoda"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Izmantot sistēmas valodu"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nav atlasīta valoda."</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Runātajam tekstam iestata valodai raksturīgu balsi"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Noklausīties piemēru"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Atskaņot īsu runas sintēzes demonstrāciju"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalēt balss datus"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalēt runas sintēzei nepieciešamos balss datus"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Lietojot šo runas sintēzes programmu, var tikt apkopots viss ierunātais teksts, tostarp tāda personīgā informācija kā paroles un kredītkaršu numuri. Tā ir no <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> programmas. Vai iespējot šīs runas sintēzes programmas lietošanu?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Lai izmantotu teksta pārveidošanu runā šajā valodā, ir nepieciešams aktīvs tīkla savienojums."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Šis ir runas sintēzes piemērs."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Noklusējuma valodas statuss"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"Lokalizācija <xliff:g id="LOCALE">%1$s</xliff:g> tiek pilnībā atbalstīta"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"Lokalizācijai <xliff:g id="LOCALE">%1$s</xliff:g> nepieciešams tīkla savienojums."</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Lokalizācija <xliff:g id="LOCALE">%1$s</xliff:g> netiek atbalstīta"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Programmas <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> iestatījumi"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Programmas iestatījumu palaišana"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Vēlamā programma"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Vispārīgi"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index 384c9b7b70a4..94a6716d7650 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Корисник: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Поставени се некои стандардни вредности"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Нема поставено стандардни вредности"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Подесувања на текст-во-говор"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Излез текст-во-говор"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Брзина на говор"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Брзина со која се кажува текстот"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Јазик"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Користете системски јазик"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Јазикот не е избран"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Поставува глас специфичен за јазикот за говорниот текст"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Слушни пример"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Пушти краток приказ на синтеза на говор"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Инсталирај гласовни податоци"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Инсталирај ги гласовните податоци потребни за синтеза на говор"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Овој софтвер за синтеза на говор може да го собере сиот текст што ќе се говори, вклучувајќи и лични податоци како што се лозинки и броеви на кредитни картички. Тоа го прави апликацијата <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Употреби го овој софтвер за синтеза на говор?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"За овој јазик е потребно поврување со мрежа што функционира на излез за текст-во-говор."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Ова е пример на синтеза на говор"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Статус на стандарден јазик"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> е целосно поддржан"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> бара мрежно поврзување"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> не е поддржано"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Подесувања на <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Стартувај подесувања на софтвер"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Претпочитан софтвер"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Општо"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml
index 2977e75a2283..18f29911a5b6 100644
--- a/packages/SettingsLib/res/values-ml-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"ഉപയോക്താവ്: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"സ്ഥിരമായ ചിലവ സജ്ജീകരിച്ചു"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"സ്ഥിരമായൊന്നും സജ്ജീകരിച്ചിട്ടില്ല"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"ടെക്‌സ്റ്റ്-ടു-സ്‌പീച്ച് ക്രമീകരണങ്ങൾ"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"ടെക്‌സ്റ്റ്-ടു-സ്‌പീച്ച് ഔട്ട്‌പുട്ട്"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"വായന നിരക്ക്"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"വാചകം പറയുന്ന വേഗത"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ഭാഷ"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"സി‌സ്റ്റം ഭാഷ ഉപയോഗിക്കുക"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"ഭാഷ തിരഞ്ഞെടുത്തിട്ടില്ല"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"സംഭാഷണ വാചകത്തിന് ഭാഷാ-നിർദ്ദിഷ്‌ട ശബ്ദം സജ്ജമാക്കുന്നു"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"ഒരു ഉദാഹരണം കേൾക്കുക"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"സംഭാഷണത്തിന്റെ ഒരു ഹ്രസ്വ പ്രകടനം പ്ലേ ചെയ്യുക"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"വോയ്‌സ് ഡാറ്റ ഇൻസ്റ്റാളുചെയ്യുക"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"സംഭാഷണ സിന്തസിസ്സിന് ആവശ്യമായ വോയ്‌സ് ഡാറ്റ ഇൻസ്റ്റാൾ ചെയ്യുക"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"പാസ്‌വേഡുകൾ, ക്രെഡിറ്റ് കാർഡ് നമ്പറുകൾ എന്നിവ പോലുള്ള വ്യക്തിഗതമായ ഡാറ്റയുൾപ്പെടെ നിങ്ങൾ സംസാരിക്കുന്ന എല്ലാ വാചകവും ഈ സംഭാഷണ സിന്തസിസ് എഞ്ചിന് ശേഖരിക്കാനായേക്കും. ഇത് <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> എഞ്ചിനിൽ നിന്നും വരുന്നു. ഈ സംഭാഷണ സിന്തസിസ് എഞ്ചിൻ ഉപയോഗിക്കുന്നത് പ്രവർത്തനക്ഷമമാക്കണോ?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"ടെക്‌സ്‌റ്റ്-ടു-സ്‌പീച്ച് ഔട്ട്‌പുട്ടിനായി ഈ ഭാഷയ്‌ക്ക് പ്രവർത്തിക്കുന്ന ഒരു നെറ്റ്‌വർക്ക് കണക്ഷൻ ആവശ്യമാണ്."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"സംഭാഷണം ഒരുമിച്ചുചേർക്കുന്നതിനുള്ള ഒരുദാഹരണമാണിത്"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"സ്ഥിര ഭാഷാ സ്ഥിതിവിവരക്കണക്കുകൾ"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> ഭാഷയെ പൂർണ്ണമായും പിന്തുണയ്‌ക്കുന്നു"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> ഭാഷയ്‌ക്ക് നെറ്റ്‌വർക്ക് കണക്ഷൻ ആവശ്യമാണ്"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> ഭാഷയെ പിന്തുണയ്‌ക്കുന്നില്ല"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> എന്നതിനായുള്ള ക്രമീകരണങ്ങൾ"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"എഞ്ചിൻ ക്രമീകരണങ്ങൾ സമാരംഭിക്കുക"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"തിരഞ്ഞെടുത്ത എഞ്ചിൻ"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"പൊതുവായ കാര്യങ്ങൾ"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml
index ed936276a8fc..77d272c2661a 100644
--- a/packages/SettingsLib/res/values-mn-rMN/strings.xml
+++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Хэрэглэгч: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Зарим үндсэн тохиргоонуудыг суулгасан"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Ямар ч үндсэн тохиргоог суулгаагүй байна"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Текст-ярианы тохиргоо"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Текст-яриа гаргах"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Ярианы түвшин"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Текстийг унших хурд"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Хэл"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Системийн хэлийг ашиглах"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Хэл сонгогдоогүй байна"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Ярианы текстүүдэд тухайн хэлэнд зориулсан хоолойг тохируулна"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Жишээ сонсох"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Яриа үүсгэх талаар богинохон жишээг тоглуулах"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Хоолойн өгөгдлийг суулгах"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Яриа үүсгэхэд шаардлагатай дууны өгөгдлийг суулгах"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Энэ яриа үүсгүүр нь нууц үг, зээлийн картын дугаар гэх мэт таны хувийн мэдээллийг оруулан унших бүх текстийг цуглуулах боломжтой. Үүнийг <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> үүсгүүрээс нийлүүлдэг. Энэ яриа үүсгүүрийн ашиглалтыг идэвхжүүлэх үү?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Энэ хэл нь текстээс дуунд хөрвүүлэхэд ажлын сүлжээний холболтыг шаарддаг."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Энэ бол яриа үүсгэх жишээ юм."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Үндсэн хэлний статус"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> бүрэн дэмжигдсэн"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> сүлжээнд хrequires network connection"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> дэмжигдээгүй байна"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>-н тохиргоо"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Үүсгүүрийн тохиргоог ажиллуулах"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Давуу үүсгүүр"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Ерөнхий"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml
index 3a05cb9a4a94..cb902a762ad9 100644
--- a/packages/SettingsLib/res/values-mr-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"वापरकर्ता: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"काही डीफॉल्‍ट सेट केले"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"कोणतेही डीफॉल्ट सेट केले नाही"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"टेक्स्ट-टू-स्पीच सेटिंग्ज"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"टेक्स्ट-टू-स्पीच आउटपुट"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"बोलण्याचा रेट"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"ज्या गतीने मजकूर बोलला जातो ती"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"भाषा"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"सिस्टम भाषा वापरा"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"भाषा निवडलेली नाही"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"बोललेल्या मजकुरासाठी भाषा-विशिष्ट आवाज सेट करते"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"उदाहरण ऐका"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"उच्चार संश्लेषणाचे एक छोटेसे प्रात्यक्षिक प्ले करा"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"व्हॉइस डेटा स्थापित करा"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"उच्चार संश्लेषणासाठी आवश्यक आवाज डेटा स्थापित करा"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"हे उच्चार संश्लेषण इंजिन संकेतशब्द आणि क्रेडिट कार्ड नंबर यासारख्या वैयक्तिक मजकुरासह, बोलला जाणारा सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. हे <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इंजिनवरून येते. या उच्चार संश्लेषण इंजिनचा वापर सक्षम करायचा?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"या भाषेस टेक्‍स्‍ट टू स्‍पीचसाठी एका नेटवर्क कनेक्शनची आवश्यकता आहे."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"हे उच्चार संश्लेषणाचे एक उदाहरण आहे"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"डीफॉल्ट भाषा स्थिती"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> पूर्णपणे समर्थित आहे"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> ला नेटवर्क कनेक्शनची आवश्यकता आहे"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> समर्थित नाही"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> साठी सेटिंग्ज"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"इंजिन सेटिंग्ज लाँच करा"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"प्राधान्यकृत इंजिन"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"सामान्य"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index b917ad08af7f..52bfc05cf1b0 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Pengguna: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Beberapa lalai ditetapkan"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Tiada lalai ditetapkan"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Tetapan teks kepada pertuturan"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Output teks ke pertuturan"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Kadar pertuturan"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Kelajuan pertuturan teks"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Bahasa"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Gunakan bahasa sistem"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Bahasa tidak dipilih"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Menetapkan suara khusus bahasa untuk teks pertuturan"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Dengar contoh"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Mainkan tunjuk cara singkat sintesis pertuturan"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Pasang data suara"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Pasang data suara yang diperlukan untuk sintesis pertuturan"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Enjin sintesis pertuturan ini mungkin boleh mengumpul semua teks yang akan dituturkan, termasuk data peribadi seperti kata laluan dan nombor kad kredit. Ia datang daripada enjin <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Dayakan penggunaan enjin sintesis pertuturan ini?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Bahasa ini memerlukan sambungan rangkaian yang berfungsi untuk output teks ke pertuturan."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Ini ialah contoh sintesis pertuturan."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status bahasa tetapan asal"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> disokong sepenuhnya"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> memerlukan sambungan rangkaian"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> tidak disokong"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"Menyemak…"</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Tetapan untuk <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Lancarkan tetapan enjin"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Enjin pilihan"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Umum"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"Sangat perlahan"</item>
+ <item msgid="4795095314303559268">"Perlahan"</item>
+ <item msgid="8903157781070679765">"Biasa"</item>
+ <item msgid="164347302621392996">"Laju"</item>
+ <item msgid="5794028588101562009">"Lebih laju"</item>
+ <item msgid="7163942783888652942">"Sangat laju"</item>
+ <item msgid="7831712693748700507">"Pantas"</item>
+ <item msgid="5194774745031751806">"Sangat pantas"</item>
+ <item msgid="9085102246155045744">"Paling laju"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 56adf2daa841..5307cf37a63d 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"သုံးစွဲသူ၊ <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"တချို့အားပုံမှတ်အဖြစ်သတ်မှတ်"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"ပုံမှန်သတ်မှတ်ထားခြင်းမရှိ"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"စာသားမှစကားပြောပြောင်း ဆက်တင်များ"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"စာသားမှ အသံထွက်စေခြင်း"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"စကားပြောနှုန်း"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"စာတမ်းအားပြောဆိုသော အမြန်နှုန်း"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ဘာသာစကား"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"စနစ်၏ ဘာသာစကားကို အသုံးပြုရန်"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"ဘာသာစကား မရွေးချယ်ထားပါ။"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"ဘာသာစကားကိုသတ်မှတ်မည်။ ပြောဆိုမည့်စာသားအတွက် သီးခြားအသံ"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"နမူနာကို နားထောင်မည်"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"အသံပေါင်းစပ်ခြင်းအတွက် တိုတောင်းသောသရုပ်ပြမှုကို ပြခြင်း"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"အသံဒေတာများကို ထည့်သွင်းခြင်း"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"စကားသံပေါင်းစပ်မှုအတွက်လိုအပ်သောအသံဒေတာအား ထည့်သွင်းမည်"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"ဤစကားသံပေါင်းစပ်အင်ဂျင်အားအသုံးပြုရာရာတွင် သင့်ကိုယ်ရေးအချက်အလက်များဖြစ်သော စကားဝှက်များနှင့် ကရက်ဒစ်ကဒ်နံပါတ်စသည်တို့အပါအဝင် သင်ပြောဆိုသောစာသားများအားလုံးကို ရယူသွားမည်ဖြစ်သည်။ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>အင်ဂျင်မှ လာပါသည်။ ဤစကားသံပေါင်းစပ်အင်ဂျင်ကို အသုံးပြုမည်လား?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"ဤဘာသာစကားသည် စာသားမှ အသံထွက်ရန် အလုပ်လုပ်သော ကွန်ရက်ချိတ်ဆက်မှု လိုအပ်သည်။"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"ဤသည်မှာ အသံတုလုပ်ခြင်း ၏ နမူနာတစ်ခုဖြစ်သည်။"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"လက်ရှိဘာသာစကားအခြေအနေ"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> သည်အပြည့်အ၀ အထောက်အကူပြုသည်။"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g>သည် ကွန်ရက်ဆက်သွယ်မှုလိုအပ်သည်"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> အတွက် မရသေးပါ"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"စစ်ဆေးနေပါသည်…"</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>အတွက် ဆက်တင်များ"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"အင်ဂျင်ဆက်တင်များကိုဖွင့်ခြင်း"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"ဦးစားပေးအင်ဂျင်"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"ယေဘုယျ"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"အလွန်နှေး"</item>
+ <item msgid="4795095314303559268">"နှေး"</item>
+ <item msgid="8903157781070679765">"ပုံမှန်"</item>
+ <item msgid="164347302621392996">"မြန်"</item>
+ <item msgid="5794028588101562009">"ပိုမြန်"</item>
+ <item msgid="7163942783888652942">"အလွန်မြန်"</item>
+ <item msgid="7831712693748700507">"သွက်သွက်"</item>
+ <item msgid="5194774745031751806">"အရမ်းသွက်"</item>
+ <item msgid="9085102246155045744">"အမြန်ဆုံး"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 0c0d66f0db6a..5e83f92c246e 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Bruker:<xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Noen standardvalg er angitt"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Ingen standardvalg er angitt"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Talesyntese-kontroller"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Tekst-til-tale"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Talehastighet"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Hvor raskt teksten leses"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Språk"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Bruk systemspråk"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Språk er ikke valgt"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Velger språkspesifikk stemme"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Lytt til et eksempel"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Spill en kort demonstrasjon av talesyntesen"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Installer stemmedata"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Installer nødvendige stemmedata for talesyntese"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Denne talesyntesemotoren kan samle inn all uttalt tekst, herunder personlige opplysninger som for eksempel passord og kredittkortnumre. Den er basert på motoren <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Vil du slå på denne talesyntesemotoren?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Dette språket krever en fungerende nettverkstilkobling for tekst-til-tale."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Dette er et eksempel på talesyntese."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status for standardspråk"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> støttes fullt ut"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> krever nettverkstilkobling"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> støttes ikke"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Innstillinger for <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Innstillinger for kjøring av motor"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Foretrukket motor"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Generelt"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml
index 4ca686085392..56c68d223ed8 100644
--- a/packages/SettingsLib/res/values-ne-rNP/strings.xml
+++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"प्रयोगकर्ता: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"केही पूर्वनिर्धारितहरू सेट गरिएका छन्"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"कुनै पूर्वनिर्धारित सेट गरिएको छैन"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"पाठ-वाचन सेटिङहरू"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"पाठ-बाट-वाणी उत्पादन"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"वाणी दर"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"पाठ वाचन हुने गति"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"भाषा"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"प्रणाली भाषा प्रयोग गर्नुहोस्"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"भाषा चयन गरिएको छैन"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"बोली पाठका लागि भाषा-विशेष आवाज सेट गर्दछ"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"एउटा उदाहरणलाई सुन्नुहोस्"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"वाणी संश्लेषणको एउटा छोटो प्रदर्शन बजाउनुहोस्"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"आवाज डेटा स्थापना गर्नुहोस्"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"वाणी संश्लेषणका लागि आवश्यक आवाज डेटा स्थापना गर्नुहोस्"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"यो वाणी संश्लेषण इन्जिनले पासवर्ड र क्रेडिट कार्ड नम्बर जस्ता निजी डेटासहित बोलिने सबै पाठ जम्मा गर्न सक्षम हुन सक्छ। यो <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इन्जिनबाट आउँछ। यो वाणी संश्लेषण इन्जिनको उपयोग सक्षम गर्नुहुन्छ?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"पाठ वाचकको आउटपुटका लागि यस भाषालाई काम गरिरहेको सञ्जाल जडान आवाश्यक पर्छ।"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"यो वाणी संश्लेषणको एउटा उदाहरण हो।"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"पूर्वनिर्धारित भाषाको वस्तुस्थिति"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> पूर्ण रूपले समर्थित छ"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> नेटवर्क जडान चाहिन्छ"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> समर्थित छैन"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>को लागि सेटिङ गर्दै"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"इन्जिन सेटिङहरू सुरुवात गर्नुहोस्"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"रुचाइएको इन्जिन"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"सामान्य"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index cae3e929bbb1..7e07a405fe37 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Gebruiker: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Enkele standaardwaarden ingesteld"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Geen standaardwaarden ingesteld"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Instellingen tekst-naar-spraak"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Spraakuitvoer"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Spreeksnelheid"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Snelheid waarmee de tekst wordt gesproken"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Taal"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Systeemtaal gebruiken"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Taal niet geselecteerd"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"De taalspecifieke stem voor de gesproken tekst instellen"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Luisteren naar een voorbeeld"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Een korte demonstratie van spraaksynthese afspelen"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Spraakgegevens installeren"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"De stemgegevens voor spraaksynthese installeren"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Deze engine voor spraaksynthese kan mogelijk alle tekst verzamelen die wordt gesproken, waaronder persoonlijke gegevens zoals wachtwoorden en creditcardnummers. Deze engine is afkomstig van de <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>-engine. Het gebruik van deze engine voor spraaksynthese inschakelen?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Deze taal heeft een werkende netwerkverbinding nodig voor tekst-naar-spraak-uitvoer."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Dit is een voorbeeld van spraaksynthese"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status van standaardtaal"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> wordt volledig ondersteund"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> heeft een netwerkverbinding nodig"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> wordt niet ondersteund"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"Controleren…"</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Instellingen voor <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Engine-instellingen openen"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Voorkeursengine"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Algemeen"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"Zeer langzaam"</item>
+ <item msgid="4795095314303559268">"Langzaam"</item>
+ <item msgid="8903157781070679765">"Normaal"</item>
+ <item msgid="164347302621392996">"Snel"</item>
+ <item msgid="5794028588101562009">"Sneller"</item>
+ <item msgid="7163942783888652942">"Zeer snel"</item>
+ <item msgid="7831712693748700507">"Vlug"</item>
+ <item msgid="5194774745031751806">"Zeer vlug"</item>
+ <item msgid="9085102246155045744">"Snelst"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml
index b31966381a06..c21185b06ca2 100644
--- a/packages/SettingsLib/res/values-pa-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"ਉਪਭੋਗਤਾ: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"ਕੁਝ ਡਿਫੌਲਟਸ ਸੈਟ ਕੀਤੇ"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"ਕੋਈ ਡਿਫੌਲਟਸ ਸੈਟ ਨਹੀਂ ਕੀਤੇ"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"ਟੈਕਸਟ-ਟੂ-ਸਪੀਚ ਸੈਟਿੰਗਾਂ"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"ਟੈਕਸਟ-ਟੂ-ਸਪੀਚ ਆਉਟਪੁਟ"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"ਸਪੀਚ ਰੇਟ"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"ਸਪੀਡ ਜਿਸਤੇ ਟੈਕਸਟ ਬੋਲਿਆ ਜਾਂਦਾ ਹੈ"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ਭਾਸ਼ਾ"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"ਸਿਸਟਮ ਭਾਸ਼ਾ ਵਰਤੋ"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"ਭਾਸ਼ਾ ਨਹੀਂ ਚੁਣੀ"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"ਬੋਲੇ ਗਏ ਟੈਕਸਟ ਲਈ ਭਾਸ਼ਾ-ਵਿਸ਼ੇਸ਼ ਵੌਇਸ ਸੈਟ ਕਰਦਾ ਹੈ"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"ਇੱਕ ਉਦਾਹਰਨ ਲਈ ਸੁਣੋ"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਦਾ ਇੱਕ ਛੋਟਾ ਪ੍ਰਦਰਸ਼ਨ ਪਲੇ ਕਰੋ"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"ਵੌਇਸ ਡਾਟਾ ਇੰਸਟੌਲ ਕਰੋ"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਲਈ ਲੁੜੀਂਦਾ ਵੌਇਸ ਡਾਟਾ ਇੰਸਟੌਲ ਕਰੋ"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"ਇਹ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਇੰਜਣ ਉਹ ਸਾਰਾ ਟੈਕਸਟ ਇਕੱਤਰ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੋ ਸਕਦਾ ਹੈ, ਜੋ ਬੋਲਿਆ ਜਾਏਗਾ, ਨਿੱਜੀ ਡਾਟਾ ਸਮੇਤ ਜਿਵੇਂ ਪਾਸਵਰਡ ਅਤੇ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ। ਇਹ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ਇੰਜਣ ਤੋਂ ਆਉਂਦਾ ਹੈ। ਕੀ ਇਸ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਇੰਜਣ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"ਇਸ ਭਾਸ਼ਾ ਲਈ ਟੈਕਸਟ-ਟੂ-ਸਪੀਚ ਆਉਟਪੁਟ ਲਈ ਇੱਕ ਚਾਲੂ ਨੈਟਵਰਕ ਕਨੈਕਸ਼ਨ ਦੀ ਲੋੜ ਹੈ।"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"ਇਹ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਦਾ ਇੱਕ ਉਦਾਹਰਨ ਹੈ"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"ਡਿਫੌਲਟ ਭਾਸ਼ਾ ਸਥਿਤੀ"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> ਪੂਰੀ ਤਰ੍ਹਾਂ ਸਮਰਥਿਤ ਹੈ"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> ਲਈ ਨੈਟਵਰਕ ਕਨੈਕਸ਼ਨ ਲੁੜੀਂਦਾ ਹੈ"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> ਲਈ ਸੈਟਿੰਗਾਂ"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"ਇੰਜਨ ਸੈਟਿੰਗਾਂ ਲੌਂਚ ਕਰੋ"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"ਤਰਜੀਹੀ ਇੰਜਣ"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"ਸਧਾਰਨ"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 7858201b08f9..b560d9d12d08 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Użytkownik: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Część ustawień domyślnych"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Brak ustawień domyślnych"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Zamiana tekstu na mowę"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Zamiana tekstu na mowę"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Szybkość mowy"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Szybkość czytania tekstu"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Język"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Użyj języka systemu"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nie wybrano języka"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Ustawia zależny od języka głos dla czytanych tekstów"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Posłuchaj przykładu"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Odtwórz krótką prezentację syntezy mowy"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Zainstaluj dane głosowe"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Zainstaluj dane głosowe wymagane do syntezy mowy"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Ten mechanizm syntezy mowy może gromadzić cały odczytywany tekst, w tym dane osobiste w postaci haseł i numerów kart kredytowych. Nazwa mechanizmu to <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Włączyć ten mechanizm syntezy mowy?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Do przetwarzania tekstu na mowę w tym języku wymagane jest działające połączenie sieciowe."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"To jest przykład syntezy mowy"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Stan domyślnego języka"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"Język <xliff:g id="LOCALE">%1$s</xliff:g> jest w pełni obsługiwany"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"Język <xliff:g id="LOCALE">%1$s</xliff:g> wymaga połączenia z siecią"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Język <xliff:g id="LOCALE">%1$s</xliff:g> nie jest obsługiwany"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Ustawienia <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Otwórz ustawienia mechanizmu"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Preferowany mechanizm"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Ogólne"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 93c4d104263f..91ba0b5bf5f6 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Usuário: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Alguns padrões definidos"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nenhum padrão definido"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Configurações da conversão de texto em voz"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Conversão de texto em voz"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de fala"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade em que o texto é falado"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma do sistema"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma não selecionado"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Define a voz específica do idioma para o texto falado"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Ouça um exemplo"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Reproduzir uma rápida demonstração da voz sintetizada"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalar dados de voz"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"É necessário instalar os dados de voz para a sintetização da fala"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Este mecanismo de síntese de fala pode coletar todo texto que será falado, inclusive dados pessoais como senhas e números de cartão de crédito. Ele é proveniente do mecanismo <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Deseja ativar o uso desse mecanismo de síntese de fala?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma requer uma conexão de rede ativa para a conversão de texto em voz."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Este é um exemplo de sintetização de voz."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status de idioma padrão"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> é totalmente suportada"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> requer conexão de rede"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> não é suportado"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Configurações para <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Iniciar configurações do mecanismo"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Mecanismo preferencial"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Gerais"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index e947352eab48..2d831d1ef123 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Utilizador: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Algumas predefinições definidas"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nenhuma predefinição definida"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Definições de texto para voz"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Saída de texto para voz"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de voz"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade a que o texto é falado"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizar idioma do sistema"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma não selecionado"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Define a voz do idioma específico para o texto lido"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Ouvir um exemplo"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Reproduzir uma breve demonstração de síntese de voz"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalar dados de voz"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalar os dados de voz necessários para a síntese de voz"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Este motor de síntese de discurso pode permitir a recolha de todo o texto que será falado, incluindo dados pessoais, como palavras-passe e números de cartão de crédito. O serviço é fornecido com o motor <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Permitir a utilização deste motor de síntese de discurso?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma requer uma ligação de rede ativa para uma saída de síntese de voz."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Exemplo de síntese de voz."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Estado do idioma predefinido"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> é totalmente suportado"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> necessita de ligação de rede"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> não é suportado"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Definições do <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Iniciar as definições do motor"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motor preferido"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Geral"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 93c4d104263f..91ba0b5bf5f6 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Usuário: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Alguns padrões definidos"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nenhum padrão definido"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Configurações da conversão de texto em voz"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Conversão de texto em voz"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de fala"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade em que o texto é falado"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma do sistema"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma não selecionado"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Define a voz específica do idioma para o texto falado"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Ouça um exemplo"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Reproduzir uma rápida demonstração da voz sintetizada"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalar dados de voz"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"É necessário instalar os dados de voz para a sintetização da fala"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Este mecanismo de síntese de fala pode coletar todo texto que será falado, inclusive dados pessoais como senhas e números de cartão de crédito. Ele é proveniente do mecanismo <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Deseja ativar o uso desse mecanismo de síntese de fala?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Este idioma requer uma conexão de rede ativa para a conversão de texto em voz."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Este é um exemplo de sintetização de voz."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status de idioma padrão"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> é totalmente suportada"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> requer conexão de rede"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> não é suportado"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Configurações para <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Iniciar configurações do mecanismo"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Mecanismo preferencial"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Gerais"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 96df0ebac15a..74f98e0aef76 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Utilizator: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Unele valori prestabilite sunt configurate"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nu este configurată nicio valoare prestabilită"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Setări text în vorbire"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Transformare text în vorbire"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Ritmul vorbirii"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Viteza cu care este vorbit textul"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Limbă"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizaţi limba sistemului"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nu ați selectat limba"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Setează vocea caracteristică limbii pentru textul vorbit"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Ascultați un exemplu"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Redați o demonstrație scurtă a sintetizării vorbirii"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalați date vocale"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalați datele vocale necesare pentru sintetizarea vorbirii"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Acest motor de sintetizare a vorbirii poate culege în întregime textul vorbit, inclusiv datele personale cum ar fi parolele și numerele cărților de credit. Metoda provine de la motorul <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Permiteți utilizarea acestui motor de sintetizare a vorbirii?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Pentru rezultatul transformării textului în vorbire pentru această limbă este necesară o conexiune de rețea care să funcţioneze."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Acesta este un exemplu de sintetizare a vorbirii"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Starea limbii prestabilite"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> este acceptată integral"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> necesită conexiune la rețea"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> nu este acceptată"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Setări pentru <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Lansați setările motorului"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motor preferat"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Preferințe generale"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index e2a4fc73c1b1..d116a3b2f5c4 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Пользователь: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Установлены некоторые настройки по умолчанию"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Настройки по умолчанию не установлены"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Настройки синтеза речи"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Синтез речи"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Скорость речи"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Скорость чтения текста"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Язык"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Язык системы"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Язык не выбран"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Выбор языка для чтения текста"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Прослушать пример"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Воспроизвести краткую демонстрацию синтезированной речи"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Установка голосовых данных"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Установить голосовые данные, необходимые для синтеза речи"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Данная система синтеза речи может записывать произносимые слова, включая личные данные, такие как пароли и номера кредитных карт. Это осуществляет система <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Разрешить использование этой системы синтеза речи?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Чтобы включить синтезатор речи для этого языка, необходимо подключение к Интернету."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Это пример синтеза речи."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Язык по умолчанию"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> поддерживается"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> поддерживается только при подключении к сети"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> не поддерживается"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Настройки синтеза речи"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Система по умолчанию"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Общие"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml
index 75302a0474dd..5fe0863963c5 100644
--- a/packages/SettingsLib/res/values-si-rLK/strings.xml
+++ b/packages/SettingsLib/res/values-si-rLK/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"පරිශීලකයා: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"ඇතැම් පෙරනිමියන් සකස් කර ඇත"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"පෙරනිමියන් සකසා නොමැත"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"පෙළ-සිට-කථාවට සැකසුම්"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"පෙළ-සිට-කථන ප්‍රතිදානය"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"කථන ශීඝ්‍රතාව"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"පෙළ කථා කරනා වේගය"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"භාෂාව"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"පද්ධති භාෂාව භාවිතා කරන්න"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"භාෂාව තෝරා ගෙන නැත"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"කථා කරන පෙළ සඳහා භාෂා-විශේෂිත හඬ සකසන්න"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"උදාහරණයකට සවන් දෙන්න"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"කථන සංස්ලෙෂණයේ කුඩා ආදර්ශනයක් ධාවනය කරන්න"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"හඬ දත්ත ස්ථාපනය කරන්න"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"කථන සංකලනයට අවශ්‍ය හඬ දත්ත ස්ථාපනය කරන්න"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"මෙම කථා සංස්ලේෂණ යන්ත්‍රයට කථා කරන සියළුම පෙළ එකතු කර ගත හැකිය, මුරපද සහ ණයපත් අංකද ඇතුලත්ව. එය පැමිණ ඇත්තේ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> යන්ත්‍රයෙනි. මෙම කථා සංස්ලේෂණ යන්ත්‍රයෙහි භාවිතය සබල කරන්නද?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"මෙම භාෂාවට පෙළ-සිට-කථනය ප්‍රතිදානය සඳහා වැඩ කරන ජාල සම්බන්ධතාවයක් අවශ්‍යයි."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"මෙය කථන සංස්ලේෂණයට උදාහරණයකි"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"සුපුරුදු භාෂා තත්වය"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> මුළුමනින්ම සහාය දක්වයි"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> සඳහා ජාල සම්බන්ධතාවයක් අවශ්‍යයි"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> සහාය නොදක්වයි"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> සඳහා සැකසුම්"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"එන්ජිම් සැකසීම් දියත් කරන්න"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"වරණ එන්ජිම"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"සාමාන්‍ය"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index d83c4bd4b2a3..7499fea3f1f1 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Používateľ: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Predvolená pre niektoré akcie"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nie je predvolená pre žiadne akcie"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Nastavenia prevodu textu na reč"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Výstup prevodu textu na reč"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Rýchlosť reči"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Rýchlosť hovoreného textu"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Jazyk"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Používať jazyk systému"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nebol vybratý jazyk"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Nastavenia jazyka hlasu pre hovorený text"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Vypočuť príklad"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Prehrať krátku ukážku syntézy reči"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Nainštalovať hlasové dáta"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Nainštalovať hlasové dáta potrebné na syntézu reči"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Nástroj na syntézu reči môže zhromažďovať všetok hovorený text, vrátane osobných údajov, ako sú heslá alebo čísla kreditných kariet. Je založený na nástroji <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Chcete aktivovať nástroj na syntézu reči?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"V prípade tohto jazyka je na prevod textu na rečový výstup potrebné pripojenie k sieti."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Toto je príklad syntézy reči"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Stav predvoleného jazyka"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"Jazyk <xliff:g id="LOCALE">%1$s</xliff:g> je plne podporovaný"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"Jazyk <xliff:g id="LOCALE">%1$s</xliff:g> vyžaduje pripojenie k sieti"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Jazyk <xliff:g id="LOCALE">%1$s</xliff:g> nie je podporovaný"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Spustiť nastavenia nástroja"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Preferovaný nástroj"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Všeobecné"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 5b8b1717d13d..294e9bba129b 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Uporabnik: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Nastavljene so nekatere privzete nastavitve"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Ni privzetih nastavitev"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Nastavitve pretvorbe besedila v govor"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Besedilo v govor"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Hitrost govora"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Hitrost govorjenega besedila"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Jezik"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Uporabi sistemski jezik"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Jezik ni izbran"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Nastavite glas, odvisen od jezika, za govorjeno besedilo"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Poslušaj primer"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Predvajaj kratko predstavitev sinteze govora"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Namesti glasovne podatke"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Namestite govorne datoteke, ki jih potrebujete za sintezo govora"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Ta mehanizem za sintezo govora bo morda lahko zbiral izgovorjeno besedilo, vključno z osebnimi podatki, kot so gesla in številke kreditnih kartic. Omogoča ga mehanizem <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Ali želite omogočiti uporabo tega mehanizma za sintezo govora?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Za pretvorbo besedila v govor potrebuje ta jezik delujočo omrežno povezavo."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"To je primer sinteze govora."</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Stanje privzetega jezika"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"Jezik <xliff:g id="LOCALE">%1$s</xliff:g> je v celoti podprt"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> zahteva omrežno povezavo"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Jezik <xliff:g id="LOCALE">%1$s</xliff:g> ni podprt"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Nastavitve za <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Zagon nastavitev mehanizma"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Prednostni mehanizem"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Splošno"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index d81d8c7aa240..609dce2242e1 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Përdoruesi: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Disa caktime me parazgjedhje"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Nuk janë caktuar parazgjedhje"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Cilësimet \"tekst-në-ligjërim\""</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Dalja \"tekst-në-ligjërim\""</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Shpejtësia e të folurit"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Shpejtësia me të cilën thuhet teksti"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Gjuha"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Përdor gjuhën e sistemit"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Nuk është përzgjedhur gjuha"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Cakton zërin specifik të gjuhës për tekstin e folur"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Dëgjo një shembull"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Luaj një demonstrim të shkurtër të sintezës së të folurit"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Instalo të dhënat e zërit"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Instalo të dhënat e zërit që kërkohen për sintezën e të folurit"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Ky motor i sintezës së të folurit mund të mbledhë të gjithë tekstin që do të flitet, duke përfshirë të dhëna personale si fjalëkalime dhe numra kartash krediti. Ai vjen nga motori <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Të aktivizohet përdorimi i këtij motori të sintezës së të folurit?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Kjo gjuhë kërkon një lidhje funksionale interneti për daljen \"tekst-në-ligjërim\"."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Ky është një shembull i sintezës së të folurit"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Statusi i gjuhës së parazgjedhur"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> mbështetet plotësisht"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> kërkon lidhje interneti"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> nuk mbështetet"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Cilësimet për \"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>\""</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Hap cilësimet e motorit"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Motori i preferuar"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Të përgjithshme"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 01a199345dcf..3f7d1fa1f661 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Корисник: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Подешене су неке подразумеване вредности"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Нису подешене подразумеване вредности"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Подешавања преласка из текста у говор"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Излаз за претварање текста у говор"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Брзина говора"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Брзина изговарања текста"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Језик"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Користи језик система"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Језик није изабран"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Подешава глас специфичан за језик намењен говорном тексту"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Послушај пример"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Пуштање кратке демонстрације синтезе говора"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Инсталирај гласовне податке"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Инсталирање говорних података потребних за синтезу говора"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Ова технологија за синтезу говора можда може да прикупља сав текст који ће бити изговорен, укључујући личне податке као што су лозинке и бројеви кредитних картица. То потиче из технологије <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Желите ли да омогућите коришћење ове технологије за синтезу говора?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"За овај језик је потребна исправна мрежна веза за претварање текста у говор."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Ово је пример синтезе говора"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Статус подразумеваног језика"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> је подржан у потпуности"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> захтева везу са мрежом"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> није подржан"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Подешавања за <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Покрени подешавања машине"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Жељена машина"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Опште"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 18b09f4911bc..d3d527960775 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Användare: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Några standardinställningar har angetts"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Inga standardinställningar har angetts"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Text-till-tal-inställningar"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Text-till-tal"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Talhastighet"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Talhastighet för texten"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Språk"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Använd systemspråk"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Inget språk valt"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Ange språkspecifik röst för den talade texten"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Lyssna på ett exempel"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Spela upp en kort demonstration av talsyntes"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Installera röstdata"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Installera de ljuddata som krävs för talsyntes"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Talsyntesmotorn kan samla in all text som ska talas, inklusive personlig information som lösenord och kreditkortsnummer. Den kommer från <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>-motorn. Vill du använda den här talsyntesmotorn?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Det krävs en fungerande nätverksanslutning för att text-till-tal ska fungera för det här språket."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Detta är ett exempel på talsyntes"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status för standardspråk"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> stöds"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> kräver nätverksanslutning"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> stöds inte"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Inställningar för <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Öppna inställningar för sökmotor"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Prioriterad sökmotor"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Allmänt"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 8b77301621d0..13c37906886a 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Mtumiaji: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Baadhi ya chaguo-msingi zimewekwa"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Hakuna chaguo-misingi zilizowekwa"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Mipangilio ya maandishi kwa hotuba"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Kubadilisha maandishi hadi usemi"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Kiwango cha usemaji"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Kasi ya kutamkwa kwa maneno"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Lugha"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Tumia lugha ya mfumo"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Lugha haijachaguliwa"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Huweka sauti maalum ya lugha inayolingana na yanayozungumzwa"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Sikiliza mfano"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Cheza onyesho fupi la usanisi usemaji"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Sakinisha data ya sauti"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Sakinisha data ya sauti inayohitajika kuunganisha usemi"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Hotuba hii inawezesha injini huenda ikaweza kukusanya maandishi ambayo yatazungumziwa, ikijumlisha data ya kibinafsi ya nenosiri na namba ya kaddi ya mkopo. Inatoka kwa injini ya <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> Wezesha matumizi ya hotuba hii iliyowezeshwa ya injini?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Lugha hii inahitaji muunganisho wa mtandao unaofanya kazi kwa towe ya maandishi hadi sauti."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Huu ni mfano wa usanisi usemaji"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Hali ya lugha chaguo-msingi"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> inaweza kutumiwa kikamilifu"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> inahitaji muunganisho wa mtandao"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> haiwezi kutumiwa"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Mipangilio ya <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Zindua mipangilio ya injini"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Injini inayofaa"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Kwa ujumla"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index b9bc93cac185..26ead855102a 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"பயனர்: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"சில இயல்புநிலைகள் அமைக்கப்பட்டன"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"இயல்புநிலைகள் எதுவும் அமைக்கப்படவில்லை"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"உரை வடிவத்திலிருந்து பேச்சுக்கான அமைப்பு"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"உரையிலிருந்து பேச்சாக மாற்றுதல்"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"பேச்சு வீதம்"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"பேசப்படும் உரையின் வேகம்"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"மொழி"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"முறைமையின் மொழியைப் பயன்படுத்து"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"மொழி தேர்ந்தெடுக்கப்படவில்லை"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"பேசப்படும் உரைக்கு மொழி சார்ந்த குரலை அமைக்கிறது"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"எடுத்துக்காட்டைக் கவனிக்கவும்"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"பேச்சு இணைப்பாக்கத்தின் சிறிய செயல்விளக்கத்தை இயக்கு"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"குரல் தரவை நிறுவு"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"பேச்சு இணைப்பாக்கத்திற்குத் தேவையான குரல் தரவை நிறுவவும்"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"இந்தப் பேச்சு இணைப்பாக்கல் இன்ஜின் ஆனது, கடவுச்சொற்கள் மற்றும் கிரெடிட் கார்டு எண்கள் போன்ற தனிப்பட்ட தகவல் உள்பட பேசப்படும் எல்லா உரையையும் சேகரிக்கலாம். இது <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> இன்ஜினிலிருந்து வந்துள்ளது. இந்தப் பேச்சு இணைப்பாக்கல் இன்ஜினை இயக்கவா?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"உரை வடிவத்திலிருந்து பேச்சு வெளியீட்டிற்காக, இந்த மொழிக்கு செயலில் உள்ள நெட்வொர்க் இணைப்பு தேவை."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"இது பேச்சு இணைப்பாக்கத்திற்கான எடுத்துக்காட்டாகும்"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"இயல்பு மொழியின் நிலை"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> முழுமையாக ஆதரிக்கப்படுகிறது"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> க்கு நெட்வொர்க் இணைப்பு அவசியமாகும்"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> ஆதரிக்கப்படவில்லை"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> க்கான அமைப்பு"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"இன்ஜின் அமைப்புகளைத் தொடங்கு"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"விருப்பத்தேர்வு"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"பொதுவானவை"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml
index 6f6694017e15..e5f6509a622b 100644
--- a/packages/SettingsLib/res/values-te-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-te-rIN/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"వినియోగదారు: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"కొన్ని డిఫాల్ట్‌లు సెట్ చేయబడ్డాయి"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"డిఫాల్ట్‌లు ఏవీ సెట్ చేయబడలేదు"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"వచనం నుండి ప్రసంగం సెట్టింగ్‌లు"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"వచనం నుండి ప్రసంగం అవుట్‌పుట్"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"ప్రసంగం రేట్"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"వచనాన్ని చదివి వినిపించాల్సిన వేగం"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"భాష"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"సిస్టమ్ భాషను ఉపయోగించు"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"భాష ఎంచుకోబడలేదు"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"చదవి వినిపించబడే వచనం కోసం భాష-నిర్దిష్ట వాయిస్‌ను సెట్ చేస్తుంది"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"ఒక ఉదాహరణ వినండి"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"ప్రసంగ సమన్వయం గురించి సంక్షిప్త ప్రదర్శనను ప్లే చేయి"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"వాయిస్ డేటాను ఇన్‌స్టాల్ చేయి"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"ప్రసంగ సమన్వయం కోసం అవసరమైన వాయిస్ డేటాను ఇన్‌స్టాల్ చేయండి"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"ఈ ప్రసంగ సమన్వయ ఇంజిన్ చదివి వినిపించబడే మొత్తం వచనాన్ని అలాగే పాస్‌వర్డ‌లు మరియు క్రెడిట్ కార్డు నంబర్‌ల వంటి వ్యక్తిగత డేటాను సేకరించగలదు. ఇది <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ఇంజిన్‌లో అందించబడుతుంది. ఈ ప్రసంగ సమన్వయ ఇంజిన్ యొక్క వినియోగాన్ని ప్రారంభించాలా?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"వచనం నుండి ప్రసంగం అవుట్‌పుట్ కోసం ఈ భాషకు పని చేస్తున్న నెట్‌వర్క్ కనెక్షన్ కావాలి."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"ఇది ప్రసంగ సమన్వయానికి ఉదాహరణ"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"డిఫాల్ట్ భాష స్థితి"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g>కి పూర్తి మద్దతు ఉంది"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g>కి నెట్‌వర్క్ కనెక్షన్ అవసరం"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g>కు మద్దతు లేదు"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> కోసం సెట్టింగ్‌లు"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"ఇంజిన్ సెట్టింగ్‌లను ప్రారంభించండి"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"ప్రాధాన్య ఇంజిన్"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"సాధారణం"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index c1febf2188e7..529d10f6aa9f 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"ผู้ใช้: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"ตั้งค่าเริ่มต้นไว้บางส่วน"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"ไม่ได้ตั้งค่าเริ่มต้น"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"การตั้งค่าการอ่านออกเสียงข้อความ"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"เอาต์พุตการอ่านออกเสียง"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"ความเร็วของคำพูด"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"ความเร็วในการพูดข้อความ"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"ภาษา"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"ใช้ภาษาของระบบ"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"ไม่ได้เลือกภาษา"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"ตั้งค่าเสียงในภาษาที่ระบุสำหรับข้อความที่ได้ยิน"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"ฟังตัวอย่าง"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"เล่นการสาธิตสั้นๆ เกี่ยวกับการสังเคราะห์เสียง"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"ติดตั้งข้อมูลเสียง"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"ติดตั้งข้อมูลเสียงที่ต้องใช้สำหรับการสังเคราะห์เสียง"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"โปรแกรมสังเคราะห์เสียงนี้อาจเก็บข้อความทั้งหมดที่ได้ยิน รวมถึงข้อมูลส่วนบุคคล เช่น รหัสผ่านและหมายเลขบัตรเครดิต โปรแกรมนี้มาจากโปรแกรม <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> คุณต้องการเปิดใช้งานโปรแกรมสังเคราะห์เสียงนี้หรือไม่"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"ภาษานี้ต้องใช้การเชื่อมต่อเครือข่ายซึ่งใช้การได้สำหรับการแปลงข้อความเป็นเสียงพูด"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"นี่เป็นตัวอย่างการสังเคราะห์เสียง"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"สถานะของภาษาเริ่มต้น"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"สนับสนุน<xliff:g id="LOCALE">%1$s</xliff:g>อย่างสมบูรณ์"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"ต้องมีการเชื่อมต่อเครือข่ายสำหรับ<xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"ไม่สนับสนุน<xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"การตั้งค่าสำหรับ <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"เปิดการตั้งค่าเครื่องมือ"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"เครื่องมือที่ต้องการ"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"ทั่วไป"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 4519773fa652..2102748327dd 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"User: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"May nakatakdang ilang default"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Walang nakatakdang mga default"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Mga setting ng text-to-speech"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Output ng text-to-speech"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Rate ng pagsasalita"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Bilis ng pagsambit sa teksto"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Wika"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Gamitin ang wika ng system"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Walang napiling wika"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Itinatakda ang boses na partikular sa wika para sa sinasambit na teksto"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Makinig sa isang halimbawa"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Mag-play ng maikling pagpapakita ng speech synthesis"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"I-install ang data ng boses"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"I-install ang data ng boses na kinakailangan para sa speech synthesis"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Maaaring makolekta ng speech synthesis engine na ito ang lahat ng teksto na sasabihin, kabilang ang personal na data tulad ng mga password at mga numero ng credit card. Nanggagaling ito mula sa <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> engine. Paganahin ang paggamit ng speech synthesis engine na ito?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Nangangailangan ang wikang ito ng gumaganang koneksyon sa network para sa text-to-speech na output."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Isa itong halimbawa ng speech synthesis"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Status ng default na wika"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"Ganap na sinusuportahan ang <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"Kailangan ng <xliff:g id="LOCALE">%1$s</xliff:g> ng koneksyon sa network"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"Hindi sinusuportahan ang <xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Mga setting para sa <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Ilunsad ang mga setting ng engine"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Ginustong engine"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Pangkalahatan"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 1834c64e4edb..67eed9dee3fb 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Kullanıcı: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Bazı varsayılan tercihler ayarlandı"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Hiçbir varsayılan tercih ayarlanmadı"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Metin-konuşma ayarları"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Metin-konuşma çıktısı"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Konuşma hızı"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Metnin konuşulduğu hız"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Dil"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Sistemin dilini kullan"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Dil seçilmedi"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Dil için tanımlı sesi, konuşulan metin için ayarlar"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Bir örnek dinleyin"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Konuşma sentezinin kısa bir sunumunu çal"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Ses verilerini yükle"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Konuşma sentezi için gereken ses verilerini yükle"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Bu konuşma sentezi motoru, şifreler ve kredi kartı numaraları gibi kişisel veriler de dahil konuşulan tüm metni toplayabilir. <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> motorundan gelmektedir. Bu konuşma sentezi motorunun kullanımı etkinleştirilsin mi?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Bu dil, metin-konuşma çıktısı için bir ağ bağlantısı gerektirir."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Bu bir konuşma sentezi örneğidir"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Varsayılan dil durumu"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> tamamen destekleniyor"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> ağ bağlantısı gerektiriyor"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> desteklenmiyor"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> ayarları"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Motor ayarlarını başlat"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Tercih edilen motor"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Genel"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index ca273ae94151..231b89b08619 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Користувач: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Налаштовано деякі значення за умовчанням"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Немає значень за умовчанням"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Налашт. синтезу мовлення"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Вивід синтезу мовлення з тексту"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Темп мовлення"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Швидкість відтворення тексту"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Мова"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Використовувати мову системи"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Мову не вибрано"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Устан. голос для відтворюваного тексту залежно від мови"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Прослухайте приклад"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Відтворити коротку демонстрацію синтезу мови"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Встановлення голосових даних"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Установіть потрібні голосові дані для синтезу мовлення"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Ця система синтезу мовлення може збирати всі відтворювані тексти, зокрема особисті дані, такі як паролі та номери кредитних карток. Вона походить від системи <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Увімкнути використання цієї системи синтезу мовлення?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Для виходу синтезу мовлення цією мовою потрібно мати з’єднання з Інтернетом."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Це приклад синтезу мовлення"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Статус мови за умовчанням"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g>: підтримується повністю"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g>: потрібне з’єднання з мережею"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g>: не підтримується"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"Перевірка…"</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Запускати налаштування системи"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Бажана система"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Загальні"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"Дуже повільно"</item>
+ <item msgid="4795095314303559268">"Повільно"</item>
+ <item msgid="8903157781070679765">"Звичайно"</item>
+ <item msgid="164347302621392996">"Швидко"</item>
+ <item msgid="5794028588101562009">"Швидше"</item>
+ <item msgid="7163942783888652942">"Дуже швидко"</item>
+ <item msgid="7831712693748700507">"Надзвичайно швидко"</item>
+ <item msgid="5194774745031751806">"Украй швидко"</item>
+ <item msgid="9085102246155045744">"Найшвидше"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index bdf50e09d662..788c95925d27 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"صارف: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"کچھ ڈیفالٹس سیٹ ہیں"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"کوئی ڈیفالٹس سیٹ نہیں ہیں"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"ٹیکسٹ ٹو اسپیچ کی ترتیبات"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"ٹیکسٹ ٹو اسپیچ آؤٹ پٹ"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"اسپیچ کی شرح"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"متن بولے جانے کی رفتار"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"زبان"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"سسٹم کی زبان استعمال کریں"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"زبان منتخب نہیں کی گئی"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"زبانی متن کیلئے زبان کیلئے مخصوص آواز کو سیٹ کرتا ہے"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"ایک مثال سنیں"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"اسپیچ سنتھیسس کا ایک مختصر مظاہرہ چلائیں"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"صوتی ڈیٹا انسٹال کریں"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"اسپیچ سنتھیسس کیلئے درکار صوتی ڈیٹا انسٹال کریں"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"یہ اسپیچ سنتھیسس انجن آپ کے ٹائپ کردہ سبھی متن کو جمع کر سکتا ہے، بشمول ذاتی ڈیٹا جیسے پاس ورڈز اور کریڈٹ کارڈ نمبرز۔ یہ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> انجن سے آتا ہے۔ اس اسپیچ سنتھیسس انجن کا استعمال فعال کریں؟"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"اس زبان کو ٹیکسٹ ٹو اسپیچ کے آؤٹ پٹ کیلئے ایک کام کرنے والے کنکشن کی ضرورت ہے۔"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"یہ تقریر کی ترکیب کی ایک مثال ہے"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"ڈیفالٹ زبان کا اسٹیٹس"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> مکمل طور پر تعاون یافتہ ہے"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> کو نیٹ ورک کنکشن کی ضرورت ہے"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> تعاون یافتہ نہیں ہے"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> کیلئے ترتیبات"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"انجن کی ترتیبات شروع کریں"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"ترجیحی انجن"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"عمومی"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index 7761b657236b..a02d23642a2e 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Foydalanuvchi: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Ba’zi birlamchi sozlamalar o‘rnatilgan"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Birlamchi sozlamalar o‘rnatilmagan"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Nutq sintezi sozlamalari"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Nutq sintezi"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Nutq tezligi"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Matnni o‘qish tezligi"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Til"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Tizim tili"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Til tanlanmagan"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Og‘zaki matn uchun tilga moslangan ovoz o‘rnatadi"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Namunani eshitish"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Qisqa nutq sintezi namunasini eshitish"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Ovoz ma’lumotlarini o‘rnatish"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Nutq sintezi uchun kerakli ovoz ma’lumotlarini o‘rnatish"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Ushbu nutq sintezi mexanizmi barcha yozgan matnlaringizni to‘plab olishi mumkin, jumladan kredit karta raqamlari va parollar kabi shaxsiy ma‘lumotlarni ham. U <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> mexanizmi bilan o‘rnatiladi. Ushbu nutq sintezi mexanizmidan foydalanilsinmi?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Bu til matnni nutqga o‘girish uchun faol Internet ulanishini talab qiladi."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Bu nutq sintezining misoli"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Birlamchi til"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> – to‘liq qo‘llab-quvvatlanadi"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> tili tarmoqqa ulanishi lozim"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> – qo‘llab-quvvatlanmaydi"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> sozlamalari"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Mexanizm sozlamalarini ishga tushirish"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Standart tizim"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Umumiy"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 3be20428c627..95451a856708 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Người dùng: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Đã đặt một số ứng dụng chạy mặc định"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Chưa đặt mặc định"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Cài đặt chuyển văn bản thành giọng nói"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Đầu ra v.bản thành giọng nói"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Tốc độ nói"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Tốc độ đọc văn bản"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Ngôn ngữ"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Sử dụng ngôn ngữ hệ thống"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Không thể chọn ngôn ngữ"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Đặt giọng nói ngôn ngữ cụ thể cho văn bản nói"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Nghe ví dụ"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Phát minh hoạ ngắn về tổng hợp giọng nói"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Cài đặt dữ liệu thoại"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Cài đặt dữ liệu thoại bắt buộc cho tổng hợp tiếng nói"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Công cụ tổng hợp tiếng nói này có thể thu thập tất cả nội dụng sẽ được nói, bao gồm dữ liệu cá nhân như mật khẩu và số thẻ tín dụng. Công cụ này xuất phát từ công cụ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Cho phép sử dụng công cụ tổng hợp tiếng nói này?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Ngôn ngữ này yêu cầu phải có kết nối mạng hoạt động để có thể phát âm thanh được chuyển từ văn bản sang giọng nói."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Đây là một ví dụ về tổng hợp tiếng nói"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Trạng thái ngôn ngữ mặc định"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> được hỗ trợ đầy đủ"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g> yêu cầu kết nối mạng"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"<xliff:g id="LOCALE">%1$s</xliff:g> không được hỗ trợ"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Cài đặt cho <xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Cài đặt chạy công cụ"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Công cụ ưu tiên"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Chung"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 0031d3932e70..5ca95da38bca 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"用户:<xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"已设置部分默认选项"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"未设置任何默认选项"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"文字转语音设置"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"文字转语音 (TTS) 输出"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"语速"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"文字转换成语音后的播放速度"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"语言"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"使用系统语言"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"未选择语言"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"设置文字转语音功能要使用的语言"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"收听示例"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"播放简短的语音合成示例"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"安装语音数据包"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"安装语音合成所需的数据包"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"此语音合成引擎能够收集语音中出现的所有信息,包括密码和信用卡号码之类的个人数据。此功能由 <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> 引擎提供。是否启用此语音合成引擎?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"您必须连接到网络才能使用文字转语音功能输出这种语言。"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"这是语音合成示例"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"默认语言状态"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"完全支持<xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"只有在连接到网络的情况下,才支持<xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"不支持<xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"“<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>”的设置"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"进行引擎设置"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"首选引擎"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"常规"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 2b41be3274cf..d6bd3c3fc3c1 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"使用者:<xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"已設定部分預設值"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"未設定預設值"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"文字轉語音設定"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"文字轉語音輸出"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"語音速率"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"文字轉語音的播放速度"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"語言"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"使用系統語言"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"未選取語言"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"設定朗讀文字所使用的語音語言"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"聆聽例子"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"播放簡短的語音合成例子"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"安裝語音資料"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"安裝語音合成所需的語音資料"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"這個語音合成引擎可能會收集您輸入的所有語音,包括密碼和信用卡號等個人資料。這個引擎來自「<xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>」引擎,是否要使用這個語音合成引擎?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"您需要操作正常的網絡連線,才能使用文字轉語音功能輸出這種語言。"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"這是語音合成例子"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"預設語言狀態"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"全面支援<xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"<xliff:g id="LOCALE">%1$s</xliff:g>需要網絡連線"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"不支援<xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"正在檢查…"</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> 設定"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"啟動引擎設定"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"首選引擎"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"一般設定"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"非常慢"</item>
+ <item msgid="4795095314303559268">"慢"</item>
+ <item msgid="8903157781070679765">"正常"</item>
+ <item msgid="164347302621392996">"快"</item>
+ <item msgid="5794028588101562009">"較快"</item>
+ <item msgid="7163942783888652942">"很快"</item>
+ <item msgid="7831712693748700507">"急速"</item>
+ <item msgid="5194774745031751806">"極快"</item>
+ <item msgid="9085102246155045744">"最快"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 6a1edf7c7d9e..94be638133c0 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -97,4 +97,38 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"使用者:<xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"已設定部分預設值"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"未設定預設值"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"文字轉語音設定"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"文字轉語音輸出"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"語音速率"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"文字轉語音的播放速度"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"語言"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"使用系統設定"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"未選取語言"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"設定文字轉語音功能要用的語言"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"聆聽範例"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"播放簡短的語音合成範例"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"安裝語音資料"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"安裝語音合成所需的語音資料"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"此語音合成引擎可能會收集您輸入的所有語音,包括密碼和信用卡號等個人資料。此引擎來自「<xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>」引擎,是否要使用此語音合成引擎?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"您必須連上網路才能使用文字轉語音輸出功能。"</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"您目前聽到的是我們的語音合成範例"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"預設語言狀態"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"完整支援<xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"需要網路連線才支援<xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"不支援<xliff:g id="LOCALE">%1$s</xliff:g>"</string>
+ <!-- no translation found for tts_status_checking (5339150797940483592) -->
+ <skip />
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> 設定"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"啟動引擎設定"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"偏好的引擎"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"一般"</string>
+ <!-- no translation found for tts_rate_entries:0 (6695494874362656215) -->
+ <!-- no translation found for tts_rate_entries:1 (4795095314303559268) -->
+ <!-- no translation found for tts_rate_entries:2 (8903157781070679765) -->
+ <!-- no translation found for tts_rate_entries:3 (164347302621392996) -->
+ <!-- no translation found for tts_rate_entries:4 (5794028588101562009) -->
+ <!-- no translation found for tts_rate_entries:5 (7163942783888652942) -->
+ <!-- no translation found for tts_rate_entries:6 (7831712693748700507) -->
+ <!-- no translation found for tts_rate_entries:7 (5194774745031751806) -->
+ <!-- no translation found for tts_rate_entries:8 (9085102246155045744) -->
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 83e3dc9ae020..a092a17bf0af 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -97,4 +97,39 @@
<string name="running_process_item_user_label" msgid="3129887865552025943">"Umsebenzisi: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Okunye okuzenzakalelayo okusethiwe"</string>
<string name="launch_defaults_none" msgid="4241129108140034876">"Akukho okuzenzakalelayo okusethiwe"</string>
+ <string name="tts_settings" msgid="8186971894801348327">"Izilungiselelo zombhalo-kuya-kunkulumo"</string>
+ <string name="tts_settings_title" msgid="1237820681016639683">"Umbhalo-uya-kokukhishwa ngokukhuluma"</string>
+ <string name="tts_default_rate_title" msgid="6030550998379310088">"Ukukala izwi"</string>
+ <string name="tts_default_rate_summary" msgid="4061815292287182801">"Isivinini leso umbhalo okhulunywe ngaso"</string>
+ <string name="tts_default_lang_title" msgid="8018087612299820556">"Ulimi"</string>
+ <string name="tts_lang_use_system" msgid="2679252467416513208">"Sebenzisa ulimi lwesistimu"</string>
+ <string name="tts_lang_not_selected" msgid="7395787019276734765">"Ulimi alukhethwanga"</string>
+ <string name="tts_default_lang_summary" msgid="5219362163902707785">"Ihlela izwi lolimi oluthize lombhalo okhulunyiwe"</string>
+ <string name="tts_play_example_title" msgid="7094780383253097230">"Lalela isibonelo"</string>
+ <string name="tts_play_example_summary" msgid="8029071615047894486">"Dlala umboniso omfushane wamazwi"</string>
+ <string name="tts_install_data_title" msgid="4264378440508149986">"Faka idatha yezwi"</string>
+ <string name="tts_install_data_summary" msgid="5742135732511822589">"Faka idatha yezwi edingekayo yamazwi ngamanye"</string>
+ <string name="tts_engine_security_warning" msgid="8786238102020223650">"Lenjini yokuqaphela amagama ingase ikwazi ukuqoqa wonke umbhalo ozokhulunywa, kuhlanganise idatha yomuntu siqu njengamaphasiwedi nezinombolo zekhadi lesikoloto. Iphuma <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> kwinjini. Vumela ukusebenzisa lenjini yokuqaphela amagama?"</string>
+ <string name="tts_engine_network_required" msgid="1190837151485314743">"Lolu limi ludinga ukuxhumana okusebenzayo kwenethiwekhi ekukhishweni kokuthunyelwe njengombhalo kunkulumo."</string>
+ <string name="tts_default_sample_string" msgid="4040835213373086322">"Lesi isibonelo sezwi"</string>
+ <string name="tts_status_title" msgid="7268566550242584413">"Isimo solimi oluzenzakalelayo"</string>
+ <string name="tts_status_ok" msgid="1309762510278029765">"I-<xliff:g id="LOCALE">%1$s</xliff:g> isekelwe ngokugcwele"</string>
+ <string name="tts_status_requires_network" msgid="6042500821503226892">"I-<xliff:g id="LOCALE">%1$s</xliff:g> idinga ukuxhumeka kwenethiwekhi"</string>
+ <string name="tts_status_not_supported" msgid="4491154212762472495">"I-<xliff:g id="LOCALE">%1$s</xliff:g> ayisekelwe"</string>
+ <string name="tts_status_checking" msgid="5339150797940483592">"Iyahlola..."</string>
+ <string name="tts_engine_settings_title" msgid="3499112142425680334">"Izilungiselelo ze-<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g>"</string>
+ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Faka izilungiselelo zenjini"</string>
+ <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Injini eyintandokazi"</string>
+ <string name="tts_general_section_title" msgid="4402572014604490502">"Okuvamile"</string>
+ <string-array name="tts_rate_entries">
+ <item msgid="6695494874362656215">"Phansi kakhulu"</item>
+ <item msgid="4795095314303559268">"Phansi"</item>
+ <item msgid="8903157781070679765">"Okujwayelekile"</item>
+ <item msgid="164347302621392996">"Sheshayo"</item>
+ <item msgid="5794028588101562009">"Ngokushesha"</item>
+ <item msgid="7163942783888652942">"Kushesha kakhulu"</item>
+ <item msgid="7831712693748700507">"Esheshisayo"</item>
+ <item msgid="5194774745031751806">"Esheshisa kakhulu"</item>
+ <item msgid="9085102246155045744">"Esheshisa kakhulukhulu"</item>
+ </string-array>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index d7dfdf857eaf..e28b2e5e530a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -258,6 +258,9 @@ public class WifiTracker {
mScanId++;
final List<ScanResult> newResults = mWifiManager.getScanResults();
for (ScanResult newResult : newResults) {
+ if (newResult.SSID == null || newResult.SSID.isEmpty()) {
+ continue;
+ }
mScanResultCache.put(newResult.BSSID, newResult);
mSeenBssids.put(newResult.BSSID, mScanId);
}
diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java
index 0d1ad197e3fa..e90a3b5a4824 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -136,9 +136,10 @@ public class BugreportReceiver extends BroadcastReceiver {
// EXTRA_TEXT should be an ArrayList, but some clients are expecting a single String.
// So, to avoid an exception on Intent.migrateExtraStreamToClipData(), we need to manually
// create the ClipData object with the attachments URIs.
- intent.putExtra(Intent.EXTRA_TEXT, SystemProperties.get("ro.build.description"));
- final ClipData clipData = new ClipData(
- null, new String[] { mimeType },
+ String messageBody = String.format("Build info: %s\nSerial number:%s",
+ SystemProperties.get("ro.build.description"), SystemProperties.get("ro.serialno"));
+ intent.putExtra(Intent.EXTRA_TEXT, messageBody);
+ final ClipData clipData = new ClipData(null, new String[] { mimeType },
new ClipData.Item(null, null, null, bugreportUri));
clipData.addItem(new ClipData.Item(null, null, null, screenshotUri));
intent.setClipData(clipData);
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 0e31d8dc9394..329e395fa4fb 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Sien hulle voordat jy ontsluit"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nee dankie"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Stel op"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Sien alles"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Versteek alles"</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">"Beëindig nou"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Vou uit"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Vou in"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Skerm is vasgespeld"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Dit hou dit in sig totdat jy dit ontspeld. Raak en hou Terug om dit te ontspeld."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Het dit"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nee, dankie"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Versteek <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Weier"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is die volumedialoog"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Raak om die oorspronklike terug te stel."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Jy gebruik tans jou werkprofiel"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Stelsel-UI-ontvanger"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Wys persentasie van ingebedde battery"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index ec6ec93722a3..8999d7c25190 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"ከመክፈትዎ በፊት ይመልከቷቸው"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"አይ፣ አመሰግናለሁ"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"አዋቅር"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"ሁሉንም ይመልከቱ"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"ሁሉንም ደብቅ"</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">"አሁን ጨርስ"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"አስፋ"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"ሰብስብ"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"ማያ ገጽ ተሰክቷል"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"ይህ እስከሚነቅሉት ድረስ በዕይታ ውስጥ ያቆየዋል። እንዲነቀል ለማድረግ ተመለስን ነካ አድርገው ይያዙት።"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"ገባኝ"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"አይ፣ አመሰግናለሁ"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ይደበቅ?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"ከልክል"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> የድምጽ መጠን መገናኛው ነው"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"የመጀመሪያውን ወደነበረበት ለመመለስ ይንኩ።"</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">"፣"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"የስራ መገለጫዎን እየተጠቀሙ ነው"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"የስርዓት በይነገጽ መቃኛ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"የተቀላቀለ የባትሪ አጠቃቀም መቶኛ አሳይ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 02fc3fec2cc9..dbfc287fe978 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -390,15 +390,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"الاطلاع عليها قبل إلغاء القفل"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"لا، شكرًا"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"إعداد"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"عرض الكل"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"إخفاء الكل"</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">"إنهاء الآن"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"توسيع"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"تصغير"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"تم تثبيت الشاشة"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"يساعد هذا على استمرار العرض حتى يتم إلغاء التثبيت. ويمكنك لمس \"رجوع\" مع الاستمرار لإلغاء التثبيت."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"حسنًا"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"لا، شكرًا"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"هل تريد إخفاء <xliff:g id="TILE_LABEL">%1$s</xliff:g>؟"</string>
@@ -409,6 +406,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"رفض"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> هو مربع حوار مستوى الصوت"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"المس لاستعادة الإعداد الأصلي."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"أنت تستخدم ملفك الشخصي للعمل"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"أداة ضبط واجهة مستخدم النظام"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"عرض نسبة البطارية المدمجة"</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index aba22f81c6a8..fb92d6b39fe9 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Kiliddən çıxarmadan öncə onları görün"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Yox, çox sağ olun"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Quraşdırın"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Hamısına baxın"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Hamısını gizlədin"</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">"İndi qurtarın"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Genişləndirin"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Yığcamlaşdırın"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekrana sancaq taxıldı"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri düyməsinə toxunun və saxlayın."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Anladım!"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Yox, çox sağ olun"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> gizlədilsin?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rədd et"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> proqramı səs səviyyəsi dialoqudur"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Orijinalı bərpa etmək üçün toxun."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"İş profilinizi istifadə edirsiniz"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Daxil batareya faizini göstərin"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 50ac61f8847b..09717536522d 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Вижте известията, преди да отключите"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Няма нужда"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Настройване"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Преглед на всичко"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Скриване на всичко"</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">"Прекратяване сега"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Разгъване"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Свиване"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Екранът е фиксиран"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Така екранът ще се показва, докато не го освободите с докосване и задържане на бутона за връщане назад."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Разбрах"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Не, благодаря"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Да се скрие ли „<xliff:g id="TILE_LABEL">%1$s</xliff:g>“?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Отказване"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> изпълнява ролята на диалоговия прозорец за силата на звука"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Докоснете, за да възстановите оригинала."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Използвате служебния си потребителски профил"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Тунер на системния потребителски интерфейс"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Показване на процента на вградената батерия"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index f32cfcc85dc5..afd4ac431be8 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"আপনি আনলক করার আগে ওগুলো দেখুন"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"না থাক"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"সেট আপ"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"সবগুলি দেখুন"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"সবগুলি লুকান"</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">"এখন সমাপ্ত করুন"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"প্রসারিত করুন"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"সঙ্কুচিত করুন"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"স্ক্রীন পিন করা হয়েছে"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"এটি আপনি আনপিন না করা পর্যন্ত এটিকে প্রদর্শিত করবে৷ আনপিন করতে \'ফিরুন\' এ স্পর্শ করে ধরে রাখুন৷"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"বুঝেছি"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"না থাক"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> লুকাবেন?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"প্রত্যাখ্যান করুন"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> হল ভলিউম ডায়লগ"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"আসলটি পুনঃস্থাপন করতে স্পর্শ করুন৷"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"আপনি আপনার কাজের প্রোফাইল ব্যবহার করছেন"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"সিস্টেম UI টিউনার"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"এম্বেড করা ব্যাটারির শতকরা হার দেখায়"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 429f70bf112a..32617edfa99a 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Mostra-les abans de desbloquejar"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"No"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configura"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Mostra-les totes"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Amaga-les totes"</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">"Finalitza ara"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Amplia"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Replega"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"La pantalla està fixada"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Continuarà a la visualització fins que n\'anul·lis la fixació. Per fer-ho, toca i mantén premut el botó Enrere."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"D\'acord"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"No, gràcies"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vols amagar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Denega"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> és el diàleg de volum"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toca per restaurar l\'original."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estàs utilitzant el perfil professional"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Personalitzador d\'interfície d\'usuari"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostra el percentatge de la bateria inserit"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index ee77cf9dad53..7d80a24b07d1 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -152,9 +152,7 @@
<string name="accessibility_airplane_mode" msgid="834748999790763092">"Režim Letadlo."</string>
<string name="accessibility_no_sims" msgid="3957997018324995781">"Není vložena SIM karta"</string>
<string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"Probíhá změna sítě operátora."</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
- <skip />
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"Stav baterie: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Systémová nastavení."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Oznámení."</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Vymazat oznámení."</string>
@@ -390,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Můžete si je přečíst před odemčením obrazovky."</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ne, děkuji"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Nastavit"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Zobrazit vše"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Skrýt vše"</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">"Ukončit"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Rozbalit"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Sbalit"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Obrazovka je připnuta"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Obsah bude připnut v zobrazení, dokud jej neuvolníte. Uvolníte jej stisknutím a podržením tlačítka Zpět."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Rozumím"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Ne, děkuji"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Skrýt <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -409,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmítnout"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialog hlasitosti"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Používáte pracovní profil"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Nástroj na ladění uživatelského rozhraní systému"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Zobrazovat vložené procento nabití baterie"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f749756d8e1f..a40eecf7dfe0 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Se dem, før du låser op"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nej tak"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Konfigurer"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Se alle"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Skjul alle"</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">"Afslut nu"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Udvid"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Skjul"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Skærmen er fastgjort"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Dette fastholder skærmen i visningen, indtil du frigør den. Tryk på Tilbage, og hold fingeren nede for at frigøre skærmen."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"OK, det er forstået"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nej tak"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Afvis"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er dialogboksen for lydstyrke"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Tryk for at gendanne originalen."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du bruger din arbejdsprofil"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Vis procent for det indbyggede batteri"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index cfaecaf4b0e6..cd6480d81ef0 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Vor dem Entsperren anzeigen"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nein danke"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Einrichten"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Alle anzeigen"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Alle ausblenden"</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">"Jetzt beenden"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Maximieren"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Minimieren"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Bildschirm ist fixiert"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Der Bildschirm wird solange angezeigt, bis Sie die Fixierung aufheben. Berühren und halten Sie \"Zurück\", wenn Sie die Fixierung aufheben möchten."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nein danke"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ausblenden?"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ablehnen"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> regelt die Lautstärke."</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Zum Wiederherstellen des Originals hier tippen"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Sie verwenden Ihr Arbeitsprofil."</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Eingebettete Akku-Prozentzahl anzeigen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6fc1b594f7c7..1fda559418eb 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Εμφάνιση πριν το ξεκλείδωμα"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Όχι"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Ρύθμιση"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Εμφάνιση όλων"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Aπόκρυψη όλων"</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">"Τερματισμός τώρα"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Ανάπτυξη"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Σύμπτυξη"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Η οθόνη καρφιτσώθηκε"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Με αυτόν τον τρόπο παραμένει σε προβολή έως ότου την ξεκαρφιτσώσετε. Αγγίξτε παρατεταμένα το στοιχείο επιστροφής για να την ξεκαρφιτσώσετε."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Το κατάλαβα"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Όχι"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Απόκρυψη <xliff:g id="TILE_LABEL">%1$s</xliff:g>;"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Απόρριψη"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> αποτελεί το παράθυρο διαλόγου ελέγχου έντασης"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Αγγίξτε για επαναφορά αρχικού."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Χρησιμοποιείτε το προφίλ εργασίας σας"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Εμφάνιση ποσοστού ενσωματωμένης μπαταρίας"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index ffdc3af75091..1e74e60d79cd 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"See them before you unlock"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"No, thanks"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Setup"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"See all"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Hide all"</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">"End now"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Expand"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Collapse"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"This keeps it in view until you unpin. Touch and hold Back to unpin."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"No, thanks"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Hide <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"You\'re using your work profile"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index ffdc3af75091..1e74e60d79cd 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"See them before you unlock"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"No, thanks"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Setup"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"See all"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Hide all"</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">"End now"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Expand"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Collapse"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"This keeps it in view until you unpin. Touch and hold Back to unpin."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"No, thanks"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Hide <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"You\'re using your work profile"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index ffdc3af75091..1e74e60d79cd 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"See them before you unlock"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"No, thanks"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Setup"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"See all"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Hide all"</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">"End now"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Expand"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Collapse"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Screen is pinned"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"This keeps it in view until you unpin. Touch and hold Back to unpin."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"No, thanks"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Hide <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Deny"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is the volume dialogue"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Touch to restore the original."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"You\'re using your work profile"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Show embedded battery percentage"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index d4bb0a661259..a11ebfa54507 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -150,9 +150,7 @@
<string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avión"</string>
<string name="accessibility_no_sims" msgid="3957997018324995781">"Sin tarjeta SIM"</string>
<string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"Cambio de proveedor de red"</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
- <skip />
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"Batería <xliff:g id="NUMBER">%d</xliff:g> por ciento"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Configuración del sistema"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificaciones"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Eliminar notificación"</string>
@@ -388,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ver antes de desbloquear"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"No"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configurar"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Ver todas"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ocultar todas"</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">"Finalizar ahora"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Expandir"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Contraer"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Pantalla fija"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Esta función mantiene la pantalla visible hasta que dejes de fijarla. Mantén presionado el botón Atrás para dejar de fijar."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Entendido"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"No, gracias"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"¿Ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rechazar"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen."</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar el original."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estás usando tu perfil de trabajo"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador de IU del sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentaje de la batería integrada"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index d3cae624ac16..aa4fd5637b0c 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ver antes de desbloquear"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"No, gracias"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configurar"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Ver todas"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ocultar todas"</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">"Finalizar ahora"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Mostrar"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Ocultar"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Pantalla fijada"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"La pantalla se mantendrá visible hasta que dejes de fijarla. Para dejar de fijarla, mantén pulsado el botón de retroceso."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Entendido"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"No, gracias"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"¿Ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rechazar"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> es el cuadro de diálogo de volumen"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar la versión original."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">"y"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estás usando tu perfil de trabajo"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Configurador de IU del sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentaje de batería insertado"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 0dfbdfc6e86d..655ee5b53b2b 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Näete neid enne avamist"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Tänan, ei"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Seadistus"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Kuva kõik"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Peida kõik"</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">"Lõpeta nüüd"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Laiendamine"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Ahendamine"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekraan on kinnitatud"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"See hoiab selle kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppu Tagasi."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Selge"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Tänan, ei"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Kas peita <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Keela"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on helitugevuse dialoog"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Originaali taastamiseks puudutage."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Kasutate oma tööprofiili"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Süsteemi kasutajaliidese tuuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Kuva lisatud akutaseme protsent"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 769164dcd65e..3a24cd190374 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ikusi desblokeatu baino lehen"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ez, eskerrik asko"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Konfiguratu"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Ikusi guztiak"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ezkutatu guztiak"</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">"Amaitu"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Zabaldu"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Tolestu"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Pantaila ainguratuta dago"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki ukituta \"Atzera\" botoia."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Ados"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Ez, eskerrik asko"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ezkutatu nahi duzu?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ukatu"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> da bolumenaren leihoa"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Ukitu jatorrizkora leheneratzeko"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Work profila erabiltzen ari zara"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sistemako erabiltzaile-interfazearen konfiguratzailea"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Erakutsi txertatutako bateriaren ehunekoa"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 6d9d43f7a448..f62ca0215e69 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"قبل از باز کردن قفل آنها را مشاهده کنید"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"نه سپاسگزارم"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"راه‌اندازی"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"مشاهده همه"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"پنهان کردن همه"</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">"اکنون به پایان برسد"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"بزرگ کردن"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"کوچک کردن"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"صفحه نمایش پین شد"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"در نما نگه‌داشته می‌شود تا اینکه پین را بردارید. برای برداشتن پین، «برگشت» را لمس کنید و نگه‌دارید."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"متوجه شدم"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"نه سپاسگزارم"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> مخفی شود؟"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"اجازه ندارد"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> کنترل‌کننده صدا است"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"برای بازیابی کنترل‌کننده اصلی، لمس کنید."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"درحال استفاده از نمایه کاری‌تان هستید"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"تنظیم‌کننده واسط کاربری سیستم"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"نمایش درصد شارژ باتری جاسازی شده"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 79bf369a129f..f1974ca995a6 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Näytä ennen lukituksen avaamista"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ei kiitos"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Määritä asetukset"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Näytä kaikki"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Piilota kaikki"</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">"Lopeta nyt"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Laajenna."</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Tiivistä."</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Näyttö on kiinnitetty"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Tämä pitää sen näkyvissä, kunnes peruutat kiinnityksen. Peruuta kiinnitys koskettamalla Edellinen-kohtaa pitkään."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Selvä"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Ei kiitos"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Piilotetaanko <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Estä"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> on äänenvoimakkuusvalinta."</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Palauta alkuperäinen koskettamalla."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Käytät työprofiilia."</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Näytä akun varaus kuvakkeessa"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 605e4c5bd089..a100cbfe228b 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Afficher les notifications avant de déverrouiller l\'appareil"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Non, merci"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configurer"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Tout afficher"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Tout masquer"</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">"Arrêter maintenant"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Développer"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Réduire"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"L\'écran est épinglé"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Cet écran est épinglé jusqu\'à ce que vous annuliez l\'opération. Pour annuler l\'épinglage, maintenez le doigt sur « Retour »."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Non, merci"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Masquer <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuser"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Touchez pour restaurer l\'original."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Vous utilisez votre profil professionnel."</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Afficher le pourcentage intégré de charge"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 6beed78e2cc4..8f6205a9e55f 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Afficher les notifications avant de déverrouiller l\'appareil"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Non, merci"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configurer"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Tout afficher"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Tout masquer"</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">"Arrêter maintenant"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Développer"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Réduire"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Écran épinglé"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Cet écran est épinglé jusqu\'à l\'annulation de l\'opération. Pour annuler l\'épinglage, appuyez de manière prolongée sur \"Retour\"."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Non, merci"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Masquer <xliff:g id="TILE_LABEL">%1$s</xliff:g> ?"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuser"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> correspond à la boîte de dialogue du volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Appuyez pour restaurer l\'interface d\'origine."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Vous utilisez votre profil professionnel."</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Afficher le pourcentage intégré de la batterie"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 9a66d879c5c6..8d3a9f8c447a 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Consúltaas antes de desbloquear"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Non grazas"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configurar"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Ver todo"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ocultar todo"</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">"Finalizar agora"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Ampliar"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Contraer"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"A pantalla está fixada"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"A pantalla manterase visible ata que anules a fixación. Para facelo, mantén premido Atrás."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"De acordo"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Non, grazas"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Queres ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Denegar"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é o cadro de diálogo de volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toca para restaurar o orixinal."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estás usando o perfil de traballo"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Configurador da IU do sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentaxe de batería inserida"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index fe604484079f..9ecaa75c087d 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"તમે અનલૉક કરો તે પહેલાં તેમને જુઓ"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"નહીં આભાર"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"સેટ અપ"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"બધું જુઓ"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"બધું છુપાવો"</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">"હવે સમાપ્ત કરો"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"વિસ્તૃત કરો"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"સંકુચિત કરો"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"સ્ક્રીન પિન કરેલ છે"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"તમે જ્યાં સુધી અનપિન કરશો નહીં ત્યાં સુધી આ તેને દૃશ્યમાં રાખે છે. અનપિન કરવા માટે પાછાં ને ટચ કરો અને પકડી રાખો."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"સમજાઈ ગયું"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"નહીં આભાર"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ને છુપાવીએ?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"નકારો"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> એ વૉલ્યૂમ સંવાદ છે"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"મૂળને પુનઃસ્થાપિત કરવા માટે ટચ કરો."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"તમે તમારી કાર્ય પ્રોફાઇલનો ઉપયોગ કરી રહ્યાં છો"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"સિસ્ટમ UI ટ્યૂનર"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"એમ્બેડ કરેલ બૅટરી ટકા બતાવો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index a433ca51d736..62ef6064e8c0 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"आपके द्वारा उन्हें अनलॉक किए जाने से पहले देखें"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"नहीं धन्यवाद"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"सेट करें"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"सभी देखें"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"सभी छिपाएं"</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">"अब समाप्त करें"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"विस्तृत करें"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"संक्षिप्त करें"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"स्‍क्रीन पिन कर दी गई है"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"इससे वह तब तक दृश्‍य में बना रहता है जब तक कि आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए वापस जाएं को स्‍पर्श करके रखें."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"समझ लिया"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"नहीं, रहने दें"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> को छिपाएं?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"अस्वीकार करें"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद है"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"मूल वॉल्यूम को फिर से लाने के लिए स्पर्श करें."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"आप अपनी कार्य प्रोफ़ाइल का उपयोग कर रहे हैं"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"सिस्टम UI ट्यूनर"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"एम्बेड किया गया बैटरी प्रतिशत दिखाएं"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index b72ac3d56bfd..c4a10cc78866 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -387,15 +387,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Pogledajte ih prije otključavanja"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ne, hvala"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Postavi"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Pokaži sve"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Sakrij sve"</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">"Prekini sada"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Proširivanje"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Sažimanje"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Zaslon je prikvačen"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite i držite Natrag da biste ga otkvačili."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Shvaćam"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Ne, hvala"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Želite li sakriti pločicu <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -406,6 +403,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odbij"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> predstavlja dijaloški okvir za upravljanje glasnoćom"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Dodirnite da biste vratili izvorno."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Upotrebljavate radni profil"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Ugađanje korisničkog sučelja sustava"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Prikaži ugrađeni postotak baterije"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index d27813aca312..f8c88c94c721 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Már a képernyőzár feloldása előtt megtekintheti őket"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nem, köszönöm"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Beállítás"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Az összes megjelenítése"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Az összes elrejtése"</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">"Befejezés most"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Kibontás"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Összecsukás"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"A képernyő rögzítve van"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva a Vissza lehetőséget."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Értem"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nem, köszönöm"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Elrejti ezt: <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Elutasítás"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás kezeli a hangerőt"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Érintse meg az eredeti érték visszaállításához."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"A munkaprofilt használja"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Kezelőfelület-hangoló"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"A beépített akkumulátor töltöttségi szintjének megjelenítése"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 125b19da1291..784008d4ad21 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Տեսեք դրանք մինչև ապակողպելը"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ոչ, շնորհակալություն"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Կարգավորել"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Տեսնել բոլորը"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Թաքցնել բոլորը"</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">"Ավարտել"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Ընդարձակել"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Կոծկել"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Էկրանն ամրացված է"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Էկրանը կմնա տեսադաշտում, մինչև այն ապամրացնեք: Ապամրացնելու համար հպեք և պահեք Հետ կոճակը:"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Հասկանալի է"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Ոչ, շնորհակալություն"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Թաքցնե՞լ <xliff:g id="TILE_LABEL">%1$s</xliff:g>-ը:"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Մերժել"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ձայնի ուժգնության երկխոսության հավելված է"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Դիպչեք՝ սկզբնօրինակը վերականգնելու համար:"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Դուք օգտագործում եք ձեր աշխատանքային պրոֆիլը"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Համակարգի ՕՄ-ի կարգավորիչ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Ցուցադրել ներկառուցված մարտկոցի տոկոսայնությունը"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 1370ef402f82..fd308343522e 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Lihat sebelum membuka kunci"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Tidak"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Siapkan"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Lihat semua"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Sembunyikan semua"</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">"Akhiri sekarang"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Luaskan"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Ciutkan"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Layar dipasangi pin"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Ini akan terus ditampilkan sampai Anda melepas pin. Sentuh dan tahan tombol Kembali untuk melepas pin."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Mengerti"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Lain kali"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Sembunyikan <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tolak"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> adalah dialog volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan aslinya."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Anda menggunakan profil kerja"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Penyetel Antarmuka Pengguna Sistem"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Tampilkan persentase baterai yang tersemat"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index a57e66cdc59a..32baffd2b973 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Sjáðu þær áður en þú opnar"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nei, takk"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Setja upp"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Sjá allt"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Fela allt"</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">"Hætta núna"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Stækka"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Minnka"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Skjárinn er festur"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Þetta heldur þessu opnu þangað til þú losar. Haltu „Til baka“ inni til að losa."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Ég skil"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nei, takk"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Fela <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Hafna"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er hljóðstyrksvalmyndin"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Snertu til að færa í upprunalegt horf."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Þú ert að nota vinnusniðið"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Fínstillingar kerfisviðmóts"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Sýna innfellda rafhlöðustöðu"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 77be0171465c..28bba7bbbbda 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Visualizza prima di sbloccare"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"No, grazie"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configura"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Mostra tutto"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Nascondi tutto"</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">"Termina adesso"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Espandi"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Comprimi"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"La schermata è bloccata"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"La schermata rimane visibile finché non la sblocchi. Tocca Panoramica e tieni premuto Indietro per sbloccare."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"No, grazie"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Nascondere <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Nega"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> rappresenta la finestra di dialogo relativa al volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Tocca per ripristinare l\'originale."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Stai utilizzando il profilo di lavoro"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintetizzatore interfaccia utente di sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostra percentuale batteria incorporata"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 20cb1ea5660a..7581aced5c5f 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"צפה בהן לפני שתבטל נעילה"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"לא, תודה"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"הגדר"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"הצג הכל"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"הסתר הכל"</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">"סיים כעת"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"הרחב"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"כווץ"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"המסך מוצמד"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"שומר בתצוגה עד לביטול ההצמדה. גע והחזק בו-זמנית ב\'הקודם\' כדי לבטל הצמדה."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"הבנתי"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"לא, תודה"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"להסתיר<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"דחה"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> הוא תיבת הדו-שיח של עוצמת הקול"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"גע כדי לשחזר את עוצמת הקול המקורית."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"אתה משתמש בפרופיל העבודה שלך"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"הצג בשורת הסטטוס את אחוז עוצמת הסוללה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 3d40c73e65c5..8d86ee373221 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -150,9 +150,7 @@
<string name="accessibility_airplane_mode" msgid="834748999790763092">"機内モード。"</string>
<string name="accessibility_no_sims" msgid="3957997018324995781">"SIMカードが挿入されていません。"</string>
<string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"携帯通信会社のネットワークを変更します。"</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
- <skip />
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"電池残量: <xliff:g id="NUMBER">%d</xliff:g>パーセント"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"システム設定。"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"通知を消去。"</string>
@@ -388,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"ロックを解除する前にご確認ください"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"キャンセル"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"設定"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"すべて表示"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"すべて非表示"</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">"今すぐ終了"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"展開"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"折りたたむ"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"画面が固定されました"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"固定を解除するまで画面が常に表示されるようになります。[戻る]を押し続けると固定が解除されます。"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"はい"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"いいえ"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>を非表示にしますか?"</string>
@@ -407,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"許可しない"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>を音量ダイアログとして使用"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"タップすると元の音量ダイアログが復元されます。"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"仕事用プロファイルを使用しています"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"システムUI調整ツール"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"内蔵電池の残量の割合を表示する"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 8f42d5b50150..92bd57a0b091 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"იხილეთ განბლოკვამდე"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"არა, გმადლობთ"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"დაყენება"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"ყველას ჩვენება"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"ყველას დამალვა"</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">"გამორთვა"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"გავრცობა"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"ჩაკეცვა"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"ეკრანი ჩამაგრებულია"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"ამით ის ხედში ჩამაგრების მოხსნამდე დარჩება. ჩამაგრების მოსახსნელად, ხანგრძლივად დააჭირეთ „უკან“-ს."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"გასაგებია"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"არა, გმადლობთ"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"დაიმალოს <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"უარყოფა"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ხმოვან დიალოგშია"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ორიგინალის აღდგენისათვის, შეეხეთ."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"თქვენ სამსახურის პროფილს იყენებთ"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"სისტემის UI ტუნერი"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ჩამაგრებული ბატარეის პროცენტის ჩვენება"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 192518a52246..5a0ed5f17027 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Бекітпесін ашу алдында оларды көру"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Жоқ, рақмет"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Реттеу"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Барлығын көру"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Барлығын жасыру"</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">"Қазір өшіру"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Жаю"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Жию"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Экран түйрелді"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Бұл сіз оны босатқанша оны көрсетіп тұрады. Босату үшін «Кері» түймесін басып тұрыңыз."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Түсіндім"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Жоқ, рақмет"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> жасыру керек пе?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Өшіру"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> — көлем диалогтық терезесі"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнұсқаны қалпына келтіру үшін түртіңіз."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Сіз жұмыс профиліңізді пайдаланып жатырсыз"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Жүйелік пайдаланушылық интерфейс тюнері"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Ендірілген батарея пайыздық шамасын көрсету"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 284af53566f5..0735cb19ca95 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"ឃើញ​ពួកវា​មុន​ពេល​ដោះ​សោ"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"ទេ អរគុណ!"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"រៀបចំ"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"មើលទាំងអស់"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"លាក់ទាំងអស់"</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">"បញ្ចប់ឥឡូវនេះ"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"ពង្រីក"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"បង្រួម"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"អេក្រង់​ត្រូវ​បាន​ភ្ជាប់"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"វានឹងនៅតែបង្ហាញ លុះត្រាតែអ្នកដកការដៅចេញ។ សូមប៉ះ និងសង្កត់ឲ្យជាប់ដើម្បីដកការដៅ។"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"យល់​ហើយ"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"ទេ អរគុណ"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"លាក់ <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"បដិសេធ"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> គឺជាប្រអប់សម្លេង"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ប៉ះដើម្បីស្តារច្បាប់ដើម។"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"អ្នកកំពុងប្រើប្រវត្តិរូបការងាររបស់អ្នក"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"កម្មវិធីសម្រួល UI ប្រព័ន្ធ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"បង្ហាញភាគរយថាមពលថ្មដែលបានបង្កប់"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 484551bd6fbf..0554f218e273 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"ನೀವು ಅನ್‌ಲಾಕ್‌ ಮಾಡುವ ಮೊದಲೇ ಅವುಗಳನ್ನು ನೋಡಿ"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"ಧನ್ಯವಾದಗಳು"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"ಹೊಂದಿಸು"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"ಎಲ್ಲವನ್ನೂ ನೋಡಿ"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"ಎಲ್ಲ ಮರೆಮಾಡಿ"</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">"ಈಗಲೇ ಅಂತ್ಯಗೊಳಿಸು"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"ವಿಸ್ತರಿಸು"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"ಸಂಕುಚಿಸು"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"ಪರದೆಯನ್ನು ಪಿನ್ ಮಾಡಲಾಗಿದೆ"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"ನೀವು ಅನ್‌ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಅನ್‌ಪಿನ್ ಮಾಡಲು ಹಿಂದೆ ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"ತಿಳಿಯಿತು"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"ಧನ್ಯವಾದಗಳು"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ಮರೆಮಾಡುವುದೇ?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"ನಿರಾಕರಿಸು"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಿದೆ"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ಮೂಲ ಮರುಸ್ಥಾಪಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌ ಅನ್ನು ನೀವು ಬಳಸುತ್ತಿರುವಿರಿ"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"ಸಿಸ್ಟಮ್ UI ಟ್ಯೂನರ್"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ಎಂಬೆಡ್ ಮಾಡಲಾದ ಬ್ಯಾಟರಿ ಶೇಕಡಾ ತೋರಿಸಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index c7f548970c1a..c7c9f156fde0 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"잠금 해제하기 전에 알림을 봅니다."</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"사용 안함"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"설정"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"모두 보기"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"모두 숨기기"</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">"지금 종료"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"펼치기"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"접기"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"화면 고정됨"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"고정 해제하기 전까지 계속 표시됩니다. 고정 해제하려면 뒤로 버튼을 길게 터치합니다."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"확인"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"거부"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>을(를) 숨기시겠습니까?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"거부"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>은(는) 볼륨 대화입니다."</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"원본을 복원하려면 터치하세요."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"직장 프로필을 사용하고 있습니다."</string>
<string name="system_ui_tuner" msgid="708224127392452018">"시스템 UI 튜너"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"내장형 배터리 잔량 비율 표시"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index f57c9fcac9eb..fe5d75d37d3b 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Аларды кулпудан чыгараардан мурун көрүңүз"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Жок, рахмат"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Орнотуу"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Бардыгын көрүү"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Баарын жашыруу"</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">"Азыр бүтүрүү"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Жайып көрсөтүү"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Жыйнап коюу"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Экран кадалган"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Бул бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Артка\" баскычын басып туруңуз."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Түшүндүм"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Жок, рахмат"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> жашырылсынбы?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Жок"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> үндү катуулатуу диалогу"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Түпнусканы калыбына келтирүү үчүн тийип коюңуз."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Жумуш профилиңизди колдонуп жатасыз"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Батарянын кубатнын деңгээли пайыз менен көрсөтлсүн"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 18f3111ff4f9..ca3470cb7f2d 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"ເບິ່ງພວກ​ມັນກ່ອນ​ທ່ານຈະ​ປົດລັອກ"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"ບໍ່, ຂອບໃຈ"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"ຕັ້ງຄ່າ"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"ເບິ່ງ​ທັງ​ໝົດ"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"ເຊື່ອງທັງ​ຫມົດ"</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">"ຢຸດດຽວນີ້"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"ຂະຫຍາຍ"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"ຫຍໍ້ລົງ"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"ປັກ​ໝຸດໜ້າ​ຈໍ​ແລ້ວ"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"ອັນ​ນີ້​ຮັກ​ສາ​ມັນ​ໄວ້​ໃນ​ມຸມມອງ​ຂອງ​ທ່ານ​ຈົນ​ກວ່າ​ທ່ານ​ຖອດ​ໝຸດ. ​ແຕະ​ປຸ່ມ ກັບ​ຄືນ​ ຄ້າງ​ໄວ້​ເພື່ອ​ຖອດ​ໝຸດ."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"ເຂົ້າໃຈແລ້ວ"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"ບໍ່, ຂອບໃຈ"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"ເຊື່ອງ <xliff:g id="TILE_LABEL">%1$s</xliff:g> ຫຼື​ບໍ່?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"ປະຕິເສດ"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ແມ່ນ​ໜ້າ​ຕ່າງ​ລະ​ດັບ​ສຽງ"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ສໍາ​ຜັດ​ເພື່ອກູ້​ຄືນ​ຕົ້ນ​ສະ​ບັບ​."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ທ່ານກຳລັງໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານ"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ສະ​ແດງ​ເປີ​ເຊັນ​ແບັດ​ເຕີ​ຣີ​ທີ່​ຕິດ​ມາ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 307b7d908fb1..2341e5a563db 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Peržiūrėti prieš atrakinant"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ne, ačiū"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Nustatyti"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Žr. viską"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Slėpti viską"</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">"Baigti dabar"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Išskleisti"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Sutraukti"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekranas prisegtas"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Tai bus rodoma, kol atsegsite. Kad atsegtumėte, palieskite ir palaikykite „Atgal“."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Supratau"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Ne, ačiū"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Slėpti „<xliff:g id="TILE_LABEL">%1$s</xliff:g>“?"</string>
@@ -407,6 +404,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Atmesti"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ yra garsumo valdymo dialogo langas"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Palieskite, kad atkurtumėte originalą."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Naudojate darbo profilį"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sistemos naudotojo sąsajos derinimo priemonė"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Rodyti įterptą akumuliat. įkrovos procentinę vertę"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 3660cda7691e..f6eb099e5c5c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -387,15 +387,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Skatiet tos pirms atbloķēšanas."</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nē"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Iestatīt"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Skatīt visus"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Slēpt visus"</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">"Izslēgt"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Izvērst"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Sakļaut"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekrāns ir piesprausts"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Šādi ekrāns būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties vienumam “Atpakaļ” un turiet to nospiestu."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Sapratu!"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nē, paldies"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vai paslēpt vienumu <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -406,6 +403,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Neatļaut"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ir skaļuma dialoglodziņš"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Pieskarieties, lai atjaunotu sākotnējo."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Jūs izmantojat darba profilu."</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sistēmas saskarnes regulators"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Rādīt akumulatora uzlādes līmeni procentos"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index f8d0417b555f..dbd3aed08c22 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Видете ги пред да отклучите"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Не, фала"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Постави"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Види ги сите"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Сокриј ги сите"</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">"Заврши сега"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Прошири"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Собери"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Екранот е прикачен"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Ќе се гледа сѐ додека не го откачите. Допрете и држете Назад за откачување."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Сфатив"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Не, фала"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Сокриј <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +404,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Одбиј"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> е дијалог за јачина на звук"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Допрете за да го вратите оригиналот."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Го користите работниот профил"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Адаптер на УИ на системот"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Прикажи вграден процент на батеријата"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 516e846bdae3..ace8ca46e22f 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -32,7 +32,7 @@
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"അറിയിപ്പുകൾ ഒന്നുമില്ല"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"നടന്നുകൊണ്ടിരിക്കുന്നവ"</string>
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"അറിയിപ്പുകൾ"</string>
- <string name="battery_low_title" msgid="6456385927409742437">"ബാറ്ററി നില കുറവാണ്"</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="invalid_charger" msgid="4549105996740522523">"USB ചാർജ്ജുചെയ്യൽ പിന്തുണയ്ക്കുന്നില്ല.\nഅതിന്റെ അനുബന്ധ ചാർജ്ജർ മാത്രം ഉപയോഗിക്കുക."</string>
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"അൺലോക്കുചെയ്യുന്നതിന് മുമ്പ് അവ കാണുക"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"വേണ്ട, നന്ദി"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"സജ്ജീകരിക്കുക"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"എല്ലാം കാണുക"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"എല്ലാം മറയ്ക്കുക"</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">"ഇപ്പോള്‍ അവസാനിപ്പിക്കുക"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"വികസിപ്പിക്കുക"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"ചുരുക്കുക"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"സ്‌ക്രീൻ പിൻ ചെയ്‌തു"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യുന്നതിന് \'മടങ്ങുക\' സ്‌പർശിച്ചുപിടിക്കുക."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"മനസ്സിലായി"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"വേണ്ട, നന്ദി"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> എന്നത് മറയ്‌ക്കണോ?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"നിരസിക്കുക"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗാണ്"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ആദ്യത്തേത് പുനഃസ്ഥാപിക്കാൻ സ്‌പർശിക്കുക."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"നിങ്ങൾ ഉപയോഗിക്കുന്നത് ഔദ്യോഗിക പ്രൊഫൈലാണ്"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"സിസ്റ്റം UI ട്യൂണർ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"എംബഡ് ചെയ്‌ത ബാറ്ററി ശതമാനം കാണിക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 8cb8df181445..698ed8a4acae 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -384,15 +384,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Түгжээг тайлахын өмнө үзнэ үү"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Үгүй"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Тохируулах"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Бүгдийг харах"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Бүгдийг нуух"</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">"Одоо дуусгах"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Дэлгэх"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Хураах"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Дэлгэц эхэнд байрлуулагдсан"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Таныг эхэнд нээхийг болиулах хүртэл харагдана. Хаахын тулд Хүрэх, Буцах товчлуурыг удаан дараарай."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Ойлголоо"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Үгүй"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>-ийг нуух уу?"</string>
@@ -403,6 +400,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Татгалзах"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь дууны диалог юм."</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Анхны хувилбарыг эргүүлэн хадгалахыг хүсвэл хүрнэ үү."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Та өөрийн ажлын профайлыг ашиглаж байна"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Системийн UI Тохируулагч"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Залгаатай тэжээлийн хувийг харуулах"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index cfa6b5ffac54..1168a71e4659 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"आपण अनलॉक करण्‍यापूर्वी त्यांना पहा"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"नाही धन्यवाद"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"सेट अप"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"सर्व पहा"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"सर्व लपवा"</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">"आता समाप्त करा"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"विस्तृत करा"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"संकुचित करा"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"स्क्रीन पिन केलेली आहे"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"हे आपण अनपिन करेपर्यंत दृश्यामध्ये ते ठेवते. अनपिन करण्यासाठी परत ला स्पर्श करा आणि धरून ठेवा."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"समजले"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"नाही धन्यवाद"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> लपवायचे?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"नकार द्या"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा व्हॉल्यूम संवाद आहे"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"मूळ पुनर्संचयित करण्यासाठी स्पर्श करा."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"आपण आपले कार्य प्रोफाईल वापरत आहात"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"सिस्टीम UI ट्यूनर"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"एम्बेडेड बॅटरी टक्केवारी दर्शवा"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 6ff9a612e52d..6511d302ef96 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Lihat sebelum anda membuka kunci"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Tidak"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Sediakan"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Lihat semua"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Sembunyikan semua"</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">"Tamatkan sekarang"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Kembangkan"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Runtuhkan"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Skrin telah disemat"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Ini akan memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh dan tahan Kembali untuk menyahsemat."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Faham"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Tidak"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Sembunyikan <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tolak"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ialah dialog kelantangan"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Sentuh untuk memulihkan yang asal."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Anda sedang menggunakan profil kerja"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Penala UI Sistem"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Tunjukkan peratusan bateri terbenam"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index e4b3e5400a4b..c8551b7a3f37 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"မဖွင့်ခင် ၎င်းတို့ကို ကြည့်ပါ"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"မလိုအပ်ပါ"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"သတ်မှတ်ရန်"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"အားလုံးကို ကြည့်ရန်"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"အားလုံး ဝှက်ထားရန်"</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">"ယခု အဆုံးသတ်ရန်"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"တိုးချဲ့ရန်"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"ခေါက်သိမ်းရန်..."</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"မျက်နှာပြင် ပင်ထိုးပြီးပါပြီ"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"ပင်ဖြုတ်သည့်အထိ ၎င်းကို မြင်နေမည်။ ပင်ဖြုတ်ရန် နောက်သို့ ခလုတ်ကို ထိလျက် ကိုင်ထားပါ။"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"အဲဒါ ရပြီ"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"မလို ကျေးဇူးပဲ"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> ဝှက်မည်လား?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"ငြင်းပယ်သည်"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အသံဒိုင်ယာလော့ခ်ဖြစ်သည်"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"မူရင်းအားပြန်လည်သိမ်းဆည်းရန် ထိပါ။"</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">"၊"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"သင်သည် အလုပ်ပရိုဖိုင်းအား သုံးနေသည်"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"စနစ် UI ဖမ်းစက်"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"မြုတ်ထားသည့် ဘတ်ထရီ ရာခိုင်နှုန်းကို ပြပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 2882d7a81a4b..7b6e60c3ad95 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -386,15 +386,12 @@
<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_setup" msgid="41079514801976810">"Konfigurer"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Se alle"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Skjul alle"</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>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Utvid"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Skjul"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Skjermen er låst"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <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="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vil du skjule <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Ikke tillat"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> er volumdialogen"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Trykk for å gå tilbake til den opprinnelige volumdialogen."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du bruker jobbprofilen din"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Vis prosent for det innebygde batteriet"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 19d84ce0cccf..c854a55717ec 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"तपाईँले अनलक गर्नअघि तिनीहरूलाई हेर्नुहोस्"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"धन्यवाद पर्दैन"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"सेटअप गर्नुहोस्"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"सबै हेर्नुहोस्"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"सबै लुकाउनुहोस्"</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">"अहिल्यै अन्त्य गर्नुहोस्"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"विस्तार गर्नुहोस्"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"संक्षिप्त पार्नुहोस्"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"पर्दा राखेका छ"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"तपाईँले अनपिन नगरेसम्म यसले त्यसलाई देखाइ राख्छ। अनपिन गर्न छुनुहोस् र होल्ड गर्नुहोस्"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"बुझेँ"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"धन्यवाद पर्दैन"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"लुकाउनुहुन्छ <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"अस्वीकार गर्नुहोस्"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> भोल्यूम संवाद हो"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"मूल पुनर्स्थापना गर्न छुनुहोस्।"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"तपाईँले कार्य प्रोफाइल प्रयोग गर्दै हुनुहुन्छ"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"प्रणाली UI ट्युनर"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"इम्बेड गरिएको ब्याट्री प्रतिशत देखाउनुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 95ddeab7c6fb..de4e58a161b0 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Weergeven voordat u ontgrendelt"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nee, bedankt"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configureren"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Alles weergeven"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Alles verbergen"</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">"Nu uitschakelen"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Uitvouwen"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Samenvouwen"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Scherm is vastgezet"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Het scherm blijft zichtbaar totdat je het losmaakt. Blijf \'Terug\' aanraken om het los te maken."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Ik snap het"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nee, bedankt"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> verbergen?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Afwijzen"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> is het volumedialoogvenster"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Tik hierop om het origineel te herstellen."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"U gebruikt je werkprofiel"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Systeem-UI-tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Percentage ingebouwde accu weergeven"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 6cb50b3be0e9..b67b75a32a1e 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"ਅਨਲੌਕ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਉਹਨਾਂ ਨੂੰ ਦੇਖੋ"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"ਸੈਟ ਅਪ"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"ਸਭ ਦੇਖੋ"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"ਸਾਰੇ ਲੁਕਾਓ"</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">"ਹੁਣੇ ਸਮਾਪਤ ਕਰੋ"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"ਵਿਸਤਾਰ ਕਰੋ"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"ਨਸ਼ਟ ਕਰੋ"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"ਸਕ੍ਰੀਨ ਪਿੰਨ ਕੀਤੀ"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"ਇਹ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਉਦੋਂ ਤੱਕ ਬਣਿਆ ਰਹਿੰਦਾ ਹੈ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਅਨਪਿੰਨ ਨਹੀਂ ਕਰਦੇ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ ਛੂੁਹੋ ਅਤੇ ਹੋਲਡ ਕਰੋ।"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"ਸਮਝ ਗਿਆ"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"ਕੀ <xliff:g id="TILE_LABEL">%1$s</xliff:g> ਨੂੰ ਲੁਕਾਉਣਾ ਹੈ?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੋਲਯੂਮ ਡਾਇਲੌਗ ਹੈ"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"ਅਸਲੀ ਨੂੰ ਰੀਸਟੋਰ ਕਰਨ ਲਈ ਛੋਹਵੋ।"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ਤੁਸੀਂ ਆਪਣੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਵਰਤ ਰਹੇ ਹੋ"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI ਟਿਊਨਰ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"ਜੋਡ਼ੀ ਗਈ ਬੈਟਰੀ ਪ੍ਰਤਿਸ਼ਤਤਾ ਦਿਖਾਓ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 1821cdd2fa73..48c4259ef51b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Zobacz powiadomienia, jeszcze zanim odblokujesz ekran"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nie, dziękuję"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Skonfiguruj"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Pokaż wszystkie"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ukrywaj wszystkie"</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">"Zakończ teraz"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Rozwiń"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Zwiń"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekran jest przypięty"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, kliknij i przytrzymaj Wstecz."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nie, dziękuję"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ukryć <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmów"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> steruje głośnością"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Dotknij, by przywrócić pierwotną."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Używasz profilu do pracy"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Kalibrator System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Pokaż procent naładowania baterii"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 68ecfc8f2930..c7044a3097b8 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -150,9 +150,7 @@
<string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avião."</string>
<string name="accessibility_no_sims" msgid="3957997018324995781">"Sem cartão SIM."</string>
<string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"Alteração de rede de operadora."</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
- <skip />
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"Bateria em <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Configurações do sistema"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificações."</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Limpar notificação."</string>
@@ -388,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Veja-as antes de desbloquear"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Não, obrigado"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configurar"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Ver tudo"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ocultar tudo"</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">"Finalizar agora"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Expandir"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Recolher"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"A tela está fixada"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Ela é mantida à vista até que seja liberada. Toque em \"Voltar\" e mantenha essa opção pressionada para liberar."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Entendi"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Não, obrigado"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Esconder <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Negar"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo referente ao volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Você está usando seu perfil de trabalho"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentagem de bateria incorporada"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 61a76f97f816..96dccf6126a5 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ver antes de desbloquear"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Não, obrigado"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configurar"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Ver tudo"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ocultar tudo"</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">"Terminar agora"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Expandir"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Reduzir"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"O ecrã está fixado"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Será mantido na vista até soltar. Toque sem soltar em Anterior para soltar."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Compreendi"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Não, obrigado"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Pretende ocultar <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Recusar"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo do volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Está a utilizar o seu perfil de trabalho"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador da interface do sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar percentagem da bateria incorporada"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 68ecfc8f2930..c7044a3097b8 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -150,9 +150,7 @@
<string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avião."</string>
<string name="accessibility_no_sims" msgid="3957997018324995781">"Sem cartão SIM."</string>
<string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"Alteração de rede de operadora."</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
- <skip />
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"Bateria em <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Configurações do sistema"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Notificações."</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Limpar notificação."</string>
@@ -388,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Veja-as antes de desbloquear"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Não, obrigado"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Configurar"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Ver tudo"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ocultar tudo"</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">"Finalizar agora"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Expandir"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Recolher"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"A tela está fixada"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Ela é mantida à vista até que seja liberada. Toque em \"Voltar\" e mantenha essa opção pressionada para liberar."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Entendi"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Não, obrigado"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Esconder <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Negar"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> é a caixa de diálogo referente ao volume"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Toque para restaurar o original."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Você está usando seu perfil de trabalho"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizador System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Mostrar porcentagem de bateria incorporada"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 3af273de6f0c..3d38d623b2a8 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -387,15 +387,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Doresc să se afișeze înainte de deblocare"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nu, mulț."</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Config."</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Afișați toate"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ascundeți toate"</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">"Opriți acum"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Extindeți"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Restrângeți"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ecranul este fixat"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Ecranul este afișat până anulați fixarea. Atingeți lung opțiunea Înapoi pentru a anula fixarea."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Am înțeles"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nu, mulțumesc"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ascundeți <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -406,6 +403,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuzați"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> afișează caseta de dialog pentru volum"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Atingeți pentru a reveni la setarea inițială."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Acum folosiți profilul de serviciu"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Afișați procentajul bateriei încorporat"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 296876c30d3b..c3fd2246bc7b 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -390,15 +390,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Просматривайте уведомления на заблокированном экране."</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Закрыть"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Настроить"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Показать все"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Скрыть все"</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">"Завершить"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Развернуть"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Свернуть"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Блокировка в приложении включена"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Приложение останется активным, пока вы не отмените блокировку, одновременно нажав кнопки \"Назад\" и \"Обзор\"."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"ОК"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Нет, спасибо"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Скрыть параметр \"<xliff:g id="TILE_LABEL">%1$s</xliff:g>\"?"</string>
@@ -409,6 +406,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Нет"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> назначено регулятором громкости"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Нажмите, чтобы восстановить приложение по умолчанию."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Вы перешли в рабочий профиль"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Показывать уровень заряда батареи в процентах"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 185fc05769a7..3ac91d14727f 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -386,8 +386,6 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"ඔබ අඟුළු හැරීමට කලින් ඒවා බලන්න"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"එපා ස්තූතියි"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"සකසන්න"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"සියල්ල බලන්න"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"සියල්ල සඟවන්න"</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">"දැන් අවසන් කරන්න"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"දිග හරින්න"</string>
@@ -404,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"ප්‍රතික්ෂේප කරන්න"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ධාරිතා සංවාදයයි"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"මුල් තත්ත්වය නැවත ප්‍රතිසාධනය කිරීමට ස්පර්ශ කරන්න."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ඔබ ඔබේ කාර්යාල පැතිකඩ භාවිත කරමින් සිටී"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"පද්ධති UI සුසරකය"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"කාවද්දන ලද බැටරි ප්‍රතිශතය පෙන්වන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index ebfd03594268..f3f935ef4ff7 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -390,15 +390,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Zobraziť pred odomknutím"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nie, vďaka"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Nastaviť"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Zobraziť všetko"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Skryť všetko"</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">"Skončiť"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Rozbaliť"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Zbaliť"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Obrazovka je pripnutá"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Obsah bude pripnutý v zobrazení, dokým ho neuvoľníte. Uvoľníte ho stlačením a podržaním tlačidla Späť."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Dobre"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nie, vďaka"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Skryť <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -409,6 +406,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Odmietnuť"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je dialóg hlasitosti"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Klepnutím obnovíte originál."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Používate svoj pracovný profil."</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Tuner používateľského rozhrania systému"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Zobraziť percentá vloženej batérie"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index d87b9a4784e8..c53bdddffc18 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Oglejte si jih pred odklepanjem"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ne, hvala"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Nastavitev"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Pokaži vse"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Skrij vse"</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">"Končaj zdaj"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Razširi"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Strni"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Zaslon je pripet"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"S tem ostane zaslon v pogledu, dokler ga ne odpnete. Pridržite tipko za nazaj, če ga želite odpeti."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Razumem"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Ne, hvala"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Želite skriti <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Zavrni"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> je pogovorno okno glede prostornine"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Dotaknite se, če želite obnoviti izvirnik."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Uporabljate delovni profil"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Uglaševalnik uporabniškega vmesnika sistema"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Prikaži odstotek napolnjenosti vgraj. akumulatorja"</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 5519e6ba00d8..0316c24787c8 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Shikoji para se t\'i shkyçësh"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Jo, faleminderit!"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Konfiguro"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Shikoji të gjitha"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Fshihi të gjitha"</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">"Përfundo tani"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Zgjeroje"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Mbylle"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekrani u gozhdua"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Prapa\" për ta hequr nga gozhdimi."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"E kuptova!"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Jo, faleminderit!"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Të fshihet <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Refuzo"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> është dialogu i volumit"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Prek për të restauruar origjinalin."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Po përdor profilin tënd të punës"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Shfaq përqindjen e baterisë së integruar"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 67959f5c37f5..842d788926a3 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -387,15 +387,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Прегледајте их пре откључавања"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Не, хвала"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Подеси"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Прикажи све"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Сакриј све"</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">"Прекини одмах"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Прошири"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Скупи"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Екран је закачен"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Због тога се он стално приказује док га не откачите. Додирните и задржите Назад да бисте га откачили."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Важи"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Не, хвала"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Желите ли да сакријете <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -406,6 +403,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Одбиј"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> је дијалог за јачину звука"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Додирните да бисте вратили оригинал."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Користите профил за Work"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Тјунер за кориснички интерфејс система"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Приказуј уграђени проценат батерије"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 48fe51268d6f..ee734ff63c71 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Visa dem innan du låser upp"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Nej tack"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Konfig."</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Visa alla"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Dölj alla"</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">"Sluta nu"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Utöka"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Komprimera"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Skärmen har fästs"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Detta visar skärmen tills du lossar den. Tryck länge på Tillbaka om du vill lossa skärmen."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nej tack"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Vill du dölja <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Neka"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> används som volymkontroll"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Tryck här om du vill återställa den ursprungliga appen."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du använder din jobbprofil"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Inställningar för systemgränssnitt"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Visa inbäddad batteriprocent"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 2b65540fa070..4a10f67a3e03 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Zitazame kabla hujafungua"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Hapana, asante"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Sanidi"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Angalia zote"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ficha zote"</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">"Komesha sasa"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Panua"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Kunja"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Skrini imebandikwa"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Hii itaendelea kuonyesha hadi uibandue. Gusa na ushikilie Nyuma ili ubandue."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Nimeelewa"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Hapana, asante"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ungependa kuficha <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Kataa"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ni mazungumzo ya sauti"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Gusa ili urejeshe ya awali."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Unatumia wasifu wako wa kazini"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Kipokea Ishara cha SystemUI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Onyesha asilimia ya betri iliyopachikwa"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 1f4a4a20338b..6474bb711dea 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"திறக்கும் முன் அவற்றைப் பார்க்கவும்"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"வேண்டாம்"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"அமை"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"எல்லாம் காட்டு"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"எல்லாம் மறை"</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">"இப்போது முடி"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"விரிவாக்கு"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"சுருக்கு"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"திரை பொருத்தப்பட்டது"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"பொருத்தியதை விலக்கும்வரை இதைக் காட்சியில் வைக்கும். விலக்க, முந்தையது என்பதைத் தொட்டுப் பிடிக்கவும்."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"புரிந்தது"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"வேண்டாம்"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>ஐ மறைக்கவா?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"நிராகரி"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"ஒலியளவு செய்தி: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"அசலை மீட்டமைக்கத் தொடவும்."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"பணி சுயவிவரத்தைப் பயன்படுத்துகிறீர்கள்"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"உள்ளிணைந்த பேட்டரி சதவீதத்தைக் காட்டு"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index d0b3439a453b..6e16a9597b9d 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"వీటిని మీరు అన్‌లాక్ చేయకముందే చూడండి"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"వద్దు, ధన్యవాదాలు"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"సెటప్ చేయి"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"అన్నీ చూడండి"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"అన్నీ దాచిపెట్టు"</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">"ఇప్పుడే ముగించు"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"విస్తరింపజేయండి"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"కుదించండి"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"స్క్రీన్ పిన్ చేయబడింది"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"ఇది మీరు అన్‌పిన్ చేసే వరకు దీన్ని వీక్షణలో ఉంచుతుంది. అన్‌పిన్ చేయడానికి వెనుకకు బటన్‌ను తాకి, ఉంచండి."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"అర్థమైంది"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"వద్దు, ధన్యవాదాలు"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g>ని దాచాలా?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"తిరస్కరించు"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"అసలుదాన్ని పునరుద్ధరించడానికి తాకండి."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"మీరు మీ కార్యాలయ ప్రొఫైల్‌ను ఉపయోగిస్తున్నారు"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"సిస్టమ్ UI ట్యూనర్"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"పొందుపరిచిన బ్యాటరీ శాతం చూపు"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index cb2921d05bf2..54987a2dd8aa 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"ดูก่อนปลดล็อก"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"ไม่เป็นไร"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"ตั้งค่า"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"ดูทั้งหมด"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"ซ่อนทั้งหมด"</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">"ไม่ใช้แล้ว"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"ขยาย"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"ยุบ"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"ตรึงหน้าจอแล้ว"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"การดำเนินการนี้จะแสดงหน้าจอนี้ไว้เสมอจนกว่าคุณจะเลิกตรึง แตะ \"กลับ\" ค้างไว้เพื่อเลิกตรึง"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"รับทราบ"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"ไม่เป็นไร ขอบคุณ"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"ซ่อน <xliff:g id="TILE_LABEL">%1$s</xliff:g> ไหม"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"ปฏิเสธ"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> เป็นช่องโต้ตอบระดับเสียง"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"แตะเพื่อคืนค่าดั้งเดิม"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"คุณกำลังใช้โปรไฟล์งานของคุณ"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"ตัวรับสัญญาณ UI ระบบ"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"แสดงเปอร์เซ็นต์ของแบตเตอรี่ในตัว"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 43969e9f8023..d8778a0d3c7d 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Tingnan ang mga ito bago ka mag-unlock"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Hindi"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"I-set up"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Tingnan lahat"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Itago lahat"</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">"Tapusin ngayon"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Palawakin"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"I-collapse"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Naka-pin ang screen"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Pinapanatili nitong nasa view ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Bumalik upang mag-unpin."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Nakuha ko"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Hindi, salamat na lang"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Itago ang <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Tanggihan"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"Ang <xliff:g id="APP_NAME">%1$s</xliff:g> ang volume dialog"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Pindutin upang ibalik ang orihinal."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Ginagamit mo ang iyong profile sa trabaho"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Tuner ng System UI"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Ipakita ang naka-embed na porsyento ng baterya"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 7a044ef67ab5..066ffbba4dfa 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Kilidi açmadan bildirimleri görün"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Hayır, teşekkürler"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Kur"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Tümünü göster"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Tümünü gizle"</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">"Şimdi sona erdir"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Genişlet"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Daralt"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekran sabitlendi"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Siz sabitlemeyi kaldırana kadar görüntülenmeye devam eder. Sabitlemeyi kaldırmak için Geri\'ye dokunun ve basılı tutun."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Anladım"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Hayır, teşekkürler"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> gizlensin mi?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Reddet"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ses denetimi iletişim kutusu olarak ayarlandı"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Orijinali geri yüklemek için dokunun."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"İş profilinizi kullanıyorsunuz"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Sistem Arayüzü Ayarlayıcısı"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Yerleşik pil yüzdesini göster"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 37030acab2fd..afa907745ef1 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -152,7 +152,7 @@
<string name="accessibility_airplane_mode" msgid="834748999790763092">"Режим польоту."</string>
<string name="accessibility_no_sims" msgid="3957997018324995781">"Немає SIM-карти."</string>
<string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"Змінення мережі оператора."</string>
- <string name="accessibility_battery_level" msgid="7451474187113371965">"Заряд акумулятора: <xliff:g id="NUMBER">%d</xliff:g>."</string>
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"Заряд акумулятора у відсотках: <xliff:g id="NUMBER">%d</xliff:g>."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Налаштування системи."</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"Сповіщення."</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Очистити сповіщення."</string>
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Переглядайте сповіщення, перш ніж розблокувати екран"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ні, дякую"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Налаштув."</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Показати всі"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Сховати всі"</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">"Закрити"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Розгорнути"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Згорнути"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Екран закріплено"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Ви постійно бачитимете екран, доки не відкріпите його. Щоб відкріпити екран, натисніть і утримуйте кнопку \"Назад\"."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Зрозуміло"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Ні, дякую"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Сховати <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +404,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Відхилити"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> призначено регулятором гучності"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Торкніться, щоб відновити оригінал."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Ви в робочому профілі"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Показувати заряд акумулятора у відсотках"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 0712f980804d..9abfebfb21f5 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"غیر مقفل کرنے سے پہلے انہیں دیکھیں"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"نہیں شکریہ"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"ترتیب دیں"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"سبھی دیکھیں"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"سبھی چھپائیں"</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">"ابھی ختم کریں"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"پھیلائیں"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"سکیڑیں"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"اسکرین پن کردہ ہے"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"یہ اس کو اس وقت تک منظر میں رکھتا ہے جب تک آپ اس سے پن ہٹا نہیں دیتے۔ پن ہٹانے کیلئے پیچھے بٹن کو ٹچ کریں اور دبائے رکھیں۔"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"سمجھ آ گئی"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"نہیں شکریہ"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> کو چھپائیں؟"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"مسترد کریں"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> والیوم ڈائلاگ ہے"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"اصل کو بحال کرنے کیلئے ٹچ کریں۔"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"آپ اپنا دفتری پروفائل استعمال کر رہے ہیں۔"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"‏سسٹم UI ٹیونر"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"سرایت کردہ بیٹری کی فیصد دکھائیں"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index ad3dcc74c06e..79a18a28a160 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ularni qulfdan chiqarishdan oldin ko‘ring"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Yo‘q, kerak emas"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Sozlash"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Barchasini ko‘rsatish"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Barchasini yashirish"</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">"Tugatish"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Yoyish"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Yig‘ish"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Ekran qadaldi"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Ekran yechilmaguncha u o‘zgarmas holatda qoladi. Uni yechish uchun “Orqaga” tugmasini bosing va ushlab turing."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Yo‘q, kerakmas"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"<xliff:g id="TILE_LABEL">%1$s</xliff:g> berkitilsinmi?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Rad etish"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ovoz balandligini boshqaradi"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Aslini tiklash uchun bosing."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Siz ishchi profildan foydalanmoqdasiz"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"SystemUI Tuner"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Batareya foizi ko‘rsatilsin"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index f13033bbb96d..a195382ae861 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Xem thông báo trước khi bạn mở khóa"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ko, cảm ơn"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Thiết lập"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Xem tất cả"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Ẩn tất cả"</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">"Kết thúc bây giờ"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Mở rộng"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Thu gọn"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Màn hình được ghim"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Thao tác này sẽ duy trì hiển thị màn hình cho đến khi bạn bỏ ghim. Chạm và giữ Quay lại để bỏ ghim."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Ok"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Không, cảm ơn"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Ẩn <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Từ chối"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> là hộp thoại khối lượng"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Chạm để khôi phục bản gốc."</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Bạn đang sử dụng hồ sơ công việc của mình"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Bộ điều hướng giao diện người dùng hệ thống"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Hiển thị tỷ lệ phần trăm pin được nhúng"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ade7636edafe..cca4f6f92002 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -388,15 +388,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"无需解锁即可查看通知"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"不用了"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"设置"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"查看全部"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"全部隐藏"</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">"立即结束"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"展开"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"收起"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"已固定屏幕"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“返回”即可取消固定屏幕。"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"知道了"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"不用了"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"要隐藏“<xliff:g id="TILE_LABEL">%1$s</xliff:g>”吗?"</string>
@@ -407,6 +404,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒绝"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”已用作音量控制对话框"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"触摸即可恢复原始设置。"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您当前正在使用工作资料"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"系统界面调谐器"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"嵌入式显示电池电量百分比 显示嵌入的电池电量百分比"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index aa6e065ca23d..ff978411cf61 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -150,9 +150,7 @@
<string name="accessibility_airplane_mode" msgid="834748999790763092">"飛航模式。"</string>
<string name="accessibility_no_sims" msgid="3957997018324995781">"沒有 SIM 卡。"</string>
<string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"流動網絡供應商網絡正在變更。"</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
- <skip />
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"系統設定"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"清除通知。"</string>
@@ -388,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"解鎖前顯示"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"不用了,謝謝"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"設定"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"顯示全部"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"全部隱藏"</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">"立即終止"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"展開"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"收合"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"螢幕已固定"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"在您取消固定前,它會保持在檢視狀態。輕觸並按住 [返回] 即可取消固定。"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"知道了"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"不用了,謝謝"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"隱藏 <xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒絕"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為音量對話框"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸即可復原。"</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">"、"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您正在使用工作設定檔"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"系統使用者介面調諧器"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"顯示嵌入的電池百分比"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index ffaaefe430c4..b529e39c0a42 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -150,9 +150,7 @@
<string name="accessibility_airplane_mode" msgid="834748999790763092">"飛行模式。"</string>
<string name="accessibility_no_sims" msgid="3957997018324995781">"沒有 SIM 卡。"</string>
<string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"行動通訊業者網路正在變更。"</string>
- <!-- String.format failed for translation -->
- <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
- <skip />
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"系統設定"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"清除通知。"</string>
@@ -388,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"解鎖前顯示"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"不用了,謝謝"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"設定"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"全部顯示"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"全部隱藏"</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">"立刻結束"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"展開"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"收合"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"螢幕已固定"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"這會讓目前的螢幕畫面保持顯示狀態,直到取消固定為止。按住「返回」按鈕即可取消固定。"</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"知道了"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"不用了,謝謝"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"隱藏<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -407,6 +402,8 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"拒絕"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」現在是預設的音量控制對話方塊。"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"輕觸這裡即可恢復原始設定。"</string>
+ <!-- no translation found for group_summary_concadenation (2705151242008937028) -->
+ <skip />
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您正在使用 Work 設定檔"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"系統使用者介面調整精靈"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"顯示嵌入式電池百分比"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index f1df7145fdb7..f77e01a8f32e 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -386,15 +386,12 @@
<string name="hidden_notifications_text" msgid="2326409389088668981">"Ibone ngaphambi kokuthi uyivule"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"Cha ngiyabonga"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"Lungisa"</string>
- <string name="notification_expand_button_text" msgid="1037425494153780718">"Buka konke"</string>
- <string name="notification_collapse_button_text" msgid="6883253262134328057">"Fihla wonke"</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">"Qeda manje"</string>
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Nweba"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Goqa"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Isikrini siphiniwe"</string>
- <!-- no translation found for screen_pinning_description (3577937698406151604) -->
- <skip />
+ <string name="screen_pinning_description" msgid="3577937698406151604">"Lokhu kuyigcina ekubukekeni uze ususe ukuphina. Thinta uphinde ubambe ukubuyela emuva ukuze ususe ukuphina."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"Ngiyitholile"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Cha ngiyabonga"</string>
<string name="quick_settings_reset_confirmation_title" msgid="748792586749897883">"Fihla i-<xliff:g id="TILE_LABEL">%1$s</xliff:g>?"</string>
@@ -405,6 +402,7 @@
<string name="volumeui_prompt_deny" msgid="5720663643411696731">"Phika"</string>
<string name="volumeui_notification_title" msgid="4906770126345910955">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> yingxoxo yevolumu"</string>
<string name="volumeui_notification_text" msgid="1826889705095768656">"Thinta ukuze ubuyisele kokwangempela."</string>
+ <string name="group_summary_concadenation" msgid="2705151242008937028">","</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Usebenzisa iphrofayela yakho yomsebenzi"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"Isishuni se-UI yesistimu"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"Bonisa amaphesenti ebhethri elinamathiselwe"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 794e9005fa31..049754ebaaef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -19,12 +19,14 @@ package com.android.systemui.qs;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -34,6 +36,7 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
@@ -620,4 +623,9 @@ public class QSPanel extends FrameLayout implements Tunable {
int getOffsetTop(TileRecord tile);
void updateResources();
}
+
+ public static boolean isTheNewQS(Context context) {
+ return Settings.Secure.getIntForUser(context.getContentResolver(), QS_THE_NEW_QS,
+ ActivityManager.getCurrentUser(), 0) != 0;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 61695b2db2d7..48b74a4566a5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -28,6 +28,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.qs.QSDetailItems;
import com.android.systemui.qs.QSDetailItems.Item;
+import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
@@ -93,7 +94,7 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
state.visible = !mKeyguard.isSecure() || !mKeyguard.isShowing()
- || mKeyguard.canSkipBouncer();
+ || mKeyguard.canSkipBouncer() || QSPanel.isTheNewQS(mContext);
state.label = mContext.getString(R.string.quick_settings_cast_title);
state.value = false;
state.autoMirrorDrawable = false;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index c6fc6ffcb4d7..2f9a496d9602 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -21,6 +21,7 @@ import android.provider.Settings.Secure;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.SecureSetting;
import com.android.systemui.qs.UsageTracker;
@@ -110,7 +111,7 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
protected void handleUpdateState(BooleanState state, Object arg) {
final int value = arg instanceof Integer ? (Integer) arg : mSetting.getValue();
final boolean enabled = value != 0;
- state.visible = enabled || mUsageTracker.isRecentlyUsed();
+ state.visible = enabled || mUsageTracker.isRecentlyUsed() || QSPanel.isTheNewQS(mContext);
state.value = enabled;
state.label = mContext.getString(R.string.quick_settings_inversion_label);
state.icon = enabled ? mEnable : mDisable;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 7b83e6a9ca25..79084ae73e3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.UsageTracker;
import com.android.systemui.statusbar.policy.HotspotController;
@@ -88,7 +89,8 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
- state.visible = mController.isHotspotSupported() && mUsageTracker.isRecentlyUsed();
+ state.visible = (mController.isHotspotSupported() && mUsageTracker.isRecentlyUsed())
+ || QSPanel.isTheNewQS(mContext);
state.label = mContext.getString(R.string.quick_settings_hotspot_label);
if (arg instanceof Boolean) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index e6fade455444..0e2672ca4da1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -18,6 +18,7 @@ package com.android.systemui.qs.tiles;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
+import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.LocationController;
@@ -73,7 +74,7 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
// Work around for bug 15916487: don't show location tile on top of lock screen. After the
// bug is fixed, this should be reverted to only hiding it on secure lock screens:
// state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
- state.visible = !mKeyguard.isShowing();
+ state.visible = !mKeyguard.isShowing() || QSPanel.isTheNewQS(mContext);
state.value = locationEnabled;
if (locationEnabled) {
state.icon = mEnable;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 4d40cb7072f7..a58bc5882f2a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -21,9 +21,11 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
+import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.Log;
import android.view.Display;
@@ -52,10 +54,21 @@ public class Recents extends SystemUI
public final static int EVENT_BUS_PRIORITY = 1;
public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000;
+ // Purely for experimentation
+ private final static String RECENTS_OVERRIDE_SYSPROP_KEY = "persist.recents_override_pkg";
+ private final static String ACTION_SHOW_RECENTS = "com.android.systemui.recents.ACTION_SHOW";
+ private final static String ACTION_HIDE_RECENTS = "com.android.systemui.recents.ACTION_HIDE";
+ private final static String ACTION_TOGGLE_RECENTS = "com.android.systemui.recents.ACTION_TOGGLE";
+
private static SystemServicesProxy sSystemServicesProxy;
private static RecentsTaskLoader sTaskLoader;
private static RecentsConfiguration sConfiguration;
+ // For experiments only, allows another package to handle recents if it is defined in the system
+ // properties. This is limited to show/toggle/hide, and does not tie into the ActivityManager,
+ // and does not reside in the home stack.
+ private String mOverrideRecentsPackageName;
+
private Handler mHandler;
private RecentsImpl mImpl;
@@ -142,6 +155,14 @@ public class Recents extends SystemUI
mHandler = new Handler();
mImpl = new RecentsImpl(mContext);
+ // Check if there is a recents override package
+ if ("userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE)) {
+ String cnStr = SystemProperties.get(RECENTS_OVERRIDE_SYSPROP_KEY);
+ if (!cnStr.isEmpty()) {
+ mOverrideRecentsPackageName = cnStr;
+ }
+ }
+
// Register with the event bus
EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
EventBus.getDefault().register(sTaskLoader, EVENT_BUS_PRIORITY);
@@ -172,6 +193,10 @@ public class Recents extends SystemUI
*/
@Override
public void showRecents(boolean triggeredFromAltTab, View statusBarView) {
+ if (proxyToOverridePackage(ACTION_SHOW_RECENTS)) {
+ return;
+ }
+
int currentUser = sSystemServicesProxy.getCurrentUser();
if (sSystemServicesProxy.isSystemUser(currentUser)) {
mImpl.showRecents(triggeredFromAltTab);
@@ -197,6 +222,10 @@ public class Recents extends SystemUI
*/
@Override
public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
+ if (proxyToOverridePackage(ACTION_HIDE_RECENTS)) {
+ return;
+ }
+
int currentUser = sSystemServicesProxy.getCurrentUser();
if (sSystemServicesProxy.isSystemUser(currentUser)) {
mImpl.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
@@ -222,6 +251,10 @@ public class Recents extends SystemUI
*/
@Override
public void toggleRecents(Display display, int layoutDirection, View statusBarView) {
+ if (proxyToOverridePackage(ACTION_TOGGLE_RECENTS)) {
+ return;
+ }
+
int currentUser = sSystemServicesProxy.getCurrentUser();
if (sSystemServicesProxy.isSystemUser(currentUser)) {
mImpl.toggleRecents();
@@ -421,4 +454,19 @@ public class Recents extends SystemUI
}
mOnConnectRunnables.clear();
}
+
+ /**
+ * Attempts to proxy the following action to the override recents package.
+ * @return whether the proxying was successful
+ */
+ private boolean proxyToOverridePackage(String action) {
+ if (mOverrideRecentsPackageName != null) {
+ Intent intent = new Intent(action);
+ intent.setPackage(mOverrideRecentsPackageName);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ mContext.sendBroadcast(intent);
+ return true;
+ }
+ return false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 243c0e1dbbf3..0e11f02a34ec 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -16,7 +16,7 @@
package com.android.systemui.recents;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import android.app.ActivityManager;
import android.app.ActivityOptions;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
index 28299d3217fb..d4158451b54b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsResizeTaskDialog.java
@@ -33,8 +33,8 @@ import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.views.RecentsView;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
/**
* A helper for the dialogs that show when task debugging is on.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ParametricCurve.java b/packages/SystemUI/src/com/android/systemui/recents/misc/ParametricCurve.java
index ea6821fe1696..515c3bda3f9c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/ParametricCurve.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/ParametricCurve.java
@@ -189,6 +189,7 @@ public class ParametricCurve {
public float computePOffsetForScaledHeight(int height, Rect bounds) {
int top = bounds.top;
int bottom = bounds.bottom;
+ height = Math.min(height, bottom - top);
if (bounds.height() == 0) {
return 0;
@@ -231,6 +232,7 @@ public class ParametricCurve {
public float computePOffsetForHeight(int height, Rect bounds) {
int top = bounds.top;
int bottom = bounds.bottom;
+ height = Math.min(height, bottom - top);
if (bounds.height() == 0) {
return 0;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 81a949d1b7cf..2fe5e988b3e6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -72,8 +72,10 @@ import java.util.Iterator;
import java.util.List;
import java.util.Random;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
-import static android.app.ActivityManager.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
/**
* Acts as a shim around the real system services that we need to access data from, and provides
@@ -233,6 +235,15 @@ public class SystemServicesProxy {
return null;
}
+ /**
+ * Returns whether this device has freeform workspaces.
+ */
+ public boolean hasFreeformWorkspaceSupport() {
+ if (mPm == null) return false;
+
+ return mPm.hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT);
+ }
+
/** Returns whether the recents is currently running */
public boolean isRecentsTopMost(ActivityManager.RunningTaskInfo topTask,
MutableBoolean isHomeTopMost) {
@@ -311,14 +322,14 @@ public class SystemServicesProxy {
* Returns whether the given stack id is the home stack id.
*/
public static boolean isHomeStack(int stackId) {
- return stackId == ActivityManager.HOME_STACK_ID;
+ return stackId == HOME_STACK_ID;
}
/**
* Returns whether the given stack id is the freeform workspace stack id.
*/
public static boolean isFreeformStack(int stackId) {
- return stackId == ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+ return stackId == FREEFORM_WORKSPACE_STACK_ID;
}
/**
@@ -728,7 +739,7 @@ public class SystemServicesProxy {
try {
// Use the home stack bounds
- ActivityManager.StackInfo stackInfo = mIam.getStackInfo(ActivityManager.HOME_STACK_ID);
+ ActivityManager.StackInfo stackInfo = mIam.getStackInfo(HOME_STACK_ID);
if (stackInfo != null) {
windowRect.set(stackInfo.bounds);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
index ce993c537e76..a97a2a800ac4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
@@ -17,10 +17,11 @@
package com.android.systemui.recents.views;
import android.util.Log;
+import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
-import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
/**
* The layout logic for the contents of the freeform workspace.
@@ -33,6 +34,7 @@ public class FreeformWorkspaceLayoutAlgorithm {
// The number of cells in the freeform workspace
private int mFreeformCellXCount;
private int mFreeformCellYCount;
+
// The width and height of the cells in the freeform workspace
private int mFreeformCellWidth;
private int mFreeformCellHeight;
@@ -44,22 +46,26 @@ public class FreeformWorkspaceLayoutAlgorithm {
* Updates the layout for each of the freeform workspace tasks. This is called after the stack
* layout is updated.
*/
- public void update(ArrayList<Task> freeformTasks, TaskStackLayoutAlgorithm stackLayout) {
+ public void update(List<Task> freeformTasks, TaskStackLayoutAlgorithm stackLayout) {
+ mTaskIndexMap.clear();
+
int numFreeformTasks = stackLayout.mNumFreeformTasks;
if (!freeformTasks.isEmpty()) {
// Calculate the cell width/height depending on the number of freeform tasks
mFreeformCellXCount = Math.max(2, (int) Math.ceil(Math.sqrt(numFreeformTasks)));
- mFreeformCellYCount = Math.max(2, (int) Math.ceil((float) numFreeformTasks / mFreeformCellXCount));
- mFreeformCellWidth = stackLayout.mFreeformRect.width() / mFreeformCellXCount;
+ mFreeformCellYCount = Math.max(2, (int) Math.ceil((float) numFreeformTasks /
+ mFreeformCellXCount));
// For now, make the cells square
+ mFreeformCellWidth = Math.min(stackLayout.mFreeformRect.width() / mFreeformCellXCount,
+ stackLayout.mFreeformRect.height() / mFreeformCellYCount);
mFreeformCellHeight = mFreeformCellWidth;
// Put each of the tasks in the progress map at a fixed index (does not need to actually
// map to a scroll position, just by index)
int taskCount = freeformTasks.size();
- for (int i = 0; i < taskCount; i++) {
+ for (int i = taskCount - 1; i >= 0; i--) {
Task task = freeformTasks.get(i);
- mTaskIndexMap.put(task.key, i);
+ mTaskIndexMap.put(task.key, taskCount - i - 1);
}
if (DEBUG) {
@@ -74,24 +80,23 @@ public class FreeformWorkspaceLayoutAlgorithm {
/**
* Returns whether the transform is available for the given task.
*/
- public boolean isTransformAvailable(Task task, float stackScroll,
- TaskStackLayoutAlgorithm stackLayout) {
- if (stackLayout.mNumFreeformTasks == 0 || task == null ||
- !mTaskIndexMap.containsKey(task.key)) {
+ public boolean isTransformAvailable(Task task, TaskStackLayoutAlgorithm stackLayout) {
+ if (stackLayout.mNumFreeformTasks == 0 || task == null) {
return false;
}
- return stackScroll > stackLayout.mStackEndScrollP;
+ return mTaskIndexMap.containsKey(task.key);
}
/**
* Returns the transform for the given task. Any rect returned will be offset by the actual
* transform for the freeform workspace.
*/
- public TaskViewTransform getTransform(Task task, float stackScroll,
- TaskViewTransform transformOut, TaskStackLayoutAlgorithm stackLayout) {
- if (Float.compare(stackScroll, stackLayout.mStackEndScrollP) > 0) {
+ public TaskViewTransform getTransform(Task task, TaskViewTransform transformOut,
+ TaskStackLayoutAlgorithm stackLayout) {
+ if (mTaskIndexMap.containsKey(task.key)) {
// This is a freeform task, so lay it out in the freeform workspace
int taskIndex = mTaskIndexMap.get(task.key);
+ int topOffset = (stackLayout.mFreeformRect.top - stackLayout.mTaskRect.top);
int x = taskIndex % mFreeformCellXCount;
int y = taskIndex / mFreeformCellXCount;
float scale = (float) mFreeformCellWidth / stackLayout.mTaskRect.width();
@@ -99,8 +104,13 @@ public class FreeformWorkspaceLayoutAlgorithm {
int scaleYOffset = (int) (((1f - scale) * stackLayout.mTaskRect.height()) / 2);
transformOut.scale = scale * 0.9f;
transformOut.translationX = x * mFreeformCellWidth - scaleXOffset;
- transformOut.translationY = y * mFreeformCellHeight - scaleYOffset;
+ transformOut.translationY = topOffset + y * mFreeformCellHeight - scaleYOffset;
+ transformOut.translationZ = stackLayout.mMaxTranslationZ;
+ transformOut.rect.set(stackLayout.mTaskRect);
+ transformOut.rect.offset(transformOut.translationX, transformOut.translationY);
+ Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
transformOut.visible = true;
+ transformOut.p = 0;
return transformOut;
}
return null;
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 a5b7aaf3036a..d72e50e0c5dc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -61,7 +61,9 @@ import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
import java.util.List;
-import static android.app.ActivityManager.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
/**
* This view is the the top level layout that contains TaskStacks (which are laid out according
@@ -489,14 +491,14 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int destinationStack) {
final int targetStackId = destinationStack != INVALID_STACK_ID ?
destinationStack : clickedTask.getTask().key.stackId;
- if (targetStackId != ActivityManager.FREEFORM_WORKSPACE_STACK_ID
- && targetStackId != ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID) {
+ if (targetStackId != FREEFORM_WORKSPACE_STACK_ID
+ && targetStackId != FULLSCREEN_WORKSPACE_STACK_ID) {
return null;
}
// If this is a full screen stack, the transition will be towards the single, full screen
// task. We only need the transition spec for this task.
List<AppTransitionAnimationSpec> specs = new ArrayList<>();
- if (targetStackId == ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID) {
+ if (targetStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
specs.add(createThumbnailHeaderAnimationSpec(
stackView, offsetX, offsetY, stackScroll, clickedTask,
clickedTask.getTask().key.id, ADD_HEADER_BITMAP));
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 45d626e15327..a0713d7defc0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -24,12 +24,14 @@ import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.ParametricCurve;
+import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.LinkedList;
/**
@@ -44,14 +46,8 @@ public class TaskStackLayoutAlgorithm {
private static final float STACK_PEEK_MIN_SCALE = 0.85f;
// The scale of the last task
private static final float SINGLE_TASK_SCALE = 0.95f;
- // The percentage of the height of the stack that we want to show the last task at
- private static final float VISIBLE_LAST_TASK_HEIGHT_PCT = 0.45f;
// The percentage of height of task to show between tasks
private static final float VISIBLE_TASK_HEIGHT_BETWEEN_TASKS = 0.5f;
- // The percentage between the maxStackScroll and the maxScroll where a given scroll will still
- // snap back to the maxStackScroll instead of to the maxScroll (which shows the freeform
- // workspace)
- private static final float SNAP_TO_MAX_STACK_SCROLL_FACTOR = 0.3f;
// A report of the visibility state of the stack
public class VisibilityReport {
@@ -67,14 +63,36 @@ public class TaskStackLayoutAlgorithm {
Context mContext;
- // This is the view bounds inset exactly by the search bar, but without the bottom inset
- // see RecentsConfiguration.getTaskStackBounds()
- public Rect mStackRect = new Rect();
- // This is the task view bounds for layout (untransformed), the rect is top-aligned to the top
- // of the stack rect
+ /*
+ +-------------------+
+ | SEARCH |
+ +-------------------+
+ |+-----------------+|
+ || FREEFORM ||
+ || ||
+ || ||
+ |+-----------------+|
+ | +-----------+ |
+ | +---------------+ |
+ | | | |
+ |+-----------------+|
+ || STACK ||
+ +-------------------+
+ */
+
+ // The task bounds (untransformed) for layout. This rect is anchored at mTaskRoot.
public Rect mTaskRect = new Rect();
- // The bounds of the freeform workspace, the rect is top-aligned to the top of the stack rect
+ // The freeform workspace bounds, inset from the top by the search bar, and is a fixed height
public Rect mFreeformRect = new Rect();
+ // The freeform stack bounds, inset from the top by the search bar and freeform workspace, and
+ // runs to the bottom of the screen
+ private Rect mFreeformStackRect = new Rect();
+ // The stack bounds, inset from the top by the search bar, and runs to
+ // the bottom of the screen
+ private Rect mStackRect = new Rect();
+ // The current stack rect, can either by mFreeformStackRect or mStackRect depending on whether
+ // there is a freeform workspace
+ public Rect mCurrentStackRect;
// This is the current system insets
public Rect mSystemInsets = new Rect();
@@ -83,13 +101,6 @@ public class TaskStackLayoutAlgorithm {
// The largest scroll progress, at this value, the front most task will be visible above the
// navigation bar
float mMaxScrollP;
- // The scroll progress at which bottom of the first task of the stack is aligned with the bottom
- // of the stack
- float mStackEndScrollP;
- // The scroll progress that we actually want to scroll the user to when they want to go to the
- // end of the stack (it accounts for the nav bar, so that the bottom of the task is offset from
- // the bottom of the stack)
- float mPreferredStackEndScrollP;
// The initial progress that the scroller is set when you first enter recents
float mInitialScrollP;
// The task progress for the front-most task in the stack
@@ -109,13 +120,6 @@ public class TaskStackLayoutAlgorithm {
// The relative progress to ensure that the offset from the bottom of the stack to the bottom
// of the task is respected
float mStackBottomPOffset;
- // The freeform workspace gap
- int mFreeformWorkspaceGapOffset;
- float mFreeformWorkspaceGapPOffset;
- // The relative progress to ensure that the freeform workspace height + gap + stack bottom
- // padding is respected
- int mFreeformWorkspaceOffset;
- float mFreeformWorkspacePOffset;
// The last computed task counts
int mNumStackTasks;
@@ -130,9 +134,6 @@ public class TaskStackLayoutAlgorithm {
// The freeform workspace layout
FreeformWorkspaceLayoutAlgorithm mFreeformLayoutAlgorithm;
- // Temporary task view transform
- TaskViewTransform mTmpTransform = new TaskViewTransform();
-
// Log function
static ParametricCurve sCurve;
@@ -190,53 +191,57 @@ public class TaskStackLayoutAlgorithm {
}
/**
- * Computes the stack and task rects.
+ * Computes the stack and task rects. The given task stack bounds is the whole bounds not
+ * including the search bar.
*/
public void initialize(Rect taskStackBounds) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
RecentsConfiguration config = Recents.getConfiguration();
int widthPadding = (int) (config.taskStackWidthPaddingPct * taskStackBounds.width());
int heightPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_stack_top_padding);
- // Compute the stack rect, inset from the given task stack bounds
- mStackRect.set(taskStackBounds.left + widthPadding, taskStackBounds.top + heightPadding,
- taskStackBounds.right - widthPadding, taskStackBounds.bottom);
+ // The freeform height is the visible height (not including system insets) - padding above
+ // freeform and below stack - gap between the freeform and stack
mStackBottomOffset = mSystemInsets.bottom + heightPadding;
-
- // Compute the task rect, align it to the top-center square in the stack rect
+ int ffHeight = (taskStackBounds.height() - 2 * heightPadding - mStackBottomOffset) / 2;
+ mFreeformRect.set(taskStackBounds.left + widthPadding,
+ taskStackBounds.top + heightPadding,
+ taskStackBounds.right - widthPadding,
+ taskStackBounds.top + heightPadding + ffHeight);
+ mFreeformStackRect.set(taskStackBounds.left + widthPadding,
+ taskStackBounds.top + heightPadding + ffHeight + heightPadding,
+ taskStackBounds.right - widthPadding,
+ taskStackBounds.bottom);
+ mStackRect.set(taskStackBounds.left + widthPadding,
+ taskStackBounds.top + heightPadding,
+ taskStackBounds.right - widthPadding,
+ taskStackBounds.bottom);
+ // Anchor the task rect to the top-center of the non-freeform stack rect
int size = Math.min(mStackRect.width(), mStackRect.height() - mStackBottomOffset);
- int xOffset = (mStackRect.width() - size) / 2;
- mTaskRect.set(mStackRect.left + xOffset, mStackRect.top,
- mStackRect.right - xOffset, mStackRect.top + size);
-
- // Compute the freeform rect, align it to the top-left of the stack rect
- mFreeformRect.set(mStackRect);
- mFreeformRect.bottom = taskStackBounds.bottom - mStackBottomOffset;
+ mTaskRect.set(mStackRect.left, mStackRect.top,
+ mStackRect.left + size, mStackRect.top + size);
+ mCurrentStackRect = ssp.hasFreeformWorkspaceSupport() ? mFreeformStackRect : mStackRect;
// Compute the progress offsets
int withinAffiliationOffset = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_bar_height);
int betweenAffiliationOffset = (int) (VISIBLE_TASK_HEIGHT_BETWEEN_TASKS * mTaskRect.height());
mWithinAffiliationPOffset = sCurve.computePOffsetForScaledHeight(withinAffiliationOffset,
- mStackRect);
+ mCurrentStackRect);
mBetweenAffiliationPOffset = sCurve.computePOffsetForScaledHeight(betweenAffiliationOffset,
- mStackRect);
+ mCurrentStackRect);
mTaskHeightPOffset = sCurve.computePOffsetForScaledHeight(mTaskRect.height(),
- mStackRect);
+ mCurrentStackRect);
mTaskHalfHeightPOffset = sCurve.computePOffsetForScaledHeight(mTaskRect.height() / 2,
- mStackRect);
- mStackBottomPOffset = sCurve.computePOffsetForHeight(mStackBottomOffset, mStackRect);
- mFreeformWorkspaceGapOffset = mStackBottomOffset;
- mFreeformWorkspaceGapPOffset = sCurve.computePOffsetForHeight(mFreeformWorkspaceGapOffset,
- mStackRect);
- mFreeformWorkspaceOffset = mFreeformWorkspaceGapOffset + mFreeformRect.height() +
- mStackBottomOffset;
- mFreeformWorkspacePOffset = sCurve.computePOffsetForHeight(mFreeformWorkspaceOffset,
- mStackRect);
+ mCurrentStackRect);
+ mStackBottomPOffset = sCurve.computePOffsetForHeight(mStackBottomOffset, mCurrentStackRect);
if (DEBUG) {
Log.d(TAG, "initialize");
Log.d(TAG, "\tarclength: " + sCurve.getArcLength());
+ Log.d(TAG, "\tmFreeformRect: " + mFreeformRect);
+ Log.d(TAG, "\tmFreeformStackRect: " + mFreeformStackRect);
Log.d(TAG, "\tmStackRect: " + mStackRect);
Log.d(TAG, "\tmTaskRect: " + mTaskRect);
Log.d(TAG, "\tmSystemInsets: " + mSystemInsets);
@@ -246,20 +251,9 @@ public class TaskStackLayoutAlgorithm {
Log.d(TAG, "\tmTaskHeightPOffset: " + mTaskHeightPOffset);
Log.d(TAG, "\tmTaskHalfHeightPOffset: " + mTaskHalfHeightPOffset);
Log.d(TAG, "\tmStackBottomPOffset: " + mStackBottomPOffset);
- Log.d(TAG, "\tmFreeformWorkspacePOffset: " + mFreeformWorkspacePOffset);
- Log.d(TAG, "\tmFreeformWorkspaceGapPOffset: " + mFreeformWorkspaceGapPOffset);
-
- Log.d(TAG, "\ty at p=0: " + sCurve.pToX(0f, mStackRect));
- Log.d(TAG, "\ty at p=1: " + sCurve.pToX(1f, mStackRect));
-
- for (int height = 0; height <= 2000; height += 50) {
- float p = sCurve.computePOffsetForScaledHeight(height, mStackRect);
- float p2 = sCurve.computePOffsetForHeight(height, mStackRect);
- Log.d(TAG, "offset: " + height + ", " +
- p + " => " + (mStackRect.bottom - sCurve.pToX(1f - p, mStackRect)) /
- sCurve.pToScale(1f - p) + ", " +
- p2 + " => " + (mStackRect.bottom - sCurve.pToX(1f - p2, mStackRect)));
- }
+
+ Log.d(TAG, "\ty at p=0: " + sCurve.pToX(0f, mCurrentStackRect));
+ Log.d(TAG, "\ty at p=1: " + sCurve.pToX(1f, mCurrentStackRect));
}
}
@@ -279,7 +273,7 @@ public class TaskStackLayoutAlgorithm {
ArrayList<Task> tasks = stack.getTasks();
if (tasks.isEmpty()) {
mFrontMostTaskP = 0;
- mMinScrollP = mMaxScrollP = mStackEndScrollP = mPreferredStackEndScrollP = 0;
+ mMinScrollP = mMaxScrollP = 0;
mNumStackTasks = mNumFreeformTasks = 0;
return;
}
@@ -307,6 +301,10 @@ public class TaskStackLayoutAlgorithm {
Task task = stackTasks.get(i);
mTaskProgressMap.put(task.key, pAtFrontMostTaskTop);
+ if (DEBUG) {
+ Log.d(TAG, "Update: " + task.activityLabel + " p: " + pAtFrontMostTaskTop);
+ }
+
if (i < (taskCount - 1)) {
// Increment the peek height
float pPeek = task.group.isFrontMostTask(task) ?
@@ -316,37 +314,24 @@ public class TaskStackLayoutAlgorithm {
}
mFrontMostTaskP = pAtFrontMostTaskTop;
- // Set the stack end scroll progress to the point at which the bottom of the front-most
- // task is aligned to the bottom of the stack
- mStackEndScrollP = alignToStackBottom(pAtFrontMostTaskTop, mTaskHeightPOffset);
if (mNumStackTasks > 1) {
- // Set the preferred stack end scroll progress to the point where the bottom of the
- // front-most task is offset by the navbar and padding from the bottom of the stack
- mPreferredStackEndScrollP = mStackEndScrollP + mStackBottomPOffset;
-
+ // Set the stack end scroll progress to the point at which the bottom of the front-most
+ // task is aligned to the bottom of the stack
+ mMaxScrollP = alignToStackBottom(pAtFrontMostTaskTop,
+ mStackBottomPOffset + mTaskHeightPOffset);
// Basically align the back-most task such that the last two tasks would be visible
- mMinScrollP = alignToStackBottom(pAtBackMostTaskTop, 2 *
- mBetweenAffiliationPOffset);
+ mMinScrollP = alignToStackBottom(pAtBackMostTaskTop,
+ mStackBottomPOffset + mTaskHeightPOffset);
} else {
// When there is a single item, then just make all the stack progresses the same
- mPreferredStackEndScrollP = mStackEndScrollP;
- mMinScrollP = mStackEndScrollP;
+ mMinScrollP = mMaxScrollP = 0;
}
- } else {
- // TODO: In the case where there is only freeform tasks, then the scrolls should be
- // set to zero
}
if (!freeformTasks.isEmpty()) {
- // The max scroll includes the freeform workspace offset. As the scroll progress exceeds
- // mStackEndScrollP up to mMaxScrollP, the stack will translate upwards and the freeform
- // workspace will be visible
mFreeformLayoutAlgorithm.update(freeformTasks, this);
- mMaxScrollP = mStackEndScrollP + mFreeformWorkspacePOffset;
- mInitialScrollP = isInitialStateFreeform(stack) ?
- mMaxScrollP : mPreferredStackEndScrollP;
+ mInitialScrollP = mMaxScrollP;
} else {
- mMaxScrollP = mPreferredStackEndScrollP;
mInitialScrollP = Math.max(mMinScrollP, mMaxScrollP - mTaskHalfHeightPOffset);
}
@@ -354,7 +339,6 @@ public class TaskStackLayoutAlgorithm {
Log.d(TAG, "mNumStackTasks: " + mNumStackTasks);
Log.d(TAG, "mNumFreeformTasks: " + mNumFreeformTasks);
Log.d(TAG, "mMinScrollP: " + mMinScrollP);
- Log.d(TAG, "mStackEndScrollP: " + mStackEndScrollP);
Log.d(TAG, "mMaxScrollP: " + mMaxScrollP);
}
}
@@ -369,28 +353,28 @@ public class TaskStackLayoutAlgorithm {
return new VisibilityReport(1, 1);
}
- // If there are freeform tasks, then they will be the only ones visible
- int freeformTaskCount = 0;
- for (Task t : tasks) {
- if (t.isFreeformTask()) {
- freeformTaskCount++;
- }
- }
- if (freeformTaskCount > 0) {
- return new VisibilityReport(freeformTaskCount, freeformTaskCount);
+ // Quick return when there are no stack tasks
+ if (mNumStackTasks == 0) {
+ return new VisibilityReport(Math.max(mNumFreeformTasks, 1),
+ Math.max(mNumFreeformTasks, 1));
}
// Otherwise, walk backwards in the stack and count the number of tasks and visible
- // thumbnails
+ // thumbnails and add that to the total freeform task count
int taskHeight = mTaskRect.height();
int taskBarHeight = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_bar_height);
- int numVisibleTasks = 1;
- int numVisibleThumbnails = 1;
- float progress = mTaskProgressMap.get(tasks.get(tasks.size() - 1).key) - mInitialScrollP;
- int prevScreenY = sCurve.pToX(progress, mStackRect);
+ int numVisibleTasks = Math.max(mNumFreeformTasks, 1);
+ int numVisibleThumbnails = Math.max(mNumFreeformTasks, 1);
+ Task firstNonFreeformTask = tasks.get(tasks.size() - mNumFreeformTasks - 1);
+ float progress = mTaskProgressMap.get(firstNonFreeformTask.key) - mInitialScrollP;
+ int prevScreenY = sCurve.pToX(progress, mCurrentStackRect);
for (int i = tasks.size() - 2; i >= 0; i--) {
Task task = tasks.get(i);
+ if (task.isFreeformTask()) {
+ continue;
+ }
+
progress = mTaskProgressMap.get(task.key) - mInitialScrollP;
if (progress < 0) {
break;
@@ -399,7 +383,7 @@ public class TaskStackLayoutAlgorithm {
if (isFrontMostTaskInGroup) {
float scaleAtP = sCurve.pToScale(progress);
int scaleYOffsetAtP = (int) (((1f - scaleAtP) * taskHeight) / 2);
- int screenY = sCurve.pToX(progress, mStackRect) + scaleYOffsetAtP;
+ int screenY = sCurve.pToX(progress, mCurrentStackRect) + scaleYOffsetAtP;
boolean hasVisibleThumbnail = (prevScreenY - screenY) > taskBarHeight;
if (hasVisibleThumbnail) {
numVisibleThumbnails++;
@@ -431,17 +415,8 @@ public class TaskStackLayoutAlgorithm {
*/
public TaskViewTransform getStackTransform(Task task, float stackScroll,
TaskViewTransform transformOut, TaskViewTransform prevTransform) {
- if (mFreeformLayoutAlgorithm.isTransformAvailable(task, stackScroll, this)) {
- mFreeformLayoutAlgorithm.getTransform(task, stackScroll, transformOut, this);
- if (transformOut.visible) {
- getFreeformWorkspaceBounds(stackScroll, mTmpTransform);
- transformOut.translationY += mTmpTransform.translationY;
- transformOut.translationZ = mMaxTranslationZ;
- transformOut.rect.set(mTaskRect);
- transformOut.rect.offset(0, transformOut.translationY);
- Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
- transformOut.p = 0;
- }
+ if (mFreeformLayoutAlgorithm.isTransformAvailable(task, this)) {
+ mFreeformLayoutAlgorithm.getTransform(task, transformOut, this);
return transformOut;
} else {
// Return early if we have an invalid index
@@ -463,32 +438,25 @@ public class TaskStackLayoutAlgorithm {
// modulate some values directly
float pTaskRelative = mMinScrollP - stackScroll;
float scale = (mNumFreeformTasks > 0) ? 1f : SINGLE_TASK_SCALE;
- int topOffset = (mStackRect.height() - mTaskRect.height()) / 2;
+ int topOffset = (mCurrentStackRect.top - mTaskRect.top) +
+ (mCurrentStackRect.height() - mTaskRect.height()) / 2;
transformOut.scale = scale;
- transformOut.translationX = 0;
- transformOut.translationY = (int) (topOffset + (pTaskRelative * mStackRect.height()));
+ transformOut.translationX = (mStackRect.width() - mTaskRect.width()) / 2;
+ transformOut.translationY = (int) (topOffset + (pTaskRelative * mCurrentStackRect.height()));
transformOut.translationZ = mMaxTranslationZ;
transformOut.rect.set(mTaskRect);
- transformOut.rect.offset(0, transformOut.translationY);
+ transformOut.rect.offset(transformOut.translationX, transformOut.translationY);
Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
transformOut.visible = true;
transformOut.p = pTaskRelative;
return transformOut;
} else {
- // Once we scroll past the preferred stack end scroll, then we should start translating
- // the cards in screen space and lock their final state at the end stack progress
- int overscrollYOffset = 0;
- if (mNumFreeformTasks > 0 && stackScroll > mStackEndScrollP) {
- float stackOverscroll = (stackScroll - mPreferredStackEndScrollP) /
- (mFreeformWorkspacePOffset - mFreeformWorkspaceGapPOffset);
- overscrollYOffset = (int) (Math.max(0, stackOverscroll) *
- (mFreeformWorkspaceOffset - mFreeformWorkspaceGapPOffset));
- stackScroll = Math.min(mPreferredStackEndScrollP, stackScroll);
- }
-
float pTaskRelative = taskProgress - stackScroll;
float pBounded = Math.max(0, Math.min(pTaskRelative, 1f));
+ if (DEBUG) {
+ Log.d(TAG, "getStackTransform (normal): " + taskProgress + ", " + stackScroll);
+ }
// If the task top is outside of the bounds below the screen, then immediately reset it
if (pTaskRelative > 1f) {
@@ -508,18 +476,18 @@ public class TaskStackLayoutAlgorithm {
float scale = sCurve.pToScale(pBounded);
int scaleYOffset = (int) (((1f - scale) * mTaskRect.height()) / 2);
transformOut.scale = scale;
- transformOut.translationX = 0;
- transformOut.translationY = sCurve.pToX(pBounded, mStackRect) - mStackRect.top -
- scaleYOffset - overscrollYOffset;
+ transformOut.translationX = (mStackRect.width() - mTaskRect.width()) / 2;
+ transformOut.translationY = (mCurrentStackRect.top - mTaskRect.top) +
+ (sCurve.pToX(pBounded, mCurrentStackRect) - mCurrentStackRect.top) -
+ scaleYOffset;
transformOut.translationZ = Math.max(mMinTranslationZ,
mMinTranslationZ + (pBounded * (mMaxTranslationZ - mMinTranslationZ)));
transformOut.rect.set(mTaskRect);
- transformOut.rect.offset(0, transformOut.translationY);
+ transformOut.rect.offset(transformOut.translationX, transformOut.translationY);
Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
transformOut.visible = true;
transformOut.p = pTaskRelative;
if (DEBUG) {
- Log.d(TAG, "getStackTransform (normal): " + taskProgress + ", " + stackScroll);
Log.d(TAG, "\t" + transformOut);
}
@@ -528,61 +496,6 @@ public class TaskStackLayoutAlgorithm {
}
/**
- * Returns whether this stack should be initialized to show the freeform workspace or not.
- */
- public boolean isInitialStateFreeform(TaskStack stack) {
- Task launchTarget = stack.getLaunchTarget();
- if (launchTarget != null) {
- return launchTarget.isFreeformTask();
- }
- Task frontTask = stack.getFrontMostTask();
- if (frontTask != null) {
- return frontTask.isFreeformTask();
- }
- return false;
- }
-
- /**
- * Update/get the transform
- */
- public TaskViewTransform getFreeformWorkspaceBounds(float stackScroll,
- TaskViewTransform transformOut) {
- transformOut.reset();
- if (mNumFreeformTasks == 0) {
- return transformOut;
- }
-
- if (stackScroll > mStackEndScrollP) {
- // mStackEndScroll is the point at which the first stack task is bottom aligned with the
- // stack, so we offset from on the stack rect height.
- float stackOverscroll = (Math.max(0, stackScroll - mStackEndScrollP)) /
- mFreeformWorkspacePOffset;
- int overscrollYOffset = (int) (stackOverscroll * mFreeformWorkspaceOffset);
- transformOut.scale = 1f;
- transformOut.alpha = 1f;
- transformOut.translationY = mStackRect.height() + mFreeformWorkspaceGapOffset -
- overscrollYOffset;
- transformOut.rect.set(mFreeformRect);
- transformOut.rect.offset(0, transformOut.translationY);
- Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
- transformOut.visible = true;
- }
- return transformOut;
- }
-
- /**
- * Returns the preferred maximum scroll position for a stack at the given {@param scroll}.
- */
- public float getPreferredMaxScrollPosition(float scroll) {
- float maxStackScrollBounds = mStackEndScrollP + SNAP_TO_MAX_STACK_SCROLL_FACTOR *
- (mMaxScrollP - mStackEndScrollP);
- if (scroll < maxStackScrollBounds) {
- return mPreferredStackEndScrollP;
- }
- return mMaxScrollP;
- }
-
- /**
* Returns the untransformed task view bounds.
*/
public Rect getUntransformedTaskViewBounds() {
@@ -604,7 +517,7 @@ public class TaskStackLayoutAlgorithm {
* screen along the arc-length proportionally (1/arclength).
*/
public float getDeltaPForY(int downY, int y) {
- float deltaP = (float) (y - downY) / mStackRect.height() * (1f / sCurve.getArcLength());
+ float deltaP = (float) (y - downY) / mCurrentStackRect.height() * (1f / sCurve.getArcLength());
return -deltaP;
}
@@ -613,7 +526,7 @@ public class TaskStackLayoutAlgorithm {
* of the curve, map back to the screen y.
*/
public int getYForDeltaP(float downScrollP, float p) {
- int y = (int) ((p - downScrollP) * mStackRect.height() * sCurve.getArcLength());
+ int y = (int) ((p - downScrollP) * mCurrentStackRect.height() * sCurve.getArcLength());
return -y;
}
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 b266eaacae10..14d75a85000d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -58,7 +58,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import static android.app.ActivityManager.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
/* The visual representation of a task stack view */
@@ -281,6 +281,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**
* Gets the stack transforms of a list of tasks, and returns the visible range of tasks.
+ * This call ignores freeform tasks.
*/
private boolean updateStackTransforms(ArrayList<TaskViewTransform> taskTransforms,
ArrayList<Task> tasks,
@@ -306,8 +307,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Update the stack transforms
TaskViewTransform prevTransform = null;
for (int i = taskCount - 1; i >= 0; i--) {
- TaskViewTransform transform = mLayoutAlgorithm.getStackTransform(tasks.get(i),
- stackScroll, taskTransforms.get(i), prevTransform);
+ Task task = tasks.get(i);
+ if (task.isFreeformTask()) {
+ continue;
+ }
+
+ TaskViewTransform transform = mLayoutAlgorithm.getStackTransform(task, stackScroll,
+ taskTransforms.get(i), prevTransform);
+ if (DEBUG) {
+ Log.d(TAG, "updateStackTransform: " + i + ", " + transform.visible);
+ }
if (transform.visible) {
if (frontMostVisibleIndex < 0) {
frontMostVisibleIndex = i;
@@ -327,7 +336,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (boundTranslationsToRect) {
transform.translationY = Math.min(transform.translationY,
- mLayoutAlgorithm.mStackRect.bottom);
+ mLayoutAlgorithm.mCurrentStackRect.bottom);
}
prevTransform = transform;
}
@@ -344,13 +353,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Get all the task transforms
ArrayList<Task> tasks = mStack.getTasks();
float stackScroll = mStackScroller.getStackScroll();
- int[] visibleRange = mTmpVisibleRange;
- boolean isValidVisibleRange = updateStackTransforms(mCurrentTaskTransforms, tasks,
- stackScroll, visibleRange, false);
+ int[] visibleStackRange = mTmpVisibleRange;
+ boolean isValidVisibleStackRange = updateStackTransforms(mCurrentTaskTransforms, tasks,
+ stackScroll, visibleStackRange, false);
boolean hasStackBackTransform = false;
boolean hasStackFrontTransform = false;
if (DEBUG) {
- Log.d(TAG, "visibleRange: " + visibleRange[0] + " to " + visibleRange[1]);
+ Log.d(TAG, "visibleRange: " + visibleStackRange[0] + " to " + visibleStackRange[1]);
}
// Return all the invisible children to the pool
@@ -363,7 +372,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView tv = taskViews.get(i);
Task task = tv.getTask();
int taskIndex = mStack.indexOfTask(task);
- if (visibleRange[1] <= taskIndex && taskIndex <= visibleRange[0]) {
+ if (task.isFreeformTask() ||
+ visibleStackRange[1] <= taskIndex && taskIndex <= visibleStackRange[0]) {
mTmpTaskViewMap.put(task, tv);
} else {
if (tv.isFocusedTask()) {
@@ -371,16 +381,43 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
lastFocusedTaskIndex = taskIndex;
resetFocusedTask();
}
+ if (DEBUG) {
+ Log.d(TAG, "returning to pool: " + task.key);
+ }
mViewPool.returnViewToPool(tv);
}
}
+ // Pick up all the freeform tasks
+ int firstVisStackIndex = isValidVisibleStackRange ? visibleStackRange[0] : 0;
+ for (int i = mStack.getTaskCount() - 1; i > firstVisStackIndex; i--) {
+ Task task = tasks.get(i);
+ if (!task.isFreeformTask()) {
+ continue;
+ }
+ TaskViewTransform transform = mLayoutAlgorithm.getStackTransform(task, stackScroll,
+ mCurrentTaskTransforms.get(i), null);
+ TaskView tv = mTmpTaskViewMap.get(task);
+ if (tv == null) {
+ if (DEBUG) {
+ Log.d(TAG, "picking up from pool: " + task.key);
+ }
+ tv = mViewPool.pickUpViewFromPool(task, task);
+ if (mLayersDisabled) {
+ tv.disableLayersForOneFrame();
+ }
+ }
+
+ // Animate the task into place
+ tv.updateViewPropertiesToTaskTransform(transform,
+ mStackViewsAnimationDuration, mRequestUpdateClippingListener);
+ }
+
// Pick up all the newly visible children and update all the existing children
- for (int i = visibleRange[0]; isValidVisibleRange && i >= visibleRange[1]; i--) {
+ for (int i = visibleStackRange[0]; isValidVisibleStackRange && i >= visibleStackRange[1]; i--) {
Task task = tasks.get(i);
TaskViewTransform transform = mCurrentTaskTransforms.get(i);
TaskView tv = mTmpTaskViewMap.get(task);
- int taskIndex = mStack.indexOfTask(task);
if (tv == null) {
tv = mViewPool.pickUpViewFromPool(task, task);
@@ -409,29 +446,19 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
// Animate the task into place
- tv.updateViewPropertiesToTaskTransform(mCurrentTaskTransforms.get(taskIndex),
+ tv.updateViewPropertiesToTaskTransform(transform,
mStackViewsAnimationDuration, mRequestUpdateClippingListener);
}
// Update the focus if the previous focused task was returned to the view pool
if (lastFocusedTaskIndex != -1) {
- if (lastFocusedTaskIndex < visibleRange[1]) {
- setFocusedTask(visibleRange[1], false, wasLastFocusedTaskAnimated);
+ if (lastFocusedTaskIndex < visibleStackRange[1]) {
+ setFocusedTask(visibleStackRange[1], false, wasLastFocusedTaskAnimated);
} else {
- setFocusedTask(visibleRange[0], false, wasLastFocusedTaskAnimated);
+ setFocusedTask(visibleStackRange[0], false, wasLastFocusedTaskAnimated);
}
}
- // Update the freeform workspace
- mLayoutAlgorithm.getFreeformWorkspaceBounds(stackScroll, mTmpTransform);
- if (mTmpTransform.visible) {
- mTmpTransform.rect.roundOut(mTmpRect);
- mFreeformWorkspaceBackground.setAlpha(255);
- mFreeformWorkspaceBackground.setBounds(mTmpRect);
- } else {
- mFreeformWorkspaceBackground.setAlpha(0);
- }
-
// Reset the request-synchronize params
mStackViewsAnimationDuration = 0;
mStackViewsDirty = false;
@@ -491,6 +518,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Compute the min and max scroll values
mLayoutAlgorithm.update(mStack);
+ // Update the freeform workspace
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ if (ssp.hasFreeformWorkspaceSupport()) {
+ mTmpRect.set(mLayoutAlgorithm.mFreeformRect);
+ mFreeformWorkspaceBackground.setAlpha(255);
+ mFreeformWorkspaceBackground.setBounds(mTmpRect);
+ }
+
// Debug logging
if (boundScrollToNewMinMax) {
mStackScroller.boundScroll();
@@ -762,7 +797,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Handler for the first layout. */
void onFirstLayout() {
- int offscreenY = mLayoutAlgorithm.mStackRect.bottom;
+ int offscreenY = mLayoutAlgorithm.mCurrentStackRect.bottom;
// Find the launch target task
Task launchTargetTask = mStack.getLaunchTarget();
@@ -863,7 +898,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mStackScroller.stopScroller();
mStackScroller.stopBoundScrollAnimation();
// Animate all the task views out of view
- ctx.offscreenTranslationY = mLayoutAlgorithm.mStackRect.bottom;
+ ctx.offscreenTranslationY = mLayoutAlgorithm.mCurrentStackRect.bottom;
List<TaskView> taskViews = getTaskViews();
int taskViewCount = taskViews.size();
@@ -929,6 +964,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
+ /**
+ * Launches the freeform tasks.
+ */
+ public boolean launchFreeformTasks() {
+ Task frontTask = mStack.getFrontMostTask();
+ if (frontTask != null && frontTask.isFreeformTask()) {
+ onTaskViewClicked(getChildViewForTask(frontTask), frontTask, false);
+ return true;
+ }
+ return false;
+ }
+
/**** TaskStackCallbacks Implementation ****/
@Override
@@ -975,6 +1022,19 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Animate all the tasks into place
requestSynchronizeStackViewsWithModel(200);
+ } else {
+ // Remove the view associated with this task, we can't rely on updateTransforms
+ // to work here because the task is no longer in the list
+ TaskView tv = getChildViewForTask(removedTask);
+ if (tv != null) {
+ mViewPool.returnViewToPool(tv);
+ }
+
+ // Update the min/max scroll and animate other task views into their new positions
+ updateMinMaxScroll(true);
+
+ // Animate all the tasks into place
+ requestSynchronizeStackViewsWithModel(200);
}
// Update the new front most task
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 6b92aeda1562..3a2ed0fa7d75 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -122,7 +122,7 @@ public class TaskStackViewScroller {
/** Returns the bounded stack scroll */
float getBoundedStackScroll(float scroll) {
return Math.max(mLayoutAlgorithm.mMinScrollP,
- Math.min(mLayoutAlgorithm.getPreferredMaxScrollPosition(scroll), scroll));
+ Math.min(mLayoutAlgorithm.mMaxScrollP, scroll));
}
/** Returns the amount that the absolute value of how much the scroll is out of bounds. */
@@ -194,7 +194,7 @@ public class TaskStackViewScroller {
// TODO: Remove
@Deprecated
int progressToScrollRange(float p) {
- return (int) (p * mLayoutAlgorithm.mStackRect.height());
+ return (int) (p * mLayoutAlgorithm.mCurrentStackRect.height());
}
/** Called from the view draw, computes the next scroll. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 9e6fb7bae4b9..59c9708840e2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -19,6 +19,7 @@ package com.android.systemui.recents.views;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Rect;
import android.util.Log;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -29,9 +30,11 @@ import android.view.ViewParent;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.Recents;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -222,49 +225,12 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
int activePointerIndex = ev.findPointerIndex(mActivePointerId);
int y = (int) ev.getY(activePointerIndex);
int velocity = (int) mVelocityTracker.getYVelocity(mActivePointerId);
- float curScrollP = mScroller.getStackScroll();
if (mIsScrolling) {
- boolean hasFreeformTasks = mSv.mStack.hasFreeformTasks();
- if (hasFreeformTasks && velocity > 0 &&
- curScrollP > layoutAlgorithm.mStackEndScrollP) {
- // Snap to workspace
- float finalY = mDownY + layoutAlgorithm.getYForDeltaP(mDownScrollP,
- layoutAlgorithm.mPreferredStackEndScrollP);
- mScrollFlingAnimator = ValueAnimator.ofInt(y, (int) finalY);
- mScrollFlingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float deltaP = layoutAlgorithm.getDeltaPForY(mDownY,
- (Integer) animation.getAnimatedValue());
- float scroll = mDownScrollP + deltaP;
- mScroller.setStackScroll(scroll);
- }
- });
- mFlingAnimUtils.apply(mScrollFlingAnimator, y, finalY, velocity);
- mScrollFlingAnimator.start();
- } else if (hasFreeformTasks && velocity < 0 &&
- curScrollP > (layoutAlgorithm.mStackEndScrollP -
- layoutAlgorithm.mTaskHalfHeightPOffset)) {
- // Snap to stack
- float finalY = mDownY + layoutAlgorithm.getYForDeltaP(mDownScrollP,
- layoutAlgorithm.mMaxScrollP);
- mScrollFlingAnimator = ValueAnimator.ofInt(y, (int) finalY);
- mScrollFlingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float deltaP = layoutAlgorithm.getDeltaPForY(mDownY,
- (Integer) animation.getAnimatedValue());
- float scroll = mDownScrollP + deltaP;
- mScroller.setStackScroll(scroll);
- }
- });
- mFlingAnimUtils.apply(mScrollFlingAnimator, y, finalY, velocity);
- mScrollFlingAnimator.start();
- } else if (mScroller.isScrollOutOfBounds()) {
+ if (mScroller.isScrollOutOfBounds()) {
mScroller.animateBoundScroll();
} else if (Math.abs(velocity) > mMinimumVelocity) {
float minY = mDownY + layoutAlgorithm.getYForDeltaP(mDownScrollP,
- layoutAlgorithm.mPreferredStackEndScrollP);
+ layoutAlgorithm.mMaxScrollP);
float maxY = mDownY + layoutAlgorithm.getYForDeltaP(mDownScrollP,
layoutAlgorithm.mMinScrollP);
mScroller.fling(mDownScrollP, mDownY, y, velocity, (int) minY, (int) maxY,
@@ -313,6 +279,17 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
return;
}
+ // If tapping on the freeform workspace background, just launch the first freeform task
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ if (ssp.hasFreeformWorkspaceSupport()) {
+ Rect freeformRect = mSv.mLayoutAlgorithm.mFreeformRect;
+ if (freeformRect.top <= y && y <= freeformRect.bottom) {
+ if (mSv.launchFreeformTasks()) {
+ return;
+ }
+ }
+ }
+
// The user intentionally tapped on the background, which is like a tap on the "desktop".
// Hide recents and transition to the launcher.
EventBus.getDefault().send(new HideRecentsEvent(false, true));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 1e038c860be2..3f0000e645d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -124,7 +124,7 @@ public abstract class BaseStatusBar extends SystemUI implements
private static final boolean NOTIFICATION_CLICK_DEBUG = true;
public static final boolean ENABLE_REMOTE_INPUT =
- Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.enable_remote_input", false);
+ SystemProperties.getBoolean("debug.enable_remote_input", true);
public static final boolean ENABLE_CHILD_NOTIFICATIONS = Build.IS_DEBUGGABLE
&& SystemProperties.getBoolean("debug.child_notifs", false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
index 4ac2c3185b6d..a51f62ad0b69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.phone;
-import static android.app.ActivityManager.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import android.animation.LayoutTransition;
import android.annotation.Nullable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index ebe77853c1b2..fafedc33f0b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -128,7 +128,6 @@ public abstract class PanelView extends FrameLayout {
};
protected void onExpandingFinished() {
- endClosing();
mBar.onExpandingFinished();
}
@@ -143,6 +142,7 @@ public abstract class PanelView extends FrameLayout {
}
protected final void notifyExpandingFinished() {
+ endClosing();
if (mExpanding) {
mExpanding = false;
onExpandingFinished();
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 85187c776401..a7879c64bc13 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -562,6 +562,8 @@ class MountService extends IMountService.Stub
private static final int H_VOLUME_BROADCAST = 6;
private static final int H_INTERNAL_BROADCAST = 7;
private static final int H_VOLUME_UNMOUNT = 8;
+ private static final int H_PARTITION_FORGET = 9;
+ private static final int H_RESET = 10;
class MountServiceHandler extends Handler {
public MountServiceHandler(Looper looper) {
@@ -669,6 +671,16 @@ class MountService extends IMountService.Stub
final Intent intent = (Intent) msg.obj;
mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
android.Manifest.permission.WRITE_MEDIA_STORAGE);
+ break;
+ }
+ case H_PARTITION_FORGET: {
+ final String partGuid = (String) msg.obj;
+ forgetPartition(partGuid);
+ break;
+ }
+ case H_RESET: {
+ resetIfReadyAndConnected();
+ break;
}
}
}
@@ -753,9 +765,7 @@ class MountService extends IMountService.Stub
}
private void handleSystemReady() {
- synchronized (mLock) {
- resetIfReadyAndConnectedLocked();
- }
+ resetIfReadyAndConnected();
// Start scheduling nominally-daily fstrim operations
MountServiceIdler.scheduleIdlePass(mContext);
@@ -793,7 +803,7 @@ class MountService extends IMountService.Stub
}
}
- private void addInternalVolume() {
+ private void addInternalVolumeLocked() {
// Create a stub volume that represents internal storage
final VolumeInfo internal = new VolumeInfo(VolumeInfo.ID_PRIVATE_INTERNAL,
VolumeInfo.TYPE_PRIVATE, null, null);
@@ -802,18 +812,22 @@ class MountService extends IMountService.Stub
mVolumes.put(internal.id, internal);
}
- private void resetIfReadyAndConnectedLocked() {
+ private void resetIfReadyAndConnected() {
Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
+ ", mDaemonConnected=" + mDaemonConnected);
if (mSystemReady && mDaemonConnected) {
- final UserManager um = UserManager.get(mContext);
- final List<UserInfo> users = um.getUsers();
+ final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
killMediaProvider(users);
- mDisks.clear();
- mVolumes.clear();
+ final int[] startedUsers;
+ synchronized (mLock) {
+ startedUsers = mStartedUsers;
- addInternalVolume();
+ mDisks.clear();
+ mVolumes.clear();
+
+ addInternalVolumeLocked();
+ }
try {
mConnector.execute("volume", "reset");
@@ -822,7 +836,7 @@ class MountService extends IMountService.Stub
for (UserInfo user : users) {
mConnector.execute("volume", "user_added", user.id, user.serialNumber);
}
- for (int userId : mStartedUsers) {
+ for (int userId : startedUsers) {
mConnector.execute("volume", "user_started", userId);
}
} catch (NativeDaemonConnectorException e) {
@@ -898,9 +912,7 @@ class MountService extends IMountService.Stub
}
private void handleDaemonConnected() {
- synchronized (mLock) {
- resetIfReadyAndConnectedLocked();
- }
+ resetIfReadyAndConnected();
/*
* Now that we've done our initialization, release
@@ -1428,6 +1440,7 @@ class MountService extends IMountService.Stub
mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
null);
mConnector.setDebug(true);
+ mConnector.setWarnIfHeld(mLock);
Thread thread = new Thread(mConnector, VOLD_TAG);
thread.start();
@@ -1445,7 +1458,9 @@ class MountService extends IMountService.Stub
userFilter.addAction(Intent.ACTION_USER_REMOVED);
mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
- addInternalVolume();
+ synchronized (mLock) {
+ addInternalVolumeLocked();
+ }
// Add ourself to the Watchdog monitors if enabled.
if (WATCHDOG_ENABLE) {
@@ -1791,10 +1806,11 @@ class MountService extends IMountService.Stub
waitForReady();
Preconditions.checkNotNull(fsUuid);
+
synchronized (mLock) {
final VolumeRecord rec = mRecords.remove(fsUuid);
if (rec != null && !TextUtils.isEmpty(rec.partGuid)) {
- forgetPartition(rec.partGuid);
+ mHandler.obtainMessage(H_PARTITION_FORGET, rec.partGuid).sendToTarget();
}
mCallbacks.notifyVolumeForgotten(fsUuid);
@@ -1802,7 +1818,7 @@ class MountService extends IMountService.Stub
// reset vold so we bind into new volume into place.
if (Objects.equals(mPrimaryStorageUuid, fsUuid)) {
mPrimaryStorageUuid = getDefaultPrimaryStorageUuid();
- resetIfReadyAndConnectedLocked();
+ mHandler.obtainMessage(H_RESET).sendToTarget();
}
writeSettingsLocked();
@@ -1819,7 +1835,7 @@ class MountService extends IMountService.Stub
final String fsUuid = mRecords.keyAt(i);
final VolumeRecord rec = mRecords.valueAt(i);
if (!TextUtils.isEmpty(rec.partGuid)) {
- forgetPartition(rec.partGuid);
+ mHandler.obtainMessage(H_PARTITION_FORGET, rec.partGuid).sendToTarget();
}
mCallbacks.notifyVolumeForgotten(fsUuid);
}
@@ -1830,7 +1846,7 @@ class MountService extends IMountService.Stub
}
writeSettingsLocked();
- resetIfReadyAndConnectedLocked();
+ mHandler.obtainMessage(H_RESET).sendToTarget();
}
}
@@ -1878,7 +1894,7 @@ class MountService extends IMountService.Stub
}
writeSettingsLocked();
- resetIfReadyAndConnectedLocked();
+ mHandler.obtainMessage(H_RESET).sendToTarget();
}
}
@@ -1915,7 +1931,7 @@ class MountService extends IMountService.Stub
Slog.d(TAG, "Skipping move to/from primary physical");
onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
- resetIfReadyAndConnectedLocked();
+ mHandler.obtainMessage(H_RESET).sendToTarget();
} else {
final VolumeInfo from = findStorageForUuid(mPrimaryStorageUuid);
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index 519a2a3f4f88..e6b6074abf9c 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -28,6 +28,7 @@ import android.util.LocalLog;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
import com.google.android.collect.Lists;
import java.io.FileDescriptor;
@@ -57,6 +58,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
private LocalLog mLocalLog;
private volatile boolean mDebug = false;
+ private volatile Object mWarnIfHeld;
private final ResponseQueue mResponseQueue;
@@ -107,6 +109,15 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
mDebug = debug;
}
+ /**
+ * Yell loudly if someone tries making future {@link #execute(Command)}
+ * calls while holding a lock on the given object.
+ */
+ public void setWarnIfHeld(Object warnIfHeld) {
+ Preconditions.checkState(mWarnIfHeld == null);
+ mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
+ }
+
@Override
public void run() {
mCallbackHandler = new Handler(mLooper, this);
@@ -394,6 +405,11 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
*/
public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args)
throws NativeDaemonConnectorException {
+ if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
+ Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+ + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
+ }
+
final long startTime = SystemClock.elapsedRealtime();
final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index a0d305cdf2c6..3f0664defbf9 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -30,6 +30,7 @@ import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
+import android.os.PowerManager;
import android.provider.Settings;
import android.util.Log;
import android.util.NtpTrustedTime;
@@ -75,6 +76,7 @@ public class NetworkTimeUpdateService {
private SettingsObserver mSettingsObserver;
// The last time that we successfully fetched the NTP time.
private long mLastNtpFetchTime = NOT_SET;
+ private final PowerManager.WakeLock mWakeLock;
// Normal polling frequency
private final long mPollingIntervalMs;
@@ -104,6 +106,9 @@ public class NetworkTimeUpdateService {
com.android.internal.R.integer.config_ntpRetry);
mTimeErrorThresholdMs = mContext.getResources().getInteger(
com.android.internal.R.integer.config_ntpThreshold);
+
+ mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, TAG);
}
/** Initialize the receivers and initiate the first NTP request */
@@ -148,7 +153,15 @@ public class NetworkTimeUpdateService {
private void onPollNetworkTime(int event) {
// If Automatic time is not set, don't bother.
if (!isAutomaticTimeRequested()) return;
+ mWakeLock.acquire();
+ try {
+ onPollNetworkTimeUnderWakeLock(event);
+ } finally {
+ mWakeLock.release();
+ }
+ }
+ private void onPollNetworkTimeUnderWakeLock(int event) {
final long refTime = SystemClock.elapsedRealtime();
// If NITZ time was received less than mPollingIntervalMs time ago,
// no need to sync to NTP.
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index df6b1d63bee2..befaaef54e49 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -337,7 +337,7 @@ public final class ActiveServices {
ServiceRecord r = res.record;
- if (!mAm.getUserManagerLocked().exists(r.userId)) {
+ if (!mAm.mUserController.exists(r.userId)) {
Slog.d(TAG, "Trying to start service with non-existent user! " + r.userId);
return null;
}
@@ -1030,8 +1030,8 @@ public final class ActiveServices {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service
+ " type=" + resolvedType + " callingUid=" + callingUid);
- userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
- false, ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);
+ userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
+ ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);
ServiceMap smap = getServiceMap(userId);
final ComponentName comp = service.getComponent();
@@ -2333,7 +2333,8 @@ public final class ActiveServices {
EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
sr.userId, sr.crashCount, sr.shortName, app.pid);
bringDownServiceLocked(sr);
- } else if (!allowRestart || !mAm.isUserRunningLocked(sr.userId, false)) {
+ } else if (!allowRestart
+ || !mAm.mUserController.isUserRunningLocked(sr.userId, false)) {
bringDownServiceLocked(sr);
} else {
boolean canceled = scheduleServiceRestartLocked(sr, true);
@@ -2446,7 +2447,7 @@ public final class ActiveServices {
if (ActivityManager.checkUidPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
uid) == PackageManager.PERMISSION_GRANTED) {
- int[] users = mAm.getUsersLocked();
+ int[] users = mAm.mUserController.getUsers();
for (int ui=0; ui<users.length && res.size() < maxNum; ui++) {
ArrayMap<ComponentName, ServiceRecord> alls = getServices(users[ui]);
for (int i=0; i<alls.size() && res.size() < maxNum; i++) {
@@ -2580,7 +2581,7 @@ public final class ActiveServices {
pw.print(mLastAnrDump);
pw.println();
}
- int[] users = mAm.getUsersLocked();
+ int[] users = mAm.mUserController.getUsers();
for (int user : users) {
ServiceMap smap = getServiceMap(user);
boolean printed = false;
@@ -2817,7 +2818,7 @@ public final class ActiveServices {
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
synchronized (mAm) {
- int[] users = mAm.getUsersLocked();
+ int[] users = mAm.mUserController.getUsers();
if ("all".equals(name)) {
for (int user : users) {
ServiceMap smap = mServiceMap.get(user);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2d7298bb31a4..546db3e2d68a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -19,12 +19,11 @@ package com.android.server.am;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.HOME_STACK_ID;
-import static android.app.ActivityManager.INVALID_STACK_ID;
-import static android.app.ActivityManager.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
@@ -47,6 +46,7 @@ import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.Manifest;
+import android.app.ActivityManager.StackId;
import android.app.AppOpsManager;
import android.app.ApplicationThreadNative;
import android.app.BroadcastOptions;
@@ -207,7 +207,6 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IPermissionController;
import android.os.IProcessInfoService;
-import android.os.IUserManager;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
@@ -375,6 +374,13 @@ public final class ActivityManagerService extends ActivityManagerNative
// we will consider it to be doing interaction for usage stats.
static final int SERVICE_USAGE_INTERACTION_TIME = 30*60*1000;
+ // Maximum amount of time we will allow to elapse before re-reporting usage stats
+ // interaction with foreground processes.
+ static final long USAGE_STATS_INTERACTION_INTERVAL = 24*60*60*1000L;
+
+ // Maximum number of users we allow to be running at a time.
+ static final int MAX_RUNNING_USERS = 3;
+
// How long to wait in getAssistContextExtras for the activity and foreground services
// to respond with the result.
static final int PENDING_ASSIST_EXTRAS_TIMEOUT = 500;
@@ -1271,8 +1277,6 @@ public final class ActivityManagerService extends ActivityManagerNative
final ActivityThread mSystemThread;
- private UserManagerService mUserManager;
-
private final class AppDeathRecipient implements IBinder.DeathRecipient {
final ProcessRecord mApp;
final int mPid;
@@ -1400,7 +1404,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean isBackground = (UserHandle.getAppId(proc.uid)
>= Process.FIRST_APPLICATION_UID
&& proc.pid != MY_PID);
- for (int userId : mUserController.mCurrentProfileIds) {
+ for (int userId : mUserController.getCurrentProfileIdsLocked()) {
isBackground &= (proc.userId != userId);
}
if (isBackground && !showBackground) {
@@ -1565,7 +1569,7 @@ public final class ActivityManagerService extends ActivityManagerNative
break;
}
case START_USER_SWITCH_MSG: {
- showUserSwitchDialog(msg.arg1, (String) msg.obj);
+ mUserController.showUserSwitchDialog(msg.arg1, (String) msg.obj);
break;
}
case DISMISS_DIALOG_MSG: {
@@ -3591,8 +3595,7 @@ public final class ActivityManagerService extends ActivityManagerNative
void enforceShellRestriction(String restriction, int userHandle) {
if (Binder.getCallingUid() == Process.SHELL_UID) {
- if (userHandle < 0
- || mUserManager.hasUserRestriction(restriction, userHandle)) {
+ if (userHandle < 0 || mUserController.hasUserRestriction(restriction, userHandle)) {
throw new SecurityException("Shell does not have permission to access user "
+ userHandle);
}
@@ -3854,8 +3857,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false, ALLOW_FULL_ONLY, "startActivity", null);
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
@@ -3945,8 +3948,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivityAndWait");
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false, ALLOW_FULL_ONLY, "startActivityAndWait", null);
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, ALLOW_FULL_ONLY, "startActivityAndWait", null);
WaitResult res = new WaitResult();
// TODO: Switch to user app stacks here.
mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
@@ -3960,8 +3963,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, Configuration config, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivityWithConfig");
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false, ALLOW_FULL_ONLY, "startActivityWithConfig", null);
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, ALLOW_FULL_ONLY, "startActivityWithConfig", null);
// TODO: Switch to user app stacks here.
int ret = mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
@@ -4018,8 +4021,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (session == null || interactor == null) {
throw new NullPointerException("null session or interactor");
}
- userId = handleIncomingUser(callingPid, callingUid, userId,
- false, ALLOW_FULL_ONLY, "startVoiceActivity", null);
+ userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
+ ALLOW_FULL_ONLY, "startVoiceActivity", null);
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(null, callingUid, callingPackage, intent,
resolvedType, session, interactor, null, null, 0, startFlags, profilerInfo, null,
@@ -4089,8 +4092,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (debug) {
Slog.v(TAG, "Next matching activity: found current " + r.packageName
+ "/" + r.info.name);
- Slog.v(TAG, "Next matching activity: next is " + aInfo.packageName
- + "/" + aInfo.name);
+ Slog.v(TAG, "Next matching activity: next is " + ((aInfo == null)
+ ? "null" : aInfo.packageName + "/" + aInfo.name));
}
break;
}
@@ -4207,8 +4210,8 @@ public final class ActivityManagerService extends ActivityManagerNative
String resultWho, int requestCode, int startFlags, Bundle options, int userId,
IActivityContainer container, TaskRecord inTask) {
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false, ALLOW_FULL_ONLY, "startActivityInPackage", null);
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, ALLOW_FULL_ONLY, "startActivityInPackage", null);
// TODO: Switch to user app stacks here.
int ret = mStackSupervisor.startActivityMayWait(null, uid, callingPackage, intent,
@@ -4222,8 +4225,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle options,
int userId) {
enforceNotIsolatedCaller("startActivities");
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false, ALLOW_FULL_ONLY, "startActivity", null);
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
int ret = mStackSupervisor.startActivities(caller, -1, callingPackage, intents,
resolvedTypes, resultTo, options, userId);
@@ -4234,8 +4237,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Intent[] intents, String[] resolvedTypes, IBinder resultTo,
Bundle options, int userId) {
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false, ALLOW_FULL_ONLY, "startActivityInPackage", null);
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, ALLOW_FULL_ONLY, "startActivityInPackage", null);
// TODO: Switch to user app stacks here.
int ret = mStackSupervisor.startActivities(null, uid, callingPackage, intents, resolvedTypes,
resultTo, options, userId);
@@ -5136,8 +5139,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
- userId = handleIncomingUser(pid, uid,
- userId, false, ALLOW_FULL_ONLY, "clearApplicationUserData", null);
+ userId = mUserController.handleIncomingUser(pid, uid, userId, false,
+ ALLOW_FULL_ONLY, "clearApplicationUserData", null);
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
@@ -5216,7 +5219,7 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, true, ALLOW_FULL_ONLY, "killBackgroundProcesses", null);
long callingId = Binder.clearCallingIdentity();
try {
@@ -5299,14 +5302,14 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
final int callingPid = Binder.getCallingPid();
- userId = handleIncomingUser(callingPid, Binder.getCallingUid(),
+ userId = mUserController.handleIncomingUser(callingPid, Binder.getCallingUid(),
userId, true, ALLOW_FULL_ONLY, "forceStopPackage", null);
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
synchronized(this) {
int[] users = userId == UserHandle.USER_ALL
- ? getUsersLocked() : new int[] { userId };
+ ? mUserController.getUsers() : new int[] { userId };
for (int user : users) {
int pkgUid = -1;
try {
@@ -5324,7 +5327,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, "Failed trying to unstop package "
+ packageName + ": " + e);
}
- if (isUserRunningLocked(user, false)) {
+ if (mUserController.isUserRunningLocked(user, false)) {
forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid);
}
}
@@ -6662,7 +6665,7 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(this) {
int callingUid = Binder.getCallingUid();
int origUserId = userId;
- userId = handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
type == ActivityManager.INTENT_SENDER_BROADCAST,
ALLOW_NON_FULL, "getIntentSender", null);
if (origUserId == UserHandle.USER_CURRENT) {
@@ -7910,8 +7913,9 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, Uri uri,
final int modeFlags, int sourceUserId, int targetUserId) {
- targetUserId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
- targetUserId, false, ALLOW_FULL_ONLY, "grantUriPermissionFromOwner", null);
+ targetUserId = mUserController.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), targetUserId, false, ALLOW_FULL_ONLY,
+ "grantUriPermissionFromOwner", null);
synchronized(this) {
UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
if (owner == null) {
@@ -8418,7 +8422,7 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags, int userId) {
final int callingUid = Binder.getCallingUid();
- userId = handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
false, ALLOW_FULL_ONLY, "getRecentTasks", null);
final boolean includeProfiles = (flags & ActivityManager.RECENT_INCLUDE_PROFILES) != 0;
@@ -8436,7 +8440,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final Set<Integer> includedUsers;
if (includeProfiles) {
- includedUsers = getProfileIdsLocked(userId);
+ includedUsers = mUserController.getProfileIds(userId);
} else {
includedUsers = new HashSet<>();
}
@@ -8654,12 +8658,9 @@ public final class ActivityManagerService extends ActivityManagerNative
// - a non-null bounds on a non-freeform (fullscreen OR docked) task moves
// that task to freeform
// - otherwise the task is not moved
- // Note it's not allowed to resize a home, docked, or pinned stack task.
int stackId = task.stack.mStackId;
- if (stackId == HOME_STACK_ID || stackId == DOCKED_STACK_ID
- || stackId == PINNED_STACK_ID) {
- throw new IllegalArgumentException("trying to resizeTask on a "
- + "home or docked task");
+ if (!StackId.isTaskResizeAllowed(stackId)) {
+ throw new IllegalArgumentException("resizeTask not allowed on task=" + task);
}
if (bounds == null && stackId == FREEFORM_WORKSPACE_STACK_ID) {
stackId = FULLSCREEN_WORKSPACE_STACK_ID;
@@ -9461,16 +9462,15 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean checkedGrants = false;
if (checkUser) {
// Looking for cross-user grants before enforcing the typical cross-users permissions
- int tmpTargetUserId = unsafeConvertIncomingUserLocked(userId);
+ int tmpTargetUserId = mUserController.unsafeConvertIncomingUserLocked(userId);
if (tmpTargetUserId != UserHandle.getUserId(callingUid)) {
if (checkAuthorityGrants(callingUid, cpi, tmpTargetUserId, checkUser)) {
return null;
}
checkedGrants = true;
}
- userId = handleIncomingUser(callingPid, callingUid, userId,
- false, ALLOW_NON_FULL,
- "checkContentProviderPermissionLocked " + cpi.authority, null);
+ userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
+ ALLOW_NON_FULL, "checkContentProviderPermissionLocked " + cpi.authority, null);
if (userId != tmpTargetUserId) {
// When we actually went to determine the final targer user ID, this ended
// up different than our initial check for the authority. This is because
@@ -9809,7 +9809,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Make sure that the user who owns this provider is running. If not,
// we don't want to allow it to run.
- if (!isUserRunningLocked(userId, false)) {
+ if (!mUserController.isUserRunningLocked(userId, false)) {
Slog.w(TAG, "Unable to launch app "
+ cpi.applicationInfo.packageName + "/"
+ cpi.applicationInfo.uid + " for provider "
@@ -9995,8 +9995,8 @@ public final class ActivityManagerService extends ActivityManagerNative
String name, int userId, IBinder token) {
enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
"Do not have permission in call getContentProviderExternal()");
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false, ALLOW_FULL_ONLY, "getContentProvider", null);
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, false, ALLOW_FULL_ONLY, "getContentProvider", null);
return getContentProviderExternalUnchecked(name, token, userId);
}
@@ -10308,7 +10308,7 @@ public final class ActivityManagerService extends ActivityManagerNative
long ident = 0;
boolean clearedIdentity = false;
synchronized (this) {
- userId = unsafeConvertIncomingUserLocked(userId);
+ userId = mUserController.unsafeConvertIncomingUserLocked(userId);
}
if (canClearIdentity(callingPid, callingUid, userId)) {
clearedIdentity = true;
@@ -10978,7 +10978,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public boolean isAssistDataAllowedOnCurrentActivity() {
int userId;
synchronized (this) {
- userId = mUserController.mCurrentUserId;
+ userId = mUserController.getCurrentUserIdLocked();
ActivityRecord activity = getFocusedStack().topActivity();
if (activity == null) {
return false;
@@ -11893,7 +11893,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// TODO: can we still do this with per user encryption?
- final int[] users = getUsersLocked();
+ final int[] users = mUserController.getUsers();
if (users.length <= 0) {
return false;
}
@@ -11923,8 +11923,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mUserController.updateCurrentProfileIdsLocked();
mRecentTasks.clear();
- mRecentTasks.addAll(mTaskPersister.restoreTasksLocked(
- getUserManagerLocked().getUserIds()));
+ mRecentTasks.addAll(mTaskPersister.restoreTasksLocked(mUserController.getUserIds()));
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
mTaskPersister.startPersisting();
@@ -12029,7 +12028,7 @@ public final class ActivityManagerService extends ActivityManagerNative
loadResourcesOnSystemReady();
final int currentUserId;
synchronized (this) {
- currentUserId = mUserController.mCurrentUserId;
+ currentUserId = mUserController.getCurrentUserIdLocked();
readGrantedUriPermissionsLocked();
}
@@ -12113,7 +12112,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Binder.restoreCallingIdentity(ident);
}
mStackSupervisor.resumeTopActivitiesLocked();
- sendUserSwitchBroadcastsLocked(-1, currentUserId);
+ mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
}
}
@@ -12313,7 +12312,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// launching the report UI under a different user.
app.errorReportReceiver = null;
- for (int userId : mUserController.mCurrentProfileIds) {
+ for (int userId : mUserController.getCurrentProfileIdsLocked()) {
if (app.userId == userId) {
app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver(
mContext, app.info.packageName, app.info.flags);
@@ -16034,97 +16033,10 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
boolean requireFull, String name, String callerPackage) {
- return handleIncomingUser(callingPid, callingUid, userId, allowAll,
+ return mUserController.handleIncomingUser(callingPid, callingUid, userId, allowAll,
requireFull ? ALLOW_FULL_ONLY : ALLOW_NON_FULL, name, callerPackage);
}
- int unsafeConvertIncomingUserLocked(int userId) {
- return (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF)
- ? mUserController.mCurrentUserId : userId;
- }
-
- int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
- int allowMode, String name, String callerPackage) {
- final int callingUserId = UserHandle.getUserId(callingUid);
- if (callingUserId == userId) {
- return userId;
- }
-
- // Note that we may be accessing mCurrentUserId outside of a lock...
- // shouldn't be a big deal, if this is being called outside
- // of a locked context there is intrinsically a race with
- // the value the caller will receive and someone else changing it.
- // We assume that USER_CURRENT_OR_SELF will use the current user; later
- // we will switch to the calling user if access to the current user fails.
- int targetUserId = unsafeConvertIncomingUserLocked(userId);
-
- if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
- final boolean allow;
- if (checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid,
- callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
- // If the caller has this permission, they always pass go. And collect $200.
- allow = true;
- } else if (allowMode == ALLOW_FULL_ONLY) {
- // We require full access, sucks to be you.
- allow = false;
- } else if (checkComponentPermission(INTERACT_ACROSS_USERS, callingPid,
- callingUid, -1, true) != PackageManager.PERMISSION_GRANTED) {
- // If the caller does not have either permission, they are always doomed.
- allow = false;
- } else if (allowMode == ALLOW_NON_FULL) {
- // We are blanket allowing non-full access, you lucky caller!
- allow = true;
- } else if (allowMode == ALLOW_NON_FULL_IN_PROFILE) {
- // We may or may not allow this depending on whether the two users are
- // in the same profile.
- allow = mUserController.isSameProfileGroup(callingUserId, targetUserId);
- } else {
- throw new IllegalArgumentException("Unknown mode: " + allowMode);
- }
- if (!allow) {
- if (userId == UserHandle.USER_CURRENT_OR_SELF) {
- // In this case, they would like to just execute as their
- // owner user instead of failing.
- targetUserId = callingUserId;
- } else {
- StringBuilder builder = new StringBuilder(128);
- builder.append("Permission Denial: ");
- builder.append(name);
- if (callerPackage != null) {
- builder.append(" from ");
- builder.append(callerPackage);
- }
- builder.append(" asks to run as user ");
- builder.append(userId);
- builder.append(" but is calling from user ");
- builder.append(UserHandle.getUserId(callingUid));
- builder.append("; this requires ");
- builder.append(INTERACT_ACROSS_USERS_FULL);
- if (allowMode != ALLOW_FULL_ONLY) {
- builder.append(" or ");
- builder.append(INTERACT_ACROSS_USERS);
- }
- String msg = builder.toString();
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
- }
- }
- if (!allowAll && targetUserId < 0) {
- throw new IllegalArgumentException(
- "Call does not support special user #" + targetUserId);
- }
- // Check shell permission
- if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_SYSTEM) {
- if (mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES,
- targetUserId)) {
- throw new SecurityException("Shell does not have permission to access user "
- + targetUserId + "\n " + Debug.getCallers(3));
- }
- }
- return targetUserId;
- }
-
boolean isSingleton(String componentProcessName, ApplicationInfo aInfo,
String className, int flags) {
boolean result = false;
@@ -16437,8 +16349,8 @@ public final class ActivityManagerService extends ActivityManagerNative
callingPid = Binder.getCallingPid();
}
- userId = handleIncomingUser(callingPid, callingUid, userId,
- true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
+ userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
+ ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
Iterator<String> actions = filter.actionsIterator();
if (actions == null) {
@@ -16628,8 +16540,8 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int user : users) {
// Skip users that have Shell restrictions
if (callingUid == Process.SHELL_UID
- && getUserManagerLocked().hasUserRestriction(
- UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
+ && mUserController.hasUserRestriction(
+ UserManager.DISALLOW_DEBUGGING_FEATURES, user)) {
continue;
}
List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
@@ -16718,14 +16630,14 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
}
- userId = handleIncomingUser(callingPid, callingUid, userId,
- true, ALLOW_NON_FULL, "broadcast", callerPackage);
+ userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
+ ALLOW_NON_FULL, "broadcast", callerPackage);
// Make sure that the user who is receiving this broadcast is running.
// If not, we will just skip it. Make an exception for shutdown broadcasts
// and upgrade steps.
- if (userId != UserHandle.USER_ALL && !isUserRunningLocked(userId, false)) {
+ if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, false)) {
if ((callingUid != Process.SYSTEM_UID
|| (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
&& !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
@@ -17030,9 +16942,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
// Query one target user at a time, excluding shell-restricted users
- UserManagerService ums = getUserManagerLocked();
for (int i = 0; i < users.length; i++) {
- if (ums.hasUserRestriction(
+ if (mUserController.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
continue;
}
@@ -17250,7 +17161,7 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new IllegalArgumentException("File descriptors passed in Intent");
}
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, true, ALLOW_NON_FULL, "removeStickyBroadcast", null);
synchronized(this) {
@@ -17334,7 +17245,7 @@ public final class ActivityManagerService extends ActivityManagerNative
IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection,
int userId, String abiOverride) {
enforceNotIsolatedCaller("startInstrumentation");
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startInstrumentation", null);
// Refuse possible leaked file descriptors
if (arguments != null && arguments.hasFileDescriptors()) {
@@ -17600,10 +17511,11 @@ public final class ActivityManagerService extends ActivityManagerNative
Binder.restoreCallingIdentity(origId);
}
}
+
void updateUserConfigurationLocked() {
Configuration configuration = new Configuration(mConfiguration);
Settings.System.getConfigurationForUser(mContext.getContentResolver(), configuration,
- mUserController.mCurrentUserId);
+ mUserController.getCurrentUserIdLocked());
updateConfigurationLocked(configuration, null, false);
}
@@ -17652,7 +17564,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mConfiguration = newConfig;
Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig);
mUsageStatsService.reportConfigurationChange(newConfig,
- mUserController.mCurrentUserId);
+ mUserController.getCurrentUserIdLocked());
//mUsageStatsService.noteStartConfig(newConfig);
final Configuration configCopy = new Configuration(mConfiguration);
@@ -18921,7 +18833,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now) {
+ private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
+ long nowElapsed) {
boolean success = true;
if (app.curRawAdj != app.setRawAdj) {
@@ -19025,7 +18938,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (app.setProcState != app.curProcState) {
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
"Proc state change of " + app.processName
- + " to " + app.curProcState);
+ + " to " + app.curProcState);
boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE;
boolean curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE;
if (setImportant && !curImportant) {
@@ -19036,14 +18949,14 @@ public final class ActivityManagerService extends ActivityManagerNative
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
- app.pid, SystemClock.elapsedRealtime());
+ app.pid, nowElapsed);
}
app.lastCpuTime = app.curCpuTime;
}
// Inform UsageStats of important process state change
// Must be called before updating setProcState
- maybeUpdateUsageStatsLocked(app);
+ maybeUpdateUsageStatsLocked(app, nowElapsed);
app.setProcState = app.curProcState;
if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
@@ -19054,6 +18967,11 @@ public final class ActivityManagerService extends ActivityManagerNative
} else {
app.procStateChanged = true;
}
+ } else if (app.reportedInteraction && (nowElapsed-app.interactionEventTime)
+ > USAGE_STATS_INTERACTION_INTERVAL) {
+ // For apps that sit around for a long time in the interactive state, we need
+ // to report this at least once a day so they don't go idle.
+ maybeUpdateUsageStatsLocked(app, nowElapsed);
}
if (changes != 0) {
@@ -19136,7 +19054,7 @@ public final class ActivityManagerService extends ActivityManagerNative
String authority) {
if (app == null) return;
if (app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
- UserState userState = mUserController.getStartedUserState(app.userId);
+ UserState userState = mUserController.getStartedUserStateLocked(app.userId);
if (userState == null) return;
final long now = SystemClock.elapsedRealtime();
Long lastReported = userState.mProviderLastReportedFg.get(authority);
@@ -19148,7 +19066,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- private void maybeUpdateUsageStatsLocked(ProcessRecord app) {
+ private void maybeUpdateUsageStatsLocked(ProcessRecord app, long nowElapsed) {
if (DEBUG_USAGE_STATS) {
Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList())
+ "] state changes: old = " + app.setProcState + ", new = "
@@ -19165,19 +19083,20 @@ public final class ActivityManagerService extends ActivityManagerNative
isInteraction = true;
app.fgInteractionTime = 0;
} else if (app.curProcState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
- final long now = SystemClock.elapsedRealtime();
if (app.fgInteractionTime == 0) {
- app.fgInteractionTime = now;
+ app.fgInteractionTime = nowElapsed;
isInteraction = false;
} else {
- isInteraction = now > app.fgInteractionTime + SERVICE_USAGE_INTERACTION_TIME;
+ isInteraction = nowElapsed > app.fgInteractionTime + SERVICE_USAGE_INTERACTION_TIME;
}
} else {
isInteraction = app.curProcState
<= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
app.fgInteractionTime = 0;
}
- if (isInteraction && !app.reportedInteraction) {
+ if (isInteraction && (!app.reportedInteraction
+ || (nowElapsed-app.interactionEventTime) > USAGE_STATS_INTERACTION_INTERVAL)) {
+ app.interactionEventTime = nowElapsed;
String[] packages = app.getPackageList();
if (packages != null) {
for (int i = 0; i < packages.length; i++) {
@@ -19187,6 +19106,9 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
app.reportedInteraction = isInteraction;
+ if (!isInteraction) {
+ app.interactionEventTime = 0;
+ }
}
private final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) {
@@ -19209,7 +19131,7 @@ public final class ActivityManagerService extends ActivityManagerNative
computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now);
- return applyOomAdjLocked(app, doingAll, now);
+ return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime());
}
final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground,
@@ -19301,6 +19223,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final ActivityRecord TOP_ACT = resumedAppLocked();
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
final long now = SystemClock.uptimeMillis();
+ final long nowElapsed = SystemClock.elapsedRealtime();
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
final int N = mLruProcesses.size();
@@ -19429,7 +19352,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- applyOomAdjLocked(app, true, now);
+ applyOomAdjLocked(app, true, now, nowElapsed);
// Count the number of process types.
switch (app.curProcState) {
@@ -19858,7 +19781,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private ProcessRecord findProcessLocked(String process, int userId, String callName) {
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, true, ALLOW_FULL_ONLY, callName, null);
ProcessRecord proc = null;
try {
@@ -20019,31 +19942,12 @@ public final class ActivityManagerService extends ActivityManagerNative
return mUserController.startUser(userId, /* foreground */ false);
}
- /**
- * Start user, if its not already running, and bring it to foreground.
- */
- boolean startUserInForeground(final int userId, Dialog dlg) {
- boolean result = mUserController.startUser(userId, /* foreground */ true);
- dlg.dismiss();
- return result;
- }
-
- private Set<Integer> getProfileIdsLocked(int userId) {
- Set<Integer> userIds = new HashSet<Integer>();
- final List<UserInfo> profiles = getUserManagerLocked().getProfiles(
- userId, false /* enabledOnly */);
- for (UserInfo user : profiles) {
- userIds.add(Integer.valueOf(user.id));
- }
- return userIds;
- }
-
@Override
public boolean switchUser(final int userId) {
enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId);
String userName;
synchronized (this) {
- UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
+ UserInfo userInfo = mUserController.getUserInfo(userId);
if (userInfo == null) {
Slog.w(TAG, "No user info for user #" + userId);
return false;
@@ -20053,68 +19957,13 @@ public final class ActivityManagerService extends ActivityManagerNative
return false;
}
userName = userInfo.name;
- mUserController.mTargetUserId = userId;
+ mUserController.setTargetUserIdLocked(userId);
}
mUiHandler.removeMessages(START_USER_SWITCH_MSG);
mUiHandler.sendMessage(mUiHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName));
return true;
}
- private void showUserSwitchDialog(int userId, String userName) {
- // The dialog will show and then initiate the user switch by calling startUserInForeground
- Dialog d = new UserSwitchingDialog(this, mContext, userId, userName,
- true /* above system */);
- d.show();
- }
-
- void sendUserSwitchBroadcastsLocked(int oldUserId, int newUserId) {
- long ident = Binder.clearCallingIdentity();
- try {
- Intent intent;
- if (oldUserId >= 0) {
- // Send USER_BACKGROUND broadcast to all profiles of the outgoing user
- List<UserInfo> profiles = mUserManager.getProfiles(oldUserId, false);
- int count = profiles.size();
- for (int i = 0; i < count; i++) {
- int profileUserId = profiles.get(i).id;
- intent = new Intent(Intent.ACTION_USER_BACKGROUND);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, Process.SYSTEM_UID, profileUserId);
- }
- }
- if (newUserId >= 0) {
- // Send USER_FOREGROUND broadcast to all profiles of the incoming user
- List<UserInfo> profiles = mUserManager.getProfiles(newUserId, false);
- int count = profiles.size();
- for (int i = 0; i < count; i++) {
- int profileUserId = profiles.get(i).id;
- intent = new Intent(Intent.ACTION_USER_FOREGROUND);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, Process.SYSTEM_UID, profileUserId);
- }
- intent = new Intent(Intent.ACTION_USER_SWITCHED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null,
- new String[] {android.Manifest.permission.MANAGE_USERS},
- AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID,
- UserHandle.USER_ALL);
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
void scheduleStartProfilesLocked() {
if (!mHandler.hasMessages(START_PROFILES_MSG)) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG),
@@ -20148,20 +19997,8 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
synchronized (this) {
- return isUserRunningLocked(userId, orStopped);
- }
- }
-
- boolean isUserRunningLocked(int userId, boolean orStopped) {
- UserState state = mUserController.getStartedUserState(userId);
- if (state == null) {
- return false;
- }
- if (orStopped) {
- return true;
+ return mUserController.isUserRunningLocked(userId, orStopped);
}
- return state.mState != UserState.STATE_STOPPING
- && state.mState != UserState.STATE_SHUTDOWN;
}
@Override
@@ -20190,19 +20027,6 @@ public final class ActivityManagerService extends ActivityManagerNative
mUserController.unregisterUserSwitchObserver(observer);
}
- int[] getUsersLocked() {
- UserManagerService ums = getUserManagerLocked();
- return ums != null ? ums.getUserIds() : new int[] { 0 };
- }
-
- UserManagerService getUserManagerLocked() {
- if (mUserManager == null) {
- IBinder b = ServiceManager.getService(Context.USER_SERVICE);
- mUserManager = (UserManagerService)IUserManager.Stub.asInterface(b);
- }
- return mUserManager;
- }
-
private int applyUserId(int uid, int userId) {
return UserHandle.getUid(userId, uid);
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index b5f424d34adf..ee9aa11b5d26 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -16,14 +16,11 @@
package com.android.server.am;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
-import static android.app.ActivityManager.FIRST_STATIC_STACK_ID;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.HOME_STACK_ID;
-import static android.app.ActivityManager.INVALID_STACK_ID;
-import static android.app.ActivityManager.LAST_STATIC_STACK_ID;
-import static android.app.ActivityManager.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static com.android.server.am.ActivityManagerDebugConfig.*;
@@ -49,6 +46,7 @@ import com.android.server.wm.WindowManagerService;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityController;
@@ -255,9 +253,6 @@ final class ActivityStack {
private final LaunchingTaskPositioner mTaskPositioner;
- // If the bounds of task contained in this stack should be persisted across power cycles.
- final boolean mPersistTaskBounds;
-
static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
@@ -367,11 +362,10 @@ final class ActivityStack {
mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
mWindowManager = mService.mWindowManager;
mStackId = activityContainer.mStackId;
- mCurrentUser = mService.mUserController.mCurrentUserId;
+ mCurrentUser = mService.mUserController.getCurrentUserIdLocked();
mRecentTasks = recentTasks;
mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID
? new LaunchingTaskPositioner() : null;
- mPersistTaskBounds = mStackId != DOCKED_STACK_ID && mStackId != PINNED_STACK_ID;
}
void attachDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) {
@@ -1365,7 +1359,7 @@ final class ActivityStack {
}
}
- if (mStackId >= FIRST_STATIC_STACK_ID && mStackId <= LAST_STATIC_STACK_ID) {
+ if (StackId.isStaticStack(mStackId)) {
// Visibility of any static stack should have been determined by the conditions above.
return false;
}
@@ -1377,9 +1371,7 @@ final class ActivityStack {
continue;
}
- if (stack.mStackId == FREEFORM_WORKSPACE_STACK_ID
- || stack.mStackId == HOME_STACK_ID
- || stack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
+ if (!StackId.isDynamicStacksVisibleBehindAllowed(stack.mStackId)) {
// These stacks can't have any dynamic stacks visible behind them.
return false;
}
@@ -1464,29 +1456,35 @@ final class ActivityStack {
}
if (r.app == null || r.app.thread == null) {
- // This activity needs to be visible, but isn't even running...
- // get it started and resume if no other stack in this stack is resumed.
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
- "Start and freeze screen for " + r);
- if (r != starting) {
- r.startFreezingScreenLocked(r.app, configChanges);
- }
- if (!r.visible || r.mLaunchTaskBehind) {
+ // We need to make sure the app is running if it's the top, or it is
+ // just made visible from invisible.
+ // If the app is already visible, it must have died while it was visible.
+ // In this case, we'll show the dead window but will not restart the app.
+ // Otherwise we could end up thrashing.
+ if (r == top || !r.visible) {
+ // This activity needs to be visible, but isn't even running...
+ // get it started and resume if no other stack in this stack is resumed.
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
- "Starting and making visible: " + r);
- setVisible(r, true);
- }
- if (r != starting) {
- mStackSupervisor.startSpecificActivityLocked(
- r, noStackActivityResumed, false);
- if (activityNdx >= activities.size()) {
- // Record may be removed if its process needs to restart.
- activityNdx = activities.size() - 1;
- } else {
- noStackActivityResumed = false;
+ "Start and freeze screen for " + r);
+ if (r != starting) {
+ r.startFreezingScreenLocked(r.app, configChanges);
+ }
+ if (!r.visible || r.mLaunchTaskBehind) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+ "Starting and making visible: " + r);
+ setVisible(r, true);
+ }
+ if (r != starting) {
+ mStackSupervisor.startSpecificActivityLocked(
+ r, noStackActivityResumed, false);
+ if (activityNdx >= activities.size()) {
+ // Record may be removed if its process needs to restart.
+ activityNdx = activities.size() - 1;
+ } else {
+ noStackActivityResumed = false;
+ }
}
}
-
} else if (r.visible) {
// If this activity is already visible, then there is nothing
// else to do here.
@@ -2797,8 +2795,7 @@ final class ActivityStack {
ActivityRecord next = topRunningActivityLocked();
final String myReason = reason + " adjustFocus";
if (next != r) {
- if (next != null && (mStackId == FREEFORM_WORKSPACE_STACK_ID
- || mStackId == DOCKED_STACK_ID || mStackId == PINNED_STACK_ID)) {
+ if (next != null && StackId.keepFocusInStackIfPossible(mStackId)) {
// For freeform, docked, and pinned stacks we always keep the focus within the
// stack as long as there is a running activity in the stack that we can adjust
// focus to.
@@ -3740,10 +3737,13 @@ final class ActivityStack {
// Don't currently have state for the activity, or
// it is finishing -- always remove it.
remove = true;
- } else if (r.launchCount > 2 &&
- r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) {
+ } else if (!r.visible && r.launchCount > 2 &&
+ r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
// We have launched this activity too many times since it was
// able to run, so give up and remove it.
+ // (Note if the activity is visible, we don't remove the record.
+ // We leave the dead window on the screen but the process will
+ // not be restarted unless user explicitly tap on it.)
remove = true;
} else {
// The process may be gone, but the activity lives on!
@@ -3773,7 +3773,11 @@ final class ActivityStack {
if (DEBUG_APP) Slog.v(TAG_APP,
"Clearing app during removeHistory for activity " + r);
r.app = null;
- r.nowVisible = false;
+ // Set nowVisible to previous visible state. If the app was visible while
+ // it died, we leave the dead window on screen so it's basically visible.
+ // This is needed when user later tap on the dead window, we need to stop
+ // other apps when user transfers focus to the restarted activity.
+ r.nowVisible = r.visible;
if (!r.haveState) {
if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
"App died, clearing saved state of " + r);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 1cd71a1cb61a..f262ec9a1702 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -18,6 +18,15 @@ package com.android.server.am;
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.app.ActivityManager.*;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
+import static android.app.ActivityManager.StackId.FIRST_STATIC_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -40,6 +49,7 @@ import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityOptions;
import android.app.AppGlobals;
@@ -364,13 +374,26 @@ public final class ActivityStackSupervisor implements DisplayListener {
final ActivityRecord sourceRecord;
final int startFlags;
final ActivityStack stack;
+ final ProcessRecord callerApp;
PendingActivityLaunch(ActivityRecord _r, ActivityRecord _sourceRecord,
- int _startFlags, ActivityStack _stack) {
+ int _startFlags, ActivityStack _stack, ProcessRecord _callerApp) {
r = _r;
sourceRecord = _sourceRecord;
startFlags = _startFlags;
stack = _stack;
+ callerApp = _callerApp;
+ }
+
+ void sendErrorResult(String message) {
+ try {
+ if (callerApp.thread != null) {
+ callerApp.thread.scheduleCrash(message);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception scheduling crash of failed "
+ + "activity launcher sourceRecord=" + sourceRecord, e);
+ }
}
}
@@ -554,8 +577,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
* @param id Id of the task we would like returned.
* @param restoreFromRecents If the id was not in the active list, but was found in recents,
* restore the task from recents to the active list.
- * @param stackId The stack to restore the task to (default launch stack will be used
- * if stackId is {@link android.app.ActivityManager#INVALID_STACK_ID}).
+ * @param stackId The stack to restore the task to (default launch stack will be used if
+ * stackId is {@link android.app.ActivityManager.StackId#INVALID_STACK_ID}).
*/
TaskRecord anyTaskForIdLocked(int id, boolean restoreFromRecents, int stackId) {
int numDisplays = mActivityDisplays.size();
@@ -1668,8 +1691,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
- PendingActivityLaunch pal =
- new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
+ PendingActivityLaunch pal = new PendingActivityLaunch(r,
+ sourceRecord, startFlags, stack, callerApp);
mPendingActivityLaunches.add(pal);
ActivityOptions.abort(options);
return ActivityManager.START_SWITCHES_CANCELED;
@@ -1820,8 +1843,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
stack = homeDisplayStacks.get(stackNdx);
- final boolean isDynamicStack = stack.mStackId >= FIRST_DYNAMIC_STACK_ID;
- if (isDynamicStack) {
+ if (!StackId.isStaticStack(stack.mStackId)) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Setting focused stack=" + stack);
return stack;
@@ -2536,9 +2558,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
try {
startActivityUncheckedLocked(pal.r, pal.sourceRecord, null, null, pal.startFlags,
- doResume && mPendingActivityLaunches.isEmpty(), null, null);
+ doResume && mPendingActivityLaunches.isEmpty(), null, null);
} catch (Exception e) {
- Slog.w(TAG, "Exception during pending activity launch pal=" + pal, e);
+ Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
+ pal.sendErrorResult(e.getMessage());
}
}
}
@@ -2863,25 +2886,25 @@ public final class ActivityStackSupervisor implements DisplayListener {
return;
}
- int stackId = task.stack.mStackId;
if (task.mResizeable && options != null) {
ActivityOptions opts = new ActivityOptions(options);
if (opts.hasBounds()) {
Rect bounds = opts.getBounds();
task.updateOverrideConfiguration(bounds);
+ final int stackId = task.getLaunchStackId();
+ if (stackId != task.stack.mStackId) {
+ moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason);
+ // moveTaskToStackUncheckedLocked() should already placed the task on top,
+ // still need moveTaskToFrontLocked() below for any transition settings.
+ }
+ // WM resizeTask must be done after the task is moved to the correct stack,
+ // because Task's setBounds() also updates dim layer's bounds, but that has
+ // dependency on the stack.
mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig,
false /*relayout*/, false /*forced*/);
- stackId = task.getLaunchStackId();
}
}
- if (stackId != task.stack.mStackId) {
- moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason);
-
- // moveTaskToStackUncheckedLocked() should already placed the task on top,
- // still need moveTaskToFrontLocked() below for any transition settings.
- }
-
final ActivityRecord r = task.getTopActivity();
task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
r == null ? null : r.appTimeTracker, reason);
@@ -2899,15 +2922,14 @@ public final class ActivityStackSupervisor implements DisplayListener {
if (activityContainer != null) {
return activityContainer.mStack;
}
- if (!createStaticStackIfNeeded
- || (stackId < FIRST_STATIC_STACK_ID || stackId > LAST_STATIC_STACK_ID)) {
+ if (!createStaticStackIfNeeded || !StackId.isStaticStack(stackId)) {
return null;
}
return createStackOnDisplay(stackId, Display.DEFAULT_DISPLAY, createOnTop);
}
ArrayList<ActivityStack> getStacks() {
- ArrayList<ActivityStack> allStacks = new ArrayList<ActivityStack>();
+ ArrayList<ActivityStack> allStacks = new ArrayList<>();
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
allStacks.addAll(mActivityDisplays.valueAt(displayNdx).mStacks);
}
@@ -3025,7 +3047,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
// 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++) {
- if (i != DOCKED_STACK_ID && getStack(i) != null) {
+ if (StackId.isResizeableByDockedStack(i) && getStack(i) != null) {
resizeStackLocked(i, null, preserveWindows, true);
}
}
@@ -3046,7 +3068,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
mWindowManager.getStackDockedModeBounds(HOME_STACK_ID, tempRect);
for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
- if (i != DOCKED_STACK_ID) {
+ if (StackId.isResizeableByDockedStack(i)) {
ActivityStack otherStack = getStack(i);
if (otherStack != null) {
resizeStackLocked(i, tempRect, PRESERVE_WINDOWS, true);
@@ -3190,7 +3212,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
* Restores a recent task to a stack
* @param task The recent task to be restored.
* @param stackId The stack to restore the task to (default launch stack will be used
- * if stackId is {@link android.app.ActivityManager#INVALID_STACK_ID}).
+ * if stackId is {@link android.app.ActivityManager.StackId#INVALID_STACK_ID}).
* @return true if the task has been restored successfully.
*/
private boolean restoreRecentTaskLocked(TaskRecord task, int stackId) {
@@ -3275,8 +3297,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
return;
}
- if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID
- || stackId == FULLSCREEN_WORKSPACE_STACK_ID) {
+ if (StackId.preserveWindowOnTaskMove(stackId)) {
// We are about to relaunch the activity because its configuration changed due to
// being maximized, i.e. size change. The activity will first remove the old window
// and then add a new one. This call will tell window manager about this, so it can
@@ -4664,7 +4685,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
@Override
public final int startActivity(Intent intent) {
mService.enforceNotIsolatedCaller("ActivityContainer.startActivity");
- final int userId = mService.handleIncomingUser(Binder.getCallingPid(),
+ final int userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), mCurrentUser, false,
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
@@ -4690,7 +4711,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
throw new IllegalArgumentException("Bad PendingIntent object");
}
- final int userId = mService.handleIncomingUser(Binder.getCallingPid(),
+ final int userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), mCurrentUser, false,
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 6ed880e0a2a5..8039072dccda 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -248,7 +248,7 @@ final class PendingIntentRecord extends IIntentSender.Stub {
boolean sendFinish = finishedReceiver != null;
int userId = key.userId;
if (userId == UserHandle.USER_CURRENT) {
- userId = owner.mUserController.getCurrentUserIdLocked();
+ userId = owner.mUserController.getCurrentOrTargetUserIdLocked();
}
switch (key.type) {
case ActivityManager.INTENT_SENDER_ACTIVITY:
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 08203c55b5d9..b77eec8adf0e 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -114,6 +114,7 @@ final class ProcessRecord {
boolean killed; // True once we know the process has been killed
boolean procStateChanged; // Keep track of whether we changed 'setAdj'.
boolean reportedInteraction;// Whether we have told usage stats about it being an interaction
+ long interactionEventTime; // The time we sent the last interaction event
long fgInteractionTime; // When we became foreground for interaction purposes
String waitingToKill; // Process is waiting to be killed when in the bg, and reason
IBinder forcingToForeground;// Token that is forcing this process to be foreground
@@ -297,6 +298,10 @@ final class ProcessRecord {
if (reportedInteraction || fgInteractionTime != 0) {
pw.print(prefix); pw.print("reportedInteraction=");
pw.print(reportedInteraction);
+ if (interactionEventTime != 0) {
+ pw.print(" time=");
+ TimeUtils.formatDuration(interactionEventTime, SystemClock.elapsedRealtime(), pw);
+ }
if (fgInteractionTime != 0) {
pw.print(" fgInteractionTime=");
TimeUtils.formatDuration(fgInteractionTime, SystemClock.elapsedRealtime(), pw);
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index edd16ef25780..862a9739fe05 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -108,7 +108,7 @@ class RecentTasks extends ArrayList<TaskRecord> {
final IPackageManager pm = AppGlobals.getPackageManager();
final int[] users = (userId == UserHandle.USER_ALL)
- ? mService.getUsersLocked() : new int[] { userId };
+ ? mService.mUserController.getUsers() : new int[] { userId };
for (int userIdx = 0; userIdx < users.length; userIdx++) {
final int user = users[userIdx];
recentsCount = size() - 1;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 120b40c73c13..5fd213f96c66 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -16,11 +16,9 @@
package com.android.server.am;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.HOME_STACK_ID;
-import static android.app.ActivityManager.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
@@ -35,6 +33,7 @@ import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskThumbnail;
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityOptions;
@@ -1193,14 +1192,14 @@ final class TaskRecord {
mFullscreen = bounds == null;
if (mFullscreen) {
- if (mBounds != null && stack.mPersistTaskBounds) {
+ if (mBounds != null && StackId.persistTaskBounds(stack.mStackId)) {
mLastNonFullscreenBounds = mBounds;
}
mBounds = null;
mOverrideConfig = Configuration.EMPTY;
} else {
mBounds = new Rect(bounds);
- if (stack == null || stack.mPersistTaskBounds) {
+ if (stack == null || StackId.persistTaskBounds(stack.mStackId)) {
mLastNonFullscreenBounds = mBounds;
}
@@ -1244,7 +1243,7 @@ final class TaskRecord {
|| stackId == HOME_STACK_ID
|| stackId == FULLSCREEN_WORKSPACE_STACK_ID) {
return (mResizeable && stack != null) ? stack.mBounds : null;
- } else if (!stack.mPersistTaskBounds) {
+ } else if (!StackId.persistTaskBounds(stackId)) {
return stack.mBounds;
}
return mLastNonFullscreenBounds;
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index ff74d836e1ba..408548925175 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -18,11 +18,17 @@ package com.android.server.am;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+
import static android.app.ActivityManager.USER_OP_IS_CURRENT;
import static android.app.ActivityManager.USER_OP_SUCCESS;
+import static android.os.Process.SYSTEM_UID;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityManagerService.ALLOW_FULL_ONLY;
+import static com.android.server.am.ActivityManagerService.ALLOW_NON_FULL;
+import static com.android.server.am.ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE;
+import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_COMPLETE_MSG;
import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MSG;
import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG;
@@ -31,8 +37,10 @@ import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_M
import android.app.ActivityManager;
import android.app.AppOpsManager;
+import android.app.Dialog;
import android.app.IStopUserCallback;
import android.app.IUserSwitchObserver;
+import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -40,11 +48,15 @@ import android.content.pm.UserInfo;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Debug;
import android.os.Handler;
+import android.os.IBinder;
import android.os.IRemoteCallback;
+import android.os.IUserManager;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;
@@ -58,7 +70,9 @@ import com.android.server.pm.UserManagerService;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Helper class for {@link ActivityManagerService} responsible for multi-user functionality.
@@ -76,9 +90,9 @@ final class UserController {
private final Handler mHandler;
// Holds the current foreground user's id
- int mCurrentUserId = 0;
+ private int mCurrentUserId = UserHandle.USER_SYSTEM;
// Holds the target user's id during a user switch
- int mTargetUserId = UserHandle.USER_NULL;
+ private int mTargetUserId = UserHandle.USER_NULL;
/**
* Which users have been started, so are allowed to run code.
@@ -96,7 +110,7 @@ final class UserController {
// If there are multiple profiles for the current user, their ids are here
// Currently only the primary user can have managed profiles
- int[] mCurrentProfileIds = new int[] {}; // Accessed by ActivityStack
+ private int[] mCurrentProfileIds = new int[] {};
/**
* Mapping from each known user ID to the profile group ID it is associated with.
@@ -106,7 +120,7 @@ final class UserController {
/**
* Registered observers of the user switching mechanics.
*/
- final RemoteCallbackList<IUserSwitchObserver> mUserSwitchObservers
+ private final RemoteCallbackList<IUserSwitchObserver> mUserSwitchObservers
= new RemoteCallbackList<>();
/**
@@ -114,6 +128,8 @@ final class UserController {
*/
Object mCurUserSwitchCallback;
+ private volatile UserManagerService mUserManager;
+
UserController(ActivityManagerService service) {
mService = service;
mHandler = mService.mHandler;
@@ -176,8 +192,7 @@ final class UserController {
mService.broadcastIntentLocked(null, null, intent,
null, null, 0, null, null,
new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
- AppOpsManager.OP_NONE, null, true, false, ActivityManagerService.MY_PID,
- Process.SYSTEM_UID, userId);
+ AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
}
}
}
@@ -272,16 +287,14 @@ final class UserController {
mService.mSystemServiceManager.stopUser(userId);
mService.broadcastIntentLocked(null, null, shutdownIntent,
null, shutdownReceiver, 0, null, null, null, AppOpsManager.OP_NONE,
- null, true, false, ActivityManagerService.MY_PID,
- android.os.Process.SYSTEM_UID, userId);
+ null, true, false, MY_PID, SYSTEM_UID, userId);
}
};
// Kick things off.
mService.broadcastIntentLocked(null, null, stoppingIntent,
null, stoppingReceiver, 0, null, null,
new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
- null, true, false, ActivityManagerService.MY_PID, Process.SYSTEM_UID,
- UserHandle.USER_ALL);
+ null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -338,8 +351,7 @@ final class UserController {
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
mService.broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, ActivityManagerService.MY_PID, Process.SYSTEM_UID,
- UserHandle.USER_ALL);
+ null, false, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
}
@@ -357,7 +369,7 @@ final class UserController {
|| oldUss.mState == UserState.STATE_SHUTDOWN) {
continue;
}
- UserInfo userInfo = getUserManagerLocked().getUserInfo(oldUserId);
+ UserInfo userInfo = getUserInfo(oldUserId);
if (userInfo.isGuest()) {
// This is a user to be stopped.
stopUserLocked(oldUserId, null);
@@ -369,7 +381,7 @@ final class UserController {
void startProfilesLocked() {
if (DEBUG_MU) Slog.i(TAG, "startProfilesLocked");
- List<UserInfo> profiles = getUserManagerLocked().getProfiles(
+ List<UserInfo> profiles = getUserManager().getProfiles(
mCurrentUserId, false /* enabledOnly */);
List<UserInfo> profilesToStart = new ArrayList<>(profiles.size());
for (UserInfo user : profiles) {
@@ -388,8 +400,13 @@ final class UserController {
}
}
- private UserManagerService getUserManagerLocked() {
- return mService.getUserManagerLocked();
+ private UserManagerService getUserManager() {
+ UserManagerService userManager = mUserManager;
+ if (userManager == null) {
+ IBinder b = ServiceManager.getService(Context.USER_SERVICE);
+ userManager = mUserManager = (UserManagerService) IUserManager.Stub.asInterface(b);
+ }
+ return userManager;
}
boolean startUser(final int userId, final boolean foreground) {
@@ -416,7 +433,7 @@ final class UserController {
mService.mStackSupervisor.setLockTaskModeLocked(null,
ActivityManager.LOCK_TASK_MODE_NONE, "startUser", false);
- final UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
+ final UserInfo userInfo = getUserInfo(userId);
if (userInfo == null) {
Slog.w(TAG, "No user info for user #" + userId);
return false;
@@ -507,8 +524,7 @@ final class UserController {
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
mService.broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, ActivityManagerService.MY_PID, Process.SYSTEM_UID,
- userId);
+ null, false, false, MY_PID, SYSTEM_UID, userId);
}
if ((userInfo.flags&UserInfo.FLAG_INITIALIZED) == 0) {
@@ -523,11 +539,10 @@ final class UserController {
onUserInitialized(uss, foreground, oldUserId, userId);
}
}, 0, null, null, null, AppOpsManager.OP_NONE,
- null, true, false, ActivityManagerService.MY_PID,
- Process.SYSTEM_UID, userId);
+ null, true, false, MY_PID, SYSTEM_UID, userId);
uss.initializing = true;
} else {
- getUserManagerLocked().makeInitialized(userInfo.id);
+ getUserManager().makeInitialized(userInfo.id);
}
}
@@ -551,9 +566,8 @@ final class UserController {
int sendingUser) throws RemoteException {
}
}, 0, null, null,
- new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
- null, true, false, ActivityManagerService.MY_PID, Process.SYSTEM_UID,
- UserHandle.USER_ALL);
+ new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
+ null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
}
}
} finally {
@@ -563,6 +577,22 @@ final class UserController {
return true;
}
+ /**
+ * Start user, if its not already running, and bring it to foreground.
+ */
+ boolean startUserInForeground(final int userId, Dialog dlg) {
+ boolean result = startUser(userId, /* foreground */ true);
+ dlg.dismiss();
+ return result;
+ }
+
+ void showUserSwitchDialog(int userId, String userName) {
+ // The dialog will show and then initiate the user switch by calling startUserInForeground
+ Dialog d = new UserSwitchingDialog(mService, mService.mContext, userId, userName,
+ true /* above system */);
+ d.show();
+ }
+
void dispatchForegroundProfileChanged(int userId) {
final int observerCount = mUserSwitchObservers.beginBroadcast();
for (int i = 0; i < observerCount; i++) {
@@ -657,7 +687,7 @@ final class UserController {
synchronized (mService) {
if (clearInitializing) {
uss.initializing = false;
- getUserManagerLocked().makeInitialized(uss.mHandle.getIdentifier());
+ getUserManager().makeInitialized(uss.mHandle.getIdentifier());
}
if (clearSwitching) {
uss.switching = false;
@@ -683,8 +713,143 @@ final class UserController {
mService.mStackSupervisor.resumeTopActivitiesLocked();
}
EventLogTags.writeAmSwitchUser(newUserId);
- getUserManagerLocked().onUserForeground(newUserId);
- mService.sendUserSwitchBroadcastsLocked(oldUserId, newUserId);
+ getUserManager().onUserForeground(newUserId);
+ sendUserSwitchBroadcastsLocked(oldUserId, newUserId);
+ }
+
+ void sendUserSwitchBroadcastsLocked(int oldUserId, int newUserId) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ Intent intent;
+ if (oldUserId >= 0) {
+ // Send USER_BACKGROUND broadcast to all profiles of the outgoing user
+ List<UserInfo> profiles = getUserManager().getProfiles(oldUserId, false);
+ int count = profiles.size();
+ for (int i = 0; i < count; i++) {
+ int profileUserId = profiles.get(i).id;
+ intent = new Intent(Intent.ACTION_USER_BACKGROUND);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
+ mService.broadcastIntentLocked(null, null, intent,
+ null, null, 0, null, null, null, AppOpsManager.OP_NONE,
+ null, false, false, MY_PID, SYSTEM_UID, profileUserId);
+ }
+ }
+ if (newUserId >= 0) {
+ // Send USER_FOREGROUND broadcast to all profiles of the incoming user
+ List<UserInfo> profiles = getUserManager().getProfiles(newUserId, false);
+ int count = profiles.size();
+ for (int i = 0; i < count; i++) {
+ int profileUserId = profiles.get(i).id;
+ intent = new Intent(Intent.ACTION_USER_FOREGROUND);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
+ mService.broadcastIntentLocked(null, null, intent,
+ null, null, 0, null, null, null, AppOpsManager.OP_NONE,
+ null, false, false, MY_PID, SYSTEM_UID, profileUserId);
+ }
+ intent = new Intent(Intent.ACTION_USER_SWITCHED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId);
+ mService.broadcastIntentLocked(null, null, intent,
+ null, null, 0, null, null,
+ new String[] {android.Manifest.permission.MANAGE_USERS},
+ AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+ UserHandle.USER_ALL);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+
+ int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
+ int allowMode, String name, String callerPackage) {
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ if (callingUserId == userId) {
+ return userId;
+ }
+
+ // Note that we may be accessing mCurrentUserId outside of a lock...
+ // shouldn't be a big deal, if this is being called outside
+ // of a locked context there is intrinsically a race with
+ // the value the caller will receive and someone else changing it.
+ // We assume that USER_CURRENT_OR_SELF will use the current user; later
+ // we will switch to the calling user if access to the current user fails.
+ int targetUserId = unsafeConvertIncomingUserLocked(userId);
+
+ if (callingUid != 0 && callingUid != SYSTEM_UID) {
+ final boolean allow;
+ if (mService.checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid,
+ callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
+ // If the caller has this permission, they always pass go. And collect $200.
+ allow = true;
+ } else if (allowMode == ALLOW_FULL_ONLY) {
+ // We require full access, sucks to be you.
+ allow = false;
+ } else if (mService.checkComponentPermission(INTERACT_ACROSS_USERS, callingPid,
+ callingUid, -1, true) != PackageManager.PERMISSION_GRANTED) {
+ // If the caller does not have either permission, they are always doomed.
+ allow = false;
+ } else if (allowMode == ALLOW_NON_FULL) {
+ // We are blanket allowing non-full access, you lucky caller!
+ allow = true;
+ } else if (allowMode == ALLOW_NON_FULL_IN_PROFILE) {
+ // We may or may not allow this depending on whether the two users are
+ // in the same profile.
+ allow = isSameProfileGroup(callingUserId, targetUserId);
+ } else {
+ throw new IllegalArgumentException("Unknown mode: " + allowMode);
+ }
+ if (!allow) {
+ if (userId == UserHandle.USER_CURRENT_OR_SELF) {
+ // In this case, they would like to just execute as their
+ // owner user instead of failing.
+ targetUserId = callingUserId;
+ } else {
+ StringBuilder builder = new StringBuilder(128);
+ builder.append("Permission Denial: ");
+ builder.append(name);
+ if (callerPackage != null) {
+ builder.append(" from ");
+ builder.append(callerPackage);
+ }
+ builder.append(" asks to run as user ");
+ builder.append(userId);
+ builder.append(" but is calling from user ");
+ builder.append(UserHandle.getUserId(callingUid));
+ builder.append("; this requires ");
+ builder.append(INTERACT_ACROSS_USERS_FULL);
+ if (allowMode != ALLOW_FULL_ONLY) {
+ builder.append(" or ");
+ builder.append(INTERACT_ACROSS_USERS);
+ }
+ String msg = builder.toString();
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ }
+ }
+ if (!allowAll && targetUserId < 0) {
+ throw new IllegalArgumentException(
+ "Call does not support special user #" + targetUserId);
+ }
+ // Check shell permission
+ if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_SYSTEM) {
+ if (hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId)) {
+ throw new SecurityException("Shell does not have permission to access user "
+ + targetUserId + "\n " + Debug.getCallers(3));
+ }
+ }
+ return targetUserId;
+ }
+
+ int unsafeConvertIncomingUserLocked(int userId) {
+ return (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF)
+ ? getCurrentUserIdLocked(): userId;
}
void registerUserSwitchObserver(IUserSwitchObserver observer) {
@@ -705,7 +870,7 @@ final class UserController {
mUserSwitchObservers.unregister(observer);
}
- UserState getStartedUserState(int userId) {
+ UserState getStartedUserStateLocked(int userId) {
return mStartedUsers.get(userId);
}
@@ -746,9 +911,8 @@ final class UserController {
intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
mService.broadcastIntentLocked(null, null, intent, null,
resultTo, 0, null, null,
- new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
- AppOpsManager.OP_NONE, null, true, false,
- ActivityManagerService.MY_PID, Process.SYSTEM_UID, userId);
+ new String[] {android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
+ AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
}
}
}
@@ -759,7 +923,7 @@ final class UserController {
* background.
*/
void updateCurrentProfileIdsLocked() {
- final List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId,
+ final List<UserInfo> profiles = getUserManager().getProfiles(mCurrentUserId,
false /* enabledOnly */);
int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
for (int i = 0; i < currentProfileIds.length; i++) {
@@ -769,7 +933,7 @@ final class UserController {
synchronized (mUserProfileGroupIdsSelfLocked) {
mUserProfileGroupIdsSelfLocked.clear();
- final List<UserInfo> users = getUserManagerLocked().getUsers(false);
+ final List<UserInfo> users = getUserManager().getUsers(false);
for (int i = 0; i < users.size(); i++) {
UserInfo user = users.get(i);
if (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
@@ -783,6 +947,18 @@ final class UserController {
return mStartedUserArray;
}
+ boolean isUserRunningLocked(int userId, boolean orStopped) {
+ UserState state = getStartedUserStateLocked(userId);
+ if (state == null) {
+ return false;
+ }
+ if (orStopped) {
+ return true;
+ }
+ return state.mState != UserState.STATE_STOPPING
+ && state.mState != UserState.STATE_SHUTDOWN;
+ }
+
UserInfo getCurrentUser() {
if ((mService.checkCallingPermission(INTERACT_ACROSS_USERS)
!= PackageManager.PERMISSION_GRANTED) && (
@@ -802,13 +978,52 @@ final class UserController {
UserInfo getCurrentUserLocked() {
int userId = mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId;
- return getUserManagerLocked().getUserInfo(userId);
+ return getUserInfo(userId);
}
- int getCurrentUserIdLocked() {
+ int getCurrentOrTargetUserIdLocked() {
return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId;
}
+ int getCurrentUserIdLocked() {
+ return mCurrentUserId;
+ }
+
+ int setTargetUserIdLocked(int targetUserId) {
+ return mTargetUserId = targetUserId;
+ }
+
+ int[] getUsers() {
+ UserManagerService ums = getUserManager();
+ return ums != null ? ums.getUserIds() : new int[] { 0 };
+ }
+
+ UserInfo getUserInfo(int userId) {
+ return getUserManager().getUserInfo(userId);
+ }
+
+ int[] getUserIds() {
+ return getUserManager().getUserIds();
+ }
+
+ boolean exists(int userId) {
+ return getUserManager().exists(userId);
+ }
+
+ boolean hasUserRestriction(String restriction, int userId) {
+ return getUserManager().hasUserRestriction(restriction, userId);
+ }
+
+ Set<Integer> getProfileIds(int userId) {
+ Set<Integer> userIds = new HashSet<>();
+ final List<UserInfo> profiles = getUserManager().getProfiles(userId,
+ false /* enabledOnly */);
+ for (UserInfo user : profiles) {
+ userIds.add(user.id);
+ }
+ return userIds;
+ }
+
boolean isSameProfileGroup(int callingUserId, int targetUserId) {
synchronized (mUserProfileGroupIdsSelfLocked) {
int callingProfile = mUserProfileGroupIdsSelfLocked.get(callingUserId,
@@ -824,6 +1039,10 @@ final class UserController {
return ArrayUtils.contains(mCurrentProfileIds, userId);
}
+ int[] getCurrentProfileIdsLocked() {
+ return mCurrentProfileIds;
+ }
+
void dump(PrintWriter pw, boolean dumpAll) {
pw.println(" mStartedUsers:");
for (int i = 0; i < mStartedUsers.size(); i++) {
@@ -858,5 +1077,4 @@ final class UserController {
}
}
}
-
}
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index 5a66f4a74d99..28b4096c8e16 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -97,7 +97,7 @@ final class UserSwitchingDialog extends AlertDialog
void startUser() {
synchronized (this) {
if (!mStartedUser) {
- mService.startUserInForeground(mUserId, this);
+ mService.mUserController.startUserInForeground(mUserId, this);
mStartedUser = true;
final View decorView = getWindow().getDecorView();
if (decorView != null) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 66e731a29dde..d89f47cc622d 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1756,7 +1756,8 @@ public class AudioService extends IAudioService.Stub {
if (uid == android.os.Process.SYSTEM_UID) {
uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
}
- if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
+ // If OP_AUDIO_MASTER_VOLUME is set, disallow unmuting.
+ if (!mute && mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
!= AppOpsManager.MODE_ALLOWED) {
return;
}
@@ -1848,7 +1849,8 @@ public class AudioService extends IAudioService.Stub {
if (uid == android.os.Process.SYSTEM_UID) {
uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
}
- if (mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
+ // If OP_MUTE_MICROPHONE is set, disallow unmuting.
+ if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
!= AppOpsManager.MODE_ALLOWED) {
return;
}
diff --git a/services/core/java/com/android/server/content/AppIdleMonitor.java b/services/core/java/com/android/server/content/AppIdleMonitor.java
index fe5c2da4c6d1..2d768d8b2aae 100644
--- a/services/core/java/com/android/server/content/AppIdleMonitor.java
+++ b/services/core/java/com/android/server/content/AppIdleMonitor.java
@@ -50,8 +50,8 @@ class AppIdleMonitor extends AppIdleStateChangeListener {
}
}
- boolean isAppIdle(String packageName, int userId) {
- return !mAppIdleParoleOn && mUsageStats.isAppIdle(packageName, userId);
+ boolean isAppIdle(String packageName, int uidForAppId, int userId) {
+ return !mAppIdleParoleOn && mUsageStats.isAppIdle(packageName, uidForAppId, userId);
}
@Override
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 15e539314a6e..82e0eafe6bea 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -2625,9 +2625,18 @@ public class SyncManager {
continue;
}
String packageName = getPackageName(op.target);
+ ApplicationInfo ai = null;
+ if (packageName != null) {
+ try {
+ ai = mContext.getPackageManager().getApplicationInfo(packageName,
+ PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_DISABLED_COMPONENTS);
+ } catch (NameNotFoundException e) {
+ }
+ }
// If app is considered idle, then skip for now and backoff
- if (packageName != null
- && mAppIdleMonitor.isAppIdle(packageName, op.target.userId)) {
+ if (ai != null
+ && mAppIdleMonitor.isAppIdle(packageName, ai.uid, op.target.userId)) {
increaseBackoffSetting(op);
op.appIdle = true;
if (isLoggable) {
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 02d4f4034244..6fc02f6eba16 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -67,7 +67,7 @@ public class AppIdleController extends StateController {
mTrackedTasks.add(jobStatus);
String packageName = jobStatus.job.getService().getPackageName();
final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
- jobStatus.getUserId());
+ jobStatus.uId, jobStatus.getUserId());
if (DEBUG) {
Slog.d(LOG_TAG, "Start tracking, setting idle state of "
+ packageName + " to " + appIdle);
@@ -108,7 +108,7 @@ public class AppIdleController extends StateController {
for (JobStatus task : mTrackedTasks) {
String packageName = task.job.getService().getPackageName();
final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName,
- task.getUserId());
+ task.uId, task.getUserId());
if (DEBUG) {
Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 17ae6dce50d9..41aea040cdc5 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -2227,7 +2227,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int userId = UserHandle.getUserId(uid);
for (String packageName : packages) {
- if (!mUsageStats.isAppIdle(packageName, userId)) {
+ if (!mUsageStats.isAppIdle(packageName, uid, userId)) {
return false;
}
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index d8676167497f..150c84932aca 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -53,6 +53,14 @@ public final class Installer extends SystemService {
mInstaller = new InstallerConnection();
}
+ /**
+ * Yell loudly if someone tries making future calls while holding a lock on
+ * the given object.
+ */
+ public void setWarnIfHeld(Object warnIfHeld) {
+ mInstaller.setWarnIfHeld(warnIfHeld);
+ }
+
@Override
public void onStart() {
Slog.i(TAG, "Waiting for installd to be ready.");
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 22bedc3c2850..08f9bd5be167 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -162,6 +162,7 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.SELinux;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -2390,6 +2391,11 @@ public class PackageManagerService extends IPackageManager.Stub {
// tidy.
Runtime.getRuntime().gc();
+ // The initial scanning above does many calls into installd while
+ // holding the mPackages lock, but we're mostly interested in yelling
+ // once we have a booted system.
+ mInstaller.setWarnIfHeld(mPackages);
+
// Expose private service for system components to use.
LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());
}
@@ -15086,6 +15092,13 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out,
+ FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+ (new PackageManagerShellCommand(this)).exec(
+ this, in, out, err, args, resultReceiver);
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -16545,7 +16558,7 @@ public class PackageManagerService extends IPackageManager.Stub {
*/
private void removeUnusedPackagesLILPw(UserManagerService userManager, final int userHandle) {
final boolean DEBUG_CLEAN_APKS = false;
- int [] users = userManager.getUserIdsLPr();
+ int [] users = userManager.getUserIds();
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
new file mode 100644
index 000000000000..c259ac2b2fec
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -0,0 +1,529 @@
+package com.android.server.pm;
+
+import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+import android.content.res.AssetManager;
+import android.content.res.Resources;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.WeakHashMap;
+
+class PackageManagerShellCommand extends ShellCommand {
+ final IPackageManager mInterface;
+ final private WeakHashMap<String, Resources> mResourceCache =
+ new WeakHashMap<String, Resources>();
+
+ PackageManagerShellCommand(PackageManagerService service) {
+ mInterface = service;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ switch(cmd) {
+ case "list":
+ return runList();
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ } catch (RemoteException e) {
+ pw.println("Remote exception: " + e);
+ }
+ return -1;
+ }
+
+ private int runList() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final String type = getNextArg();
+ if (type == null) {
+ pw.println("Error: didn't specify type of data to list");
+ return -1;
+ }
+ switch(type) {
+ case "features":
+ return runListFeatures();
+ case "instrumentation":
+ return runListInstrumentation();
+ case "libraries":
+ return runListLibraries();
+ case "package":
+ case "packages":
+ return runListPackages(false /*showSourceDir*/);
+ case "permission-groups":
+ return runListPermissionGroups();
+ case "permissions":
+ return runListPermissions();
+ }
+ pw.println("Error: unknown list type '" + type + "'");
+ return -1;
+ }
+
+ private int runListFeatures() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final List<FeatureInfo> list = new ArrayList<FeatureInfo>();
+ final FeatureInfo[] rawList = mInterface.getSystemAvailableFeatures();
+ for (int i=0; i<rawList.length; i++) {
+ list.add(rawList[i]);
+ }
+
+ // sort by name
+ Collections.sort(list, new Comparator<FeatureInfo>() {
+ public int compare(FeatureInfo o1, FeatureInfo o2) {
+ if (o1.name == o2.name) return 0;
+ if (o1.name == null) return -1;
+ if (o2.name == null) return 1;
+ return o1.name.compareTo(o2.name);
+ }
+ });
+
+ final int count = (list != null) ? list.size() : 0;
+ for (int p = 0; p < count; p++) {
+ FeatureInfo fi = list.get(p);
+ pw.print("feature:");
+ if (fi.name != null) pw.println(fi.name);
+ else pw.println("reqGlEsVersion=0x"
+ + Integer.toHexString(fi.reqGlEsVersion));
+ }
+ return 0;
+ }
+
+ private int runListInstrumentation() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ boolean showSourceDir = false;
+ String targetPackage = null;
+
+ try {
+ String opt;
+ while ((opt = getNextArg()) != null) {
+ switch (opt) {
+ case "-f":
+ showSourceDir = true;
+ break;
+ default:
+ if (opt.charAt(0) != '-') {
+ targetPackage = opt;
+ } else {
+ pw.println("Error: Unknown option: " + opt);
+ return -1;
+ }
+ break;
+ }
+ }
+ } catch (RuntimeException ex) {
+ pw.println("Error: " + ex.toString());
+ return -1;
+ }
+
+ final List<InstrumentationInfo> list =
+ mInterface.queryInstrumentation(targetPackage, 0 /*flags*/);
+
+ // sort by target package
+ Collections.sort(list, new Comparator<InstrumentationInfo>() {
+ public int compare(InstrumentationInfo o1, InstrumentationInfo o2) {
+ return o1.targetPackage.compareTo(o2.targetPackage);
+ }
+ });
+
+ final int count = (list != null) ? list.size() : 0;
+ for (int p = 0; p < count; p++) {
+ final InstrumentationInfo ii = list.get(p);
+ pw.print("instrumentation:");
+ if (showSourceDir) {
+ pw.print(ii.sourceDir);
+ pw.print("=");
+ }
+ final ComponentName cn = new ComponentName(ii.packageName, ii.name);
+ pw.print(cn.flattenToShortString());
+ pw.print(" (target=");
+ pw.print(ii.targetPackage);
+ pw.println(")");
+ }
+ return 0;
+ }
+
+ private int runListLibraries() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final List<String> list = new ArrayList<String>();
+ final String[] rawList = mInterface.getSystemSharedLibraryNames();
+ for (int i = 0; i < rawList.length; i++) {
+ list.add(rawList[i]);
+ }
+
+ // sort by name
+ Collections.sort(list, new Comparator<String>() {
+ public int compare(String o1, String o2) {
+ if (o1 == o2) return 0;
+ if (o1 == null) return -1;
+ if (o2 == null) return 1;
+ return o1.compareTo(o2);
+ }
+ });
+
+ final int count = (list != null) ? list.size() : 0;
+ for (int p = 0; p < count; p++) {
+ String lib = list.get(p);
+ pw.print("library:");
+ pw.println(lib);
+ }
+ return 0;
+ }
+
+ private int runListPackages(boolean showSourceDir) throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ int getFlags = 0;
+ boolean listDisabled = false, listEnabled = false;
+ boolean listSystem = false, listThirdParty = false;
+ boolean listInstaller = false;
+ int userId = UserHandle.USER_SYSTEM;
+ try {
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-d":
+ listDisabled = true;
+ break;
+ case "-e":
+ listEnabled = true;
+ break;
+ case "-f":
+ showSourceDir = true;
+ break;
+ case "-i":
+ listInstaller = true;
+ break;
+ case "-l":
+ // old compat
+ break;
+ case "-lf":
+ showSourceDir = true;
+ break;
+ case "-s":
+ listSystem = true;
+ break;
+ case "-u":
+ getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
+ break;
+ case "-3":
+ listThirdParty = true;
+ break;
+ case "--user":
+ userId = Integer.parseInt(getNextArg());
+ break;
+ default:
+ pw.println("Error: Unknown option: " + opt);
+ return -1;
+ }
+ }
+ } catch (RuntimeException ex) {
+ pw.println("Error: " + ex.toString());
+ return -1;
+ }
+
+ final String filter = getNextArg();
+
+ @SuppressWarnings("unchecked")
+ final ParceledListSlice<PackageInfo> slice =
+ mInterface.getInstalledPackages(getFlags, userId);
+ final List<PackageInfo> packages = slice.getList();
+
+ final int count = packages.size();
+ for (int p = 0; p < count; p++) {
+ final PackageInfo info = packages.get(p);
+ if (filter != null && !info.packageName.contains(filter)) {
+ continue;
+ }
+ final boolean isSystem =
+ (info.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0;
+ if ((!listDisabled || !info.applicationInfo.enabled) &&
+ (!listEnabled || info.applicationInfo.enabled) &&
+ (!listSystem || isSystem) &&
+ (!listThirdParty || !isSystem)) {
+ pw.print("package:");
+ if (showSourceDir) {
+ pw.print(info.applicationInfo.sourceDir);
+ pw.print("=");
+ }
+ pw.print(info.packageName);
+ if (listInstaller) {
+ pw.print(" installer=");
+ pw.print(mInterface.getInstallerPackageName(info.packageName));
+ }
+ pw.println();
+ }
+ }
+ return 0;
+ }
+
+ private int runListPermissionGroups() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final List<PermissionGroupInfo> pgs = mInterface.getAllPermissionGroups(0);
+
+ final int count = pgs.size();
+ for (int p = 0; p < count ; p++) {
+ final PermissionGroupInfo pgi = pgs.get(p);
+ pw.print("permission group:");
+ pw.println(pgi.name);
+ }
+ return 0;
+ }
+
+ private int runListPermissions() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ boolean labels = false;
+ boolean groups = false;
+ boolean userOnly = false;
+ boolean summary = false;
+ boolean dangerousOnly = false;
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-d":
+ dangerousOnly = true;
+ break;
+ case "-f":
+ labels = true;
+ break;
+ case "-g":
+ groups = true;
+ break;
+ case "-s":
+ groups = true;
+ labels = true;
+ summary = true;
+ break;
+ case "-u":
+ userOnly = true;
+ break;
+ default:
+ pw.println("Error: Unknown option: " + opt);
+ return 1;
+ }
+ }
+
+ final ArrayList<String> groupList = new ArrayList<String>();
+ if (groups) {
+ final List<PermissionGroupInfo> infos =
+ mInterface.getAllPermissionGroups(0 /*flags*/);
+ final int count = infos.size();
+ for (int i = 0; i < count; i++) {
+ groupList.add(infos.get(i).name);
+ }
+ groupList.add(null);
+ } else {
+ final String grp = getNextArg();
+ groupList.add(grp);
+ }
+
+ if (dangerousOnly) {
+ pw.println("Dangerous Permissions:");
+ pw.println("");
+ doListPermissions(groupList, groups, labels, summary,
+ PermissionInfo.PROTECTION_DANGEROUS,
+ PermissionInfo.PROTECTION_DANGEROUS);
+ if (userOnly) {
+ pw.println("Normal Permissions:");
+ pw.println("");
+ doListPermissions(groupList, groups, labels, summary,
+ PermissionInfo.PROTECTION_NORMAL,
+ PermissionInfo.PROTECTION_NORMAL);
+ }
+ } else if (userOnly) {
+ pw.println("Dangerous and Normal Permissions:");
+ pw.println("");
+ doListPermissions(groupList, groups, labels, summary,
+ PermissionInfo.PROTECTION_NORMAL,
+ PermissionInfo.PROTECTION_DANGEROUS);
+ } else {
+ pw.println("All Permissions:");
+ pw.println("");
+ doListPermissions(groupList, groups, labels, summary,
+ -10000, 10000);
+ }
+ return 0;
+ }
+
+ private void doListPermissions(ArrayList<String> groupList, boolean groups, boolean labels,
+ boolean summary, int startProtectionLevel, int endProtectionLevel)
+ throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final int groupCount = groupList.size();
+ for (int i = 0; i < groupCount; i++) {
+ String groupName = groupList.get(i);
+ String prefix = "";
+ if (groups) {
+ if (i > 0) {
+ pw.println("");
+ }
+ if (groupName != null) {
+ PermissionGroupInfo pgi =
+ mInterface.getPermissionGroupInfo(groupName, 0 /*flags*/);
+ if (summary) {
+ Resources res = getResources(pgi);
+ if (res != null) {
+ pw.print(loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel) + ": ");
+ } else {
+ pw.print(pgi.name + ": ");
+
+ }
+ } else {
+ pw.println((labels ? "+ " : "") + "group:" + pgi.name);
+ if (labels) {
+ pw.println(" package:" + pgi.packageName);
+ Resources res = getResources(pgi);
+ if (res != null) {
+ pw.println(" label:"
+ + loadText(pgi, pgi.labelRes, pgi.nonLocalizedLabel));
+ pw.println(" description:"
+ + loadText(pgi, pgi.descriptionRes,
+ pgi.nonLocalizedDescription));
+ }
+ }
+ }
+ } else {
+ pw.println(((labels && !summary) ? "+ " : "") + "ungrouped:");
+ }
+ prefix = " ";
+ }
+ List<PermissionInfo> ps =
+ mInterface.queryPermissionsByGroup(groupList.get(i), 0 /*flags*/);
+ final int count = ps.size();
+ boolean first = true;
+ for (int p = 0 ; p < count ; p++) {
+ PermissionInfo pi = ps.get(p);
+ if (groups && groupName == null && pi.group != null) {
+ continue;
+ }
+ final int base = pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
+ if (base < startProtectionLevel
+ || base > endProtectionLevel) {
+ continue;
+ }
+ if (summary) {
+ if (first) {
+ first = false;
+ } else {
+ pw.print(", ");
+ }
+ Resources res = getResources(pi);
+ if (res != null) {
+ pw.print(loadText(pi, pi.labelRes,
+ pi.nonLocalizedLabel));
+ } else {
+ pw.print(pi.name);
+ }
+ } else {
+ pw.println(prefix + (labels ? "+ " : "")
+ + "permission:" + pi.name);
+ if (labels) {
+ pw.println(prefix + " package:" + pi.packageName);
+ Resources res = getResources(pi);
+ if (res != null) {
+ pw.println(prefix + " label:"
+ + loadText(pi, pi.labelRes,
+ pi.nonLocalizedLabel));
+ pw.println(prefix + " description:"
+ + loadText(pi, pi.descriptionRes,
+ pi.nonLocalizedDescription));
+ }
+ pw.println(prefix + " protectionLevel:"
+ + PermissionInfo.protectionToString(pi.protectionLevel));
+ }
+ }
+ }
+
+ if (summary) {
+ pw.println("");
+ }
+ }
+ }
+
+ private String loadText(PackageItemInfo pii, int res, CharSequence nonLocalized)
+ throws RemoteException {
+ if (nonLocalized != null) {
+ return nonLocalized.toString();
+ }
+ if (res != 0) {
+ Resources r = getResources(pii);
+ if (r != null) {
+ try {
+ return r.getString(res);
+ } catch (Resources.NotFoundException e) {
+ }
+ }
+ }
+ return null;
+ }
+
+ private Resources getResources(PackageItemInfo pii) throws RemoteException {
+ Resources res = mResourceCache.get(pii.packageName);
+ if (res != null) return res;
+
+ ApplicationInfo ai = mInterface.getApplicationInfo(pii.packageName, 0, 0);
+ AssetManager am = new AssetManager();
+ am.addAssetPath(ai.publicSourceDir);
+ res = new Resources(am, null, null);
+ mResourceCache.put(pii.packageName, res);
+ return res;
+ }
+
+ @Override
+ public void onHelp() {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println("Package manager (package) commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println("");
+ pw.println(" list features");
+ pw.println(" Prints all features of the system.");
+ pw.println(" list instrumentation [-f] [TARGET-PACKAGE]");
+ pw.println(" Prints all test packages; optionally only those targetting TARGET-PACKAGE");
+ pw.println(" Options:");
+ pw.println(" -f: dump the name of the .apk file containing the test package");
+ pw.println(" list libraries");
+ pw.println(" Prints all system libraries.");
+ pw.println(" list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
+ pw.println(" Prints all packages; optionally only those whose name contains");
+ pw.println(" the text in FILTER.");
+ pw.println(" Options:");
+ pw.println(" -f: see their associated file");
+ pw.println(" -d: filter to only show disbled packages");
+ pw.println(" -e: filter to only show enabled packages");
+ pw.println(" -s: filter to only show system packages");
+ pw.println(" -3: filter to only show third party packages");
+ pw.println(" -i: see the installer for the packages");
+ pw.println(" -u: also include uninstalled packages");
+ pw.println(" list permission-groups");
+ pw.println(" Prints all known permission groups.");
+ pw.println(" list permissions [-g] [-f] [-d] [-u] [GROUP]");
+ pw.println(" Prints all known permissions; optionally only those in GROUP.");
+ pw.println(" Options:");
+ pw.println(" -g: organize by group");
+ pw.println(" -f: print all information");
+ pw.println(" -s: short summary");
+ pw.println(" -d: only list dangerous permissions");
+ pw.println(" -u: list only the permissions users will see");
+ pw.println("");
+ }
+}
+
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 5d0e83d0fa15..c41d49359a66 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -22,6 +22,7 @@ import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
import android.app.IStopUserCallback;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
@@ -44,7 +45,9 @@ import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.ServiceManager;
+import android.os.ShellCommand;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -92,13 +95,15 @@ import libcore.io.IoUtils;
* Service for {@link UserManager}.
*
* Method naming convention:
- * - Methods suffixed with "Locked" should be called within the {@code this} lock.
- * - Methods suffixed with "RL" should be called within the {@link #mRestrictionsLock} lock.
+ * <ul>
+ * <li> Methods suffixed with "LILP" should be called within {@link #mInstallLock} and
+ * {@link #mPackagesLock} locks obtained in the respective order.
+ * <li> Methods suffixed with "LR" should be called within the {@link #mRestrictionsLock} lock.
+ * <li> Methods suffixed with "LU" should be called within the {@link #mUsersLock} lock.
+ * </ul>
*/
public class UserManagerService extends IUserManager.Stub {
-
private static final String LOG_TAG = "UserManagerService";
-
private static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
private static final String TAG_NAME = "name";
@@ -160,15 +165,17 @@ public class UserManagerService extends IUserManager.Stub {
private final PackageManagerService mPm;
private final Object mInstallLock;
private final Object mPackagesLock;
+ // Short-term lock for internal state, when interaction/sync with PM is not required
+ private final Object mUsersLock = new Object();
+ private final Object mRestrictionsLock = new Object();
private final Handler mHandler;
private final File mUsersDir;
private final File mUserListFile;
- private final SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
-
- private final Object mRestrictionsLock = new Object();
+ @GuardedBy("mUsersLock")
+ private final SparseArray<UserInfo> mUsers = new SparseArray<>();
/**
* User restrictions set via UserManager. This doesn't include restrictions set by
@@ -179,7 +186,7 @@ public class UserManagerService extends IUserManager.Stub {
* maybe shared between {@link #mBaseUserRestrictions} and
* {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
* (Otherwise we won't be able to detect what restrictions have changed in
- * {@link #updateUserRestrictionsInternalRL).
+ * {@link #updateUserRestrictionsInternalLR}.
*/
@GuardedBy("mRestrictionsLock")
private final SparseArray<Bundle> mBaseUserRestrictions = new SparseArray<>();
@@ -194,20 +201,29 @@ public class UserManagerService extends IUserManager.Stub {
* maybe shared between {@link #mBaseUserRestrictions} and
* {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
* (Otherwise we won't be able to detect what restrictions have changed in
- * {@link #updateUserRestrictionsInternalRL).
+ * {@link #updateUserRestrictionsInternalLR}.
*/
@GuardedBy("mRestrictionsLock")
private final SparseArray<Bundle> mCachedEffectiveUserRestrictions = new SparseArray<>();
+ /**
+ * User restrictions that have already been applied in {@link #applyUserRestrictionsLR}. We
+ * use it to detect restrictions that have changed since the last
+ * {@link #applyUserRestrictionsLR} call.
+ */
+ @GuardedBy("mRestrictionsLock")
+ private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>();
+
private final Bundle mGuestRestrictions = new Bundle();
/**
* Set of user IDs being actively removed. Removed IDs linger in this set
* for several seconds to work around a VFS caching issue.
*/
- // @GuardedBy("mPackagesLock")
+ @GuardedBy("mUsersLock")
private final SparseBooleanArray mRemovingUserIds = new SparseBooleanArray();
+ @GuardedBy("mUsersLock")
private int[] mUserIds;
private int mNextSerialNumber;
private int mUserVersion = 0;
@@ -267,7 +283,7 @@ public class UserManagerService extends IUserManager.Stub {
-1, -1);
mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
initDefaultGuestRestrictions();
- readUserListLocked();
+ readUserListLILP();
sInstance = this;
}
}
@@ -278,21 +294,23 @@ public class UserManagerService extends IUserManager.Stub {
void systemReady() {
synchronized (mInstallLock) {
synchronized (mPackagesLock) {
- // Prune out any partially created/partially removed users.
- ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
- final int userSize = mUsers.size();
- for (int i = 0; i < userSize; i++) {
- UserInfo ui = mUsers.valueAt(i);
- if ((ui.partial || ui.guestToRemove) && i != 0) {
- partials.add(ui);
+ synchronized (mUsersLock) {
+ // Prune out any partially created/partially removed users.
+ ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
+ final int userSize = mUsers.size();
+ for (int i = 0; i < userSize; i++) {
+ UserInfo ui = mUsers.valueAt(i);
+ if ((ui.partial || ui.guestToRemove) && i != 0) {
+ partials.add(ui);
+ }
+ }
+ final int partialsSize = partials.size();
+ for (int i = 0; i < partialsSize; i++) {
+ UserInfo ui = partials.get(i);
+ Slog.w(LOG_TAG, "Removing partially created user " + ui.id
+ + " (name=" + ui.name + ")");
+ removeUserStateLILP(ui.id);
}
- }
- final int partialsSize = partials.size();
- for (int i = 0; i < partialsSize; i++) {
- UserInfo ui = partials.get(i);
- Slog.w(LOG_TAG, "Removing partially created user " + ui.id
- + " (name=" + ui.name + ")");
- removeUserStateLocked(ui.id);
}
}
}
@@ -312,7 +330,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public UserInfo getPrimaryUser() {
checkManageUsersPermission("query users");
- synchronized (mPackagesLock) {
+ synchronized (mUsersLock) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
UserInfo ui = mUsers.valueAt(i);
@@ -327,7 +345,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
checkManageUsersPermission("query users");
- synchronized (mPackagesLock) {
+ synchronized (mUsersLock) {
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
@@ -350,8 +368,8 @@ public class UserManagerService extends IUserManager.Stub {
}
final long ident = Binder.clearCallingIdentity();
try {
- synchronized (mPackagesLock) {
- return getProfilesLocked(userId, enabledOnly);
+ synchronized (mUsersLock) {
+ return getProfilesLU(userId, enabledOnly);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -359,8 +377,8 @@ public class UserManagerService extends IUserManager.Stub {
}
/** Assume permissions already checked and caller's identity cleared */
- private List<UserInfo> getProfilesLocked(int userId, boolean enabledOnly) {
- UserInfo user = getUserInfoLocked(userId);
+ private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly) {
+ UserInfo user = getUserInfoLU(userId);
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
if (user == null) {
// Probably a dying user
@@ -387,8 +405,8 @@ public class UserManagerService extends IUserManager.Stub {
public int getCredentialOwnerProfile(int userHandle) {
checkManageUsersPermission("get the credential owner");
if (!"file".equals(SystemProperties.get("ro.crypto.type", "none"))) {
- synchronized (mPackagesLock) {
- UserInfo profileParent = getProfileParentLocked(userHandle);
+ synchronized (mUsersLock) {
+ UserInfo profileParent = getProfileParentLU(userHandle);
if (profileParent != null) {
return profileParent.id;
}
@@ -403,32 +421,35 @@ public class UserManagerService extends IUserManager.Stub {
if (userId == otherUserId) return true;
checkManageUsersPermission("check if in the same profile group");
synchronized (mPackagesLock) {
- return isSameProfileGroupLocked(userId, otherUserId);
+ return isSameProfileGroupLP(userId, otherUserId);
}
}
- private boolean isSameProfileGroupLocked(int userId, int otherUserId) {
- UserInfo userInfo = getUserInfoLocked(userId);
- if (userInfo == null || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
- return false;
- }
- UserInfo otherUserInfo = getUserInfoLocked(otherUserId);
- if (otherUserInfo == null || otherUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
- return false;
+ private boolean isSameProfileGroupLP(int userId, int otherUserId) {
+ synchronized (mUsersLock) {
+ UserInfo userInfo = getUserInfoLU(userId);
+ if (userInfo == null || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+ return false;
+ }
+ UserInfo otherUserInfo = getUserInfoLU(otherUserId);
+ if (otherUserInfo == null
+ || otherUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+ return false;
+ }
+ return userInfo.profileGroupId == otherUserInfo.profileGroupId;
}
- return userInfo.profileGroupId == otherUserInfo.profileGroupId;
}
@Override
public UserInfo getProfileParent(int userHandle) {
checkManageUsersPermission("get the profile parent");
- synchronized (mPackagesLock) {
- return getProfileParentLocked(userHandle);
+ synchronized (mUsersLock) {
+ return getProfileParentLU(userHandle);
}
}
- private UserInfo getProfileParentLocked(int userHandle) {
- UserInfo profile = getUserInfoLocked(userHandle);
+ private UserInfo getProfileParentLU(int userHandle) {
+ UserInfo profile = getUserInfoLU(userHandle);
if (profile == null) {
return null;
}
@@ -436,11 +457,11 @@ public class UserManagerService extends IUserManager.Stub {
if (parentUserId == UserInfo.NO_PROFILE_GROUP_ID) {
return null;
} else {
- return getUserInfoLocked(parentUserId);
+ return getUserInfoLU(parentUserId);
}
}
- private boolean isProfileOf(UserInfo user, UserInfo profile) {
+ private static boolean isProfileOf(UserInfo user, UserInfo profile) {
return user.id == profile.id ||
(user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
&& user.profileGroupId == profile.profileGroupId);
@@ -450,10 +471,13 @@ public class UserManagerService extends IUserManager.Stub {
public void setUserEnabled(int userId) {
checkManageUsersPermission("enable user");
synchronized (mPackagesLock) {
- UserInfo info = getUserInfoLocked(userId);
+ UserInfo info;
+ synchronized (mUsersLock) {
+ info = getUserInfoLU(userId);
+ }
if (info != null && !info.isEnabled()) {
info.flags ^= UserInfo.FLAG_DISABLED;
- writeUserLocked(info);
+ writeUserLP(info);
}
}
}
@@ -461,23 +485,23 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public UserInfo getUserInfo(int userId) {
checkManageUsersPermission("query user");
- synchronized (mPackagesLock) {
- return getUserInfoLocked(userId);
+ synchronized (mUsersLock) {
+ return getUserInfoLU(userId);
}
}
@Override
public boolean isRestricted() {
- synchronized (mPackagesLock) {
- return getUserInfoLocked(UserHandle.getCallingUserId()).isRestricted();
+ synchronized (mUsersLock) {
+ return getUserInfoLU(UserHandle.getCallingUserId()).isRestricted();
}
}
@Override
public boolean canHaveRestrictedProfile(int userId) {
checkManageUsersPermission("canHaveRestrictedProfile");
- synchronized (mPackagesLock) {
- final UserInfo userInfo = getUserInfoLocked(userId);
+ synchronized (mUsersLock) {
+ final UserInfo userInfo = getUserInfoLU(userId);
if (userInfo == null || !userInfo.canHaveProfile()) {
return false;
}
@@ -494,7 +518,7 @@ public class UserManagerService extends IUserManager.Stub {
/*
* Should be locked on mUsers before calling this.
*/
- private UserInfo getUserInfoLocked(int userId) {
+ private UserInfo getUserInfoLU(int userId) {
UserInfo ui = mUsers.get(userId);
// If it is partial and not in the process of being removed, return as unknown user.
if (ui != null && ui.partial && !mRemovingUserIds.get(userId)) {
@@ -504,11 +528,19 @@ public class UserManagerService extends IUserManager.Stub {
return ui;
}
+ /**
+ * Obtains {@link #mUsersLock} and return UserInfo from mUsers.
+ * <p>No permissions checking or any addition checks are made</p>
+ */
+ private UserInfo getUserInfoNoChecks(int userId) {
+ synchronized (mUsersLock) {
+ return mUsers.get(userId);
+ }
+ }
+
/** Called by PackageManagerService */
public boolean exists(int userId) {
- synchronized (mPackagesLock) {
- return mUsers.get(userId) != null;
- }
+ return getUserInfoNoChecks(userId) != null;
}
@Override
@@ -516,14 +548,14 @@ public class UserManagerService extends IUserManager.Stub {
checkManageUsersPermission("rename users");
boolean changed = false;
synchronized (mPackagesLock) {
- UserInfo info = mUsers.get(userId);
+ UserInfo info = getUserInfoNoChecks(userId);
if (info == null || info.partial) {
Slog.w(LOG_TAG, "setUserName: unknown user #" + userId);
return;
}
if (name != null && !name.equals(info.name)) {
info.name = name;
- writeUserLocked(info);
+ writeUserLP(info);
changed = true;
}
}
@@ -538,13 +570,13 @@ public class UserManagerService extends IUserManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
synchronized (mPackagesLock) {
- UserInfo info = mUsers.get(userId);
+ UserInfo info = getUserInfoNoChecks(userId);
if (info == null || info.partial) {
Slog.w(LOG_TAG, "setUserIcon: unknown user #" + userId);
return;
}
- writeBitmapLocked(info, bitmap);
- writeUserLocked(info);
+ writeBitmapLP(info, bitmap);
+ writeUserLP(info);
}
sendUserInfoChangedBroadcast(userId);
} finally {
@@ -563,12 +595,12 @@ public class UserManagerService extends IUserManager.Stub {
public ParcelFileDescriptor getUserIcon(int userId) {
String iconPath;
synchronized (mPackagesLock) {
- UserInfo info = mUsers.get(userId);
+ UserInfo info = getUserInfoNoChecks(userId);
if (info == null || info.partial) {
Slog.w(LOG_TAG, "getUserIcon: unknown user #" + userId);
return null;
}
- int callingGroupId = mUsers.get(UserHandle.getCallingUserId()).profileGroupId;
+ int callingGroupId = getUserInfoNoChecks(UserHandle.getCallingUserId()).profileGroupId;
if (callingGroupId == UserInfo.NO_PROFILE_GROUP_ID
|| callingGroupId != info.profileGroupId) {
checkManageUsersPermission("get the icon of a user who is not related");
@@ -591,13 +623,14 @@ public class UserManagerService extends IUserManager.Stub {
public void makeInitialized(int userId) {
checkManageUsersPermission("makeInitialized");
synchronized (mPackagesLock) {
- UserInfo info = mUsers.get(userId);
+ UserInfo info = getUserInfoNoChecks(userId);
if (info == null || info.partial) {
Slog.w(LOG_TAG, "makeInitialized: unknown user #" + userId);
+ // TODO Check if we should return here instead of a null check below
}
- if ((info.flags&UserInfo.FLAG_INITIALIZED) == 0) {
+ if (info != null && (info.flags&UserInfo.FLAG_INITIALIZED) == 0) {
info.flags |= UserInfo.FLAG_INITIALIZED;
- scheduleWriteUserLocked(info);
+ scheduleWriteUserLP(info);
}
}
}
@@ -616,6 +649,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public Bundle getDefaultGuestRestrictions() {
checkManageUsersPermission("getDefaultGuestRestrictions");
+ // TODO Switch to mGuestRestrictions for locking
synchronized (mPackagesLock) {
return new Bundle(mGuestRestrictions);
}
@@ -624,15 +658,17 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public void setDefaultGuestRestrictions(Bundle restrictions) {
checkManageUsersPermission("setDefaultGuestRestrictions");
- synchronized (mPackagesLock) {
- mGuestRestrictions.clear();
- mGuestRestrictions.putAll(restrictions);
- writeUserListLocked();
+ synchronized (mInstallLock) {
+ synchronized (mPackagesLock) {
+ mGuestRestrictions.clear();
+ mGuestRestrictions.putAll(restrictions);
+ writeUserListLILP();
+ }
}
}
@GuardedBy("mRestrictionsLock")
- private Bundle computeEffectiveUserRestrictionsRL(int userId) {
+ private Bundle computeEffectiveUserRestrictionsLR(int userId) {
final DevicePolicyManagerInternal dpmi =
LocalServices.getService(DevicePolicyManagerInternal.class);
final Bundle systemRestrictions = mBaseUserRestrictions.get(userId);
@@ -648,7 +684,7 @@ public class UserManagerService extends IUserManager.Stub {
}
@GuardedBy("mRestrictionsLock")
- private void invalidateEffectiveUserRestrictionsRL(int userId) {
+ private void invalidateEffectiveUserRestrictionsLR(int userId) {
if (DBG) {
Log.d(LOG_TAG, "invalidateEffectiveUserRestrictions userId=" + userId);
}
@@ -659,7 +695,7 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mRestrictionsLock) {
Bundle restrictions = mCachedEffectiveUserRestrictions.get(userId);
if (restrictions == null) {
- restrictions = computeEffectiveUserRestrictionsRL(userId);
+ restrictions = computeEffectiveUserRestrictionsLR(userId);
mCachedEffectiveUserRestrictions.put(userId, restrictions);
}
return restrictions;
@@ -705,7 +741,7 @@ public class UserManagerService extends IUserManager.Stub {
UserRestrictionsUtils.merge(newRestrictions, mBaseUserRestrictions.get(userId));
newRestrictions.putBoolean(key, value);
- updateUserRestrictionsInternalRL(newRestrictions, userId);
+ updateUserRestrictionsInternalLR(newRestrictions, userId);
}
}
@@ -721,14 +757,12 @@ public class UserManagerService extends IUserManager.Stub {
* @param userId target user ID.
*/
@GuardedBy("mRestrictionsLock")
- private void updateUserRestrictionsInternalRL(
+ private void updateUserRestrictionsInternalLR(
@Nullable Bundle newRestrictions, int userId) {
if (DBG) {
Log.d(LOG_TAG, "updateUserRestrictionsInternalLocked userId=" + userId
+ " bundle=" + newRestrictions);
}
- final Bundle prevRestrictions = getEffectiveUserRestrictions(userId);
-
// Update system restrictions.
if (newRestrictions != null) {
// If newRestrictions == the current one, it's probably a bug.
@@ -738,15 +772,22 @@ public class UserManagerService extends IUserManager.Stub {
mBaseUserRestrictions.put(userId, newRestrictions);
}
- mCachedEffectiveUserRestrictions.put(
- userId, computeEffectiveUserRestrictionsRL(userId));
+ final Bundle effective = computeEffectiveUserRestrictionsLR(userId);
- applyUserRestrictionsRL(userId, mBaseUserRestrictions.get(userId), prevRestrictions);
+ mCachedEffectiveUserRestrictions.put(userId, effective);
+
+ applyUserRestrictionsLR(userId, effective);
}
@GuardedBy("mRestrictionsLock")
- private void applyUserRestrictionsRL(int userId,
- Bundle newRestrictions, Bundle prevRestrictions) {
+ private void applyUserRestrictionsLR(int userId, Bundle newRestrictions) {
+ final Bundle prevRestrictions = mAppliedUserRestrictions.get(userId);
+
+ if (DBG) {
+ Log.d(LOG_TAG, "applyUserRestrictionsRL userId=" + userId
+ + " new=" + newRestrictions + " prev=" + prevRestrictions);
+ }
+
final long token = Binder.clearCallingIdentity();
try {
mAppOpsService.setUserRestrictions(newRestrictions, userId);
@@ -756,20 +797,22 @@ public class UserManagerService extends IUserManager.Stub {
Binder.restoreCallingIdentity(token);
}
- // TODO Move the code from DPMS.setUserRestriction().
+ UserRestrictionsUtils.applyUserRestrictions(
+ mContext, userId, newRestrictions, prevRestrictions);
+
+ mAppliedUserRestrictions.put(userId, new Bundle(newRestrictions));
}
@GuardedBy("mRestrictionsLock")
- private void updateEffectiveUserRestrictionsRL(int userId) {
- updateUserRestrictionsInternalRL(null, userId);
+ private void updateEffectiveUserRestrictionsLR(int userId) {
+ updateUserRestrictionsInternalLR(null, userId);
}
@GuardedBy("mRestrictionsLock")
- private void updateEffectiveUserRestrictionsForAllUsersRL() {
+ private void updateEffectiveUserRestrictionsForAllUsersLR() {
// First, invalidate all cached values.
- synchronized (mRestrictionsLock) {
- mCachedEffectiveUserRestrictions.clear();
- }
+ mCachedEffectiveUserRestrictions.clear();
+
// We don't want to call into ActivityManagerNative while taking a lock, so we'll call
// it on a handler.
final Runnable r = new Runnable() {
@@ -790,7 +833,7 @@ public class UserManagerService extends IUserManager.Stub {
// TODO: "Apply restrictions upon user start hasn't been implemented. Implement it.
synchronized (mRestrictionsLock) {
for (int i = 0; i < runningUsers.length; i++) {
- updateUserRestrictionsInternalRL(null, runningUsers[i]);
+ updateUserRestrictionsInternalLR(null, runningUsers[i]);
}
}
}
@@ -801,8 +844,12 @@ public class UserManagerService extends IUserManager.Stub {
/**
* Check if we've hit the limit of how many users can be created.
*/
- private boolean isUserLimitReachedLocked() {
- return getAliveUsersExcludingGuestsCountLocked() >= UserManager.getMaxSupportedUsers();
+ private boolean isUserLimitReached() {
+ int count;
+ synchronized (mUsersLock) {
+ count = getAliveUsersExcludingGuestsCountLU();
+ }
+ return count >= UserManager.getMaxSupportedUsers();
}
@Override
@@ -820,18 +867,18 @@ public class UserManagerService extends IUserManager.Stub {
if (managedProfilesCount >= MAX_MANAGED_PROFILES) {
return false;
}
- synchronized(mPackagesLock) {
- UserInfo userInfo = getUserInfoLocked(userId);
+ synchronized(mUsersLock) {
+ UserInfo userInfo = getUserInfoLU(userId);
if (!userInfo.canHaveProfile()) {
return false;
}
- int usersCount = getAliveUsersExcludingGuestsCountLocked();
+ int usersCount = getAliveUsersExcludingGuestsCountLU();
// We allow creating a managed profile in the special case where there is only one user.
return usersCount == 1 || usersCount < UserManager.getMaxSupportedUsers();
}
}
- private int getAliveUsersExcludingGuestsCountLocked() {
+ private int getAliveUsersExcludingGuestsCountLU() {
int aliveUserCount = 0;
final int totalUserCount = mUsers.size();
// Skip over users being removed
@@ -870,7 +917,7 @@ public class UserManagerService extends IUserManager.Stub {
}
}
- private void writeBitmapLocked(UserInfo info, Bitmap bitmap) {
+ private void writeBitmapLP(UserInfo info, Bitmap bitmap) {
try {
File dir = new File(mUsersDir, Integer.toString(info.id));
File file = new File(dir, USER_PHOTO_FILENAME);
@@ -904,18 +951,14 @@ public class UserManagerService extends IUserManager.Stub {
* @return the array of user ids.
*/
public int[] getUserIds() {
- synchronized (mPackagesLock) {
+ synchronized (mUsersLock) {
return mUserIds;
}
}
- int[] getUserIdsLPr() {
- return mUserIds;
- }
-
- private void readUserListLocked() {
+ private void readUserListLILP() {
if (!mUserListFile.exists()) {
- fallbackToSingleUserLocked();
+ fallbackToSingleUserLILP();
return;
}
FileInputStream fis = null;
@@ -932,7 +975,7 @@ public class UserManagerService extends IUserManager.Stub {
if (type != XmlPullParser.START_TAG) {
Slog.e(LOG_TAG, "Unable to read user list");
- fallbackToSingleUserLocked();
+ fallbackToSingleUserLILP();
return;
}
@@ -953,12 +996,14 @@ public class UserManagerService extends IUserManager.Stub {
final String name = parser.getName();
if (name.equals(TAG_USER)) {
String id = parser.getAttributeValue(null, ATTR_ID);
- UserInfo user = readUserLocked(Integer.parseInt(id));
+ UserInfo user = readUserLILP(Integer.parseInt(id));
if (user != null) {
- mUsers.put(user.id, user);
- if (mNextSerialNumber < 0 || mNextSerialNumber <= user.id) {
- mNextSerialNumber = user.id + 1;
+ synchronized (mUsersLock) {
+ mUsers.put(user.id, user);
+ if (mNextSerialNumber < 0 || mNextSerialNumber <= user.id) {
+ mNextSerialNumber = user.id + 1;
+ }
}
}
} else if (name.equals(TAG_GUEST_RESTRICTIONS)) {
@@ -975,12 +1020,12 @@ public class UserManagerService extends IUserManager.Stub {
}
}
}
- updateUserIdsLocked();
- upgradeIfNecessaryLocked();
+ updateUserIds();
+ upgradeIfNecessaryLILP();
} catch (IOException ioe) {
- fallbackToSingleUserLocked();
+ fallbackToSingleUserLILP();
} catch (XmlPullParserException pe) {
- fallbackToSingleUserLocked();
+ fallbackToSingleUserLILP();
} finally {
if (fis != null) {
try {
@@ -994,24 +1039,24 @@ public class UserManagerService extends IUserManager.Stub {
/**
* Upgrade steps between versions, either for fixing bugs or changing the data format.
*/
- private void upgradeIfNecessaryLocked() {
+ private void upgradeIfNecessaryLILP() {
int userVersion = mUserVersion;
if (userVersion < 1) {
// Assign a proper name for the owner, if not initialized correctly before
- UserInfo user = mUsers.get(UserHandle.USER_SYSTEM);
+ UserInfo user = getUserInfoNoChecks(UserHandle.USER_SYSTEM);
if ("Primary".equals(user.name)) {
user.name = mContext.getResources().getString(com.android.internal.R.string.owner_name);
- scheduleWriteUserLocked(user);
+ scheduleWriteUserLP(user);
}
userVersion = 1;
}
if (userVersion < 2) {
// Owner should be marked as initialized
- UserInfo user = mUsers.get(UserHandle.USER_SYSTEM);
+ UserInfo user = getUserInfoNoChecks(UserHandle.USER_SYSTEM);
if ((user.flags & UserInfo.FLAG_INITIALIZED) == 0) {
user.flags |= UserInfo.FLAG_INITIALIZED;
- scheduleWriteUserLocked(user);
+ scheduleWriteUserLP(user);
}
userVersion = 2;
}
@@ -1028,13 +1073,15 @@ public class UserManagerService extends IUserManager.Stub {
if (userVersion < 6) {
final boolean splitSystemUser = UserManager.isSplitSystemUser();
- for (int i = 0; i < mUsers.size(); i++) {
- UserInfo user = mUsers.valueAt(i);
- // In non-split mode, only user 0 can have restricted profiles
- if (!splitSystemUser && user.isRestricted()
- && (user.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID)) {
- user.restrictedProfileParentId = UserHandle.USER_SYSTEM;
- scheduleWriteUserLocked(user);
+ synchronized (mUsersLock) {
+ for (int i = 0; i < mUsers.size(); i++) {
+ UserInfo user = mUsers.valueAt(i);
+ // In non-split mode, only user 0 can have restricted profiles
+ if (!splitSystemUser && user.isRestricted()
+ && (user.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID)) {
+ user.restrictedProfileParentId = UserHandle.USER_SYSTEM;
+ scheduleWriteUserLP(user);
+ }
}
}
userVersion = 6;
@@ -1045,11 +1092,11 @@ public class UserManagerService extends IUserManager.Stub {
+ USER_VERSION);
} else {
mUserVersion = userVersion;
- writeUserListLocked();
+ writeUserListLILP();
}
}
- private void fallbackToSingleUserLocked() {
+ private void fallbackToSingleUserLILP() {
int flags = UserInfo.FLAG_INITIALIZED;
// In split system user mode, the admin and primary flags are assigned to the first human
// user.
@@ -1060,7 +1107,9 @@ public class UserManagerService extends IUserManager.Stub {
UserInfo system = new UserInfo(UserHandle.USER_SYSTEM,
mContext.getResources().getString(com.android.internal.R.string.owner_name), null,
flags);
- mUsers.put(system.id, system);
+ synchronized (mUsersLock) {
+ mUsers.put(system.id, system);
+ }
mNextSerialNumber = MIN_USER_ID;
mUserVersion = USER_VERSION;
@@ -1069,14 +1118,14 @@ public class UserManagerService extends IUserManager.Stub {
mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
}
- updateUserIdsLocked();
+ updateUserIds();
initDefaultGuestRestrictions();
- writeUserListLocked();
- writeUserLocked(system);
+ writeUserListLILP();
+ writeUserLP(system);
}
- private void scheduleWriteUserLocked(UserInfo userInfo) {
+ private void scheduleWriteUserLP(UserInfo userInfo) {
if (!mHandler.hasMessages(WRITE_USER_MSG, userInfo)) {
Message msg = mHandler.obtainMessage(WRITE_USER_MSG, userInfo);
mHandler.sendMessageDelayed(msg, WRITE_USER_DELAY);
@@ -1090,7 +1139,7 @@ public class UserManagerService extends IUserManager.Stub {
* <name>Primary</name>
* </user>
*/
- private void writeUserLocked(UserInfo userInfo) {
+ private void writeUserLP(UserInfo userInfo) {
FileOutputStream fos = null;
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userInfo.id + XML_SUFFIX));
try {
@@ -1156,7 +1205,8 @@ public class UserManagerService extends IUserManager.Stub {
* <user id="2"></user>
* </users>
*/
- private void writeUserListLocked() {
+ private void writeUserListLILP() {
+ // TODO Investigate removing a dependency on mInstallLock
FileOutputStream fos = null;
AtomicFile userListFile = new AtomicFile(mUserListFile);
try {
@@ -1177,11 +1227,17 @@ public class UserManagerService extends IUserManager.Stub {
UserRestrictionsUtils
.writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS);
serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
- final int userSize = mUsers.size();
- for (int i = 0; i < userSize; i++) {
- UserInfo user = mUsers.valueAt(i);
+ int[] userIdsToWrite;
+ synchronized (mUsersLock) {
+ userIdsToWrite = new int[mUsers.size()];
+ for (int i = 0; i < userIdsToWrite.length; i++) {
+ UserInfo user = mUsers.valueAt(i);
+ userIdsToWrite[i] = user.id;
+ }
+ }
+ for (int id : userIdsToWrite) {
serializer.startTag(null, TAG_USER);
- serializer.attribute(null, ATTR_ID, Integer.toString(user.id));
+ serializer.attribute(null, ATTR_ID, Integer.toString(id));
serializer.endTag(null, TAG_USER);
}
@@ -1195,7 +1251,7 @@ public class UserManagerService extends IUserManager.Stub {
}
}
- private UserInfo readUserLocked(int id) {
+ private UserInfo readUserLILP(int id) {
int flags = 0;
int serialNumber = id;
String name = null;
@@ -1389,20 +1445,22 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mPackagesLock) {
UserInfo parent = null;
if (parentId != UserHandle.USER_NULL) {
- parent = getUserInfoLocked(parentId);
+ synchronized (mUsersLock) {
+ parent = getUserInfoLU(parentId);
+ }
if (parent == null) return null;
}
if (isManagedProfile && !canAddMoreManagedProfiles(parentId)) {
Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
return null;
}
- if (!isGuest && !isManagedProfile && isUserLimitReachedLocked()) {
+ if (!isGuest && !isManagedProfile && isUserLimitReached()) {
// If we're not adding a guest user or a managed profile and the limit has
// been reached, cannot add a user.
return null;
}
// If we're adding a guest and there already exists one, bail.
- if (isGuest && findCurrentGuestUserLocked() != null) {
+ if (isGuest && findCurrentGuestUser() != null) {
return null;
}
// In legacy mode, restricted profile's parent can only be the owner user
@@ -1436,7 +1494,7 @@ public class UserManagerService extends IUserManager.Stub {
flags |= UserInfo.FLAG_ADMIN;
}
}
- userId = getNextAvailableIdLocked();
+ userId = getNextAvailableId();
userInfo = new UserInfo(userId, name, null, flags);
userInfo.serialNumber = mNextSerialNumber++;
long now = System.currentTimeMillis();
@@ -1444,12 +1502,12 @@ public class UserManagerService extends IUserManager.Stub {
userInfo.partial = true;
Environment.getUserSystemDirectory(userInfo.id).mkdirs();
mUsers.put(userId, userInfo);
- writeUserListLocked();
+ writeUserListLILP();
if (parent != null) {
if (isManagedProfile) {
if (parent.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
parent.profileGroupId = parent.id;
- scheduleWriteUserLocked(parent);
+ scheduleWriteUserLP(parent);
}
userInfo.profileGroupId = parent.profileGroupId;
} else if (isRestricted) {
@@ -1458,7 +1516,7 @@ public class UserManagerService extends IUserManager.Stub {
}
if (parent.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID) {
parent.restrictedProfileParentId = parent.id;
- scheduleWriteUserLocked(parent);
+ scheduleWriteUserLP(parent);
}
userInfo.restrictedProfileParentId = parent.restrictedProfileParentId;
}
@@ -1477,8 +1535,8 @@ public class UserManagerService extends IUserManager.Stub {
}
mPm.createNewUserLILPw(userId);
userInfo.partial = false;
- scheduleWriteUserLocked(userInfo);
- updateUserIdsLocked();
+ scheduleWriteUserLP(userInfo);
+ updateUserIds();
Bundle restrictions = new Bundle();
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.append(userId, restrictions);
@@ -1521,12 +1579,14 @@ public class UserManagerService extends IUserManager.Stub {
* Find the current guest user. If the Guest user is partial,
* then do not include it in the results as it is about to die.
*/
- private UserInfo findCurrentGuestUserLocked() {
- final int size = mUsers.size();
- for (int i = 0; i < size; i++) {
- final UserInfo user = mUsers.valueAt(i);
- if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) {
- return user;
+ private UserInfo findCurrentGuestUser() {
+ synchronized (mUsersLock) {
+ final int size = mUsers.size();
+ for (int i = 0; i < size; i++) {
+ final UserInfo user = mUsers.valueAt(i);
+ if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) {
+ return user;
+ }
}
}
return null;
@@ -1550,9 +1610,11 @@ public class UserManagerService extends IUserManager.Stub {
try {
final UserInfo user;
synchronized (mPackagesLock) {
- user = mUsers.get(userHandle);
- if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) {
- return false;
+ synchronized (mUsersLock) {
+ user = mUsers.get(userHandle);
+ if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) {
+ return false;
+ }
}
if (!user.isGuest()) {
return false;
@@ -1566,7 +1628,7 @@ public class UserManagerService extends IUserManager.Stub {
// Mark it as disabled, so that it isn't returned any more when
// profiles are queried.
user.flags |= UserInfo.FLAG_DISABLED;
- writeUserLocked(user);
+ writeUserLP(user);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -1596,15 +1658,17 @@ public class UserManagerService extends IUserManager.Stub {
return false;
}
synchronized (mPackagesLock) {
- user = mUsers.get(userHandle);
- if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) {
- return false;
- }
+ synchronized (mUsersLock) {
+ user = mUsers.get(userHandle);
+ if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) {
+ return false;
+ }
- // We remember deleted user IDs to prevent them from being
- // reused during the current boot; they can still be reused
- // after a reboot.
- mRemovingUserIds.put(userHandle, true);
+ // We remember deleted user IDs to prevent them from being
+ // reused during the current boot; they can still be reused
+ // after a reboot.
+ mRemovingUserIds.put(userHandle, true);
+ }
try {
mAppOpsService.removeUser(userHandle);
@@ -1618,7 +1682,7 @@ public class UserManagerService extends IUserManager.Stub {
// Mark it as disabled, so that it isn't returned any more when
// profiles are queried.
user.flags |= UserInfo.FLAG_DISABLED;
- writeUserLocked(user);
+ writeUserLP(user);
}
if (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
@@ -1676,7 +1740,7 @@ public class UserManagerService extends IUserManager.Stub {
.onUserRemoved(userHandle);
synchronized (mInstallLock) {
synchronized (mPackagesLock) {
- removeUserStateLocked(userHandle);
+ removeUserStateLILP(userHandle);
}
}
}
@@ -1690,20 +1754,22 @@ public class UserManagerService extends IUserManager.Stub {
}
}
- private void removeUserStateLocked(final int userHandle) {
+ private void removeUserStateLILP(final int userHandle) {
mContext.getSystemService(StorageManager.class)
.deleteUserKey(userHandle);
// Cleanup package manager settings
mPm.cleanUpUserLILPw(this, userHandle);
// Remove this user from the list
- mUsers.remove(userHandle);
+ synchronized (mUsersLock) {
+ mUsers.remove(userHandle);
+ }
// Remove user file
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
userFile.delete();
// Update the user list
- writeUserListLocked();
- updateUserIdsLocked();
+ writeUserListLILP();
+ updateUserIds();
removeDirectoryRecursive(Environment.getUserSystemDirectory(userHandle));
}
@@ -1739,7 +1805,7 @@ public class UserManagerService extends IUserManager.Stub {
}
synchronized (mPackagesLock) {
// Read the restrictions from XML
- return readApplicationRestrictionsLocked(packageName, userId);
+ return readApplicationRestrictionsLP(packageName, userId);
}
}
@@ -1752,7 +1818,7 @@ public class UserManagerService extends IUserManager.Stub {
cleanAppRestrictionsForPackage(packageName, userId);
} else {
// Write the restrictions to XML
- writeApplicationRestrictionsLocked(packageName, restrictions, userId);
+ writeApplicationRestrictionsLP(packageName, restrictions, userId);
}
}
@@ -1800,16 +1866,15 @@ public class UserManagerService extends IUserManager.Stub {
}
}
- private Bundle readApplicationRestrictionsLocked(String packageName,
- int userId) {
+ private Bundle readApplicationRestrictionsLP(String packageName, int userId) {
AtomicFile restrictionsFile =
new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
packageToRestrictionsFileName(packageName)));
- return readApplicationRestrictionsLocked(restrictionsFile);
+ return readApplicationRestrictionsLP(restrictionsFile);
}
@VisibleForTesting
- static Bundle readApplicationRestrictionsLocked(AtomicFile restrictionsFile) {
+ static Bundle readApplicationRestrictionsLP(AtomicFile restrictionsFile) {
final Bundle restrictions = new Bundle();
final ArrayList<String> values = new ArrayList<>();
if (!restrictionsFile.getBaseFile().exists()) {
@@ -1892,17 +1957,16 @@ public class UserManagerService extends IUserManager.Stub {
return childBundle;
}
- private void writeApplicationRestrictionsLocked(String packageName,
+ private void writeApplicationRestrictionsLP(String packageName,
Bundle restrictions, int userId) {
AtomicFile restrictionsFile = new AtomicFile(
new File(Environment.getUserSystemDirectory(userId),
packageToRestrictionsFileName(packageName)));
- writeApplicationRestrictionsLocked(restrictions, restrictionsFile);
+ writeApplicationRestrictionsLP(restrictions, restrictionsFile);
}
@VisibleForTesting
- static void writeApplicationRestrictionsLocked(Bundle restrictions,
- AtomicFile restrictionsFile) {
+ static void writeApplicationRestrictionsLP(Bundle restrictions, AtomicFile restrictionsFile) {
FileOutputStream fos = null;
try {
fos = restrictionsFile.startWrite();
@@ -1972,17 +2036,17 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public int getUserSerialNumber(int userHandle) {
- synchronized (mPackagesLock) {
+ synchronized (mUsersLock) {
if (!exists(userHandle)) return -1;
- return getUserInfoLocked(userHandle).serialNumber;
+ return getUserInfoLU(userHandle).serialNumber;
}
}
@Override
public int getUserHandle(int userSerialNumber) {
- synchronized (mPackagesLock) {
+ synchronized (mUsersLock) {
for (int userId : mUserIds) {
- UserInfo info = getUserInfoLocked(userId);
+ UserInfo info = getUserInfoLU(userId);
if (info != null && info.serialNumber == userSerialNumber) return userId;
}
// Not found
@@ -1994,13 +2058,13 @@ public class UserManagerService extends IUserManager.Stub {
public long getUserCreationTime(int userHandle) {
int callingUserId = UserHandle.getCallingUserId();
UserInfo userInfo = null;
- synchronized (mPackagesLock) {
+ synchronized (mUsersLock) {
if (callingUserId == userHandle) {
- userInfo = getUserInfoLocked(userHandle);
+ userInfo = getUserInfoLU(userHandle);
} else {
- UserInfo parent = getProfileParentLocked(userHandle);
+ UserInfo parent = getProfileParentLU(userHandle);
if (parent != null && parent.id == callingUserId) {
- userInfo = getUserInfoLocked(userHandle);
+ userInfo = getUserInfoLU(userHandle);
}
}
}
@@ -2014,22 +2078,24 @@ public class UserManagerService extends IUserManager.Stub {
/**
* Caches the list of user ids in an array, adjusting the array size when necessary.
*/
- private void updateUserIdsLocked() {
+ private void updateUserIds() {
int num = 0;
- final int userSize = mUsers.size();
- for (int i = 0; i < userSize; i++) {
- if (!mUsers.valueAt(i).partial) {
- num++;
+ synchronized (mUsersLock) {
+ final int userSize = mUsers.size();
+ for (int i = 0; i < userSize; i++) {
+ if (!mUsers.valueAt(i).partial) {
+ num++;
+ }
}
- }
- final int[] newUsers = new int[num];
- int n = 0;
- for (int i = 0; i < userSize; i++) {
- if (!mUsers.valueAt(i).partial) {
- newUsers[n++] = mUsers.keyAt(i);
+ final int[] newUsers = new int[num];
+ int n = 0;
+ for (int i = 0; i < userSize; i++) {
+ if (!mUsers.valueAt(i).partial) {
+ newUsers[n++] = mUsers.keyAt(i);
+ }
}
+ mUserIds = newUsers;
}
- mUserIds = newUsers;
}
/**
@@ -2038,7 +2104,7 @@ public class UserManagerService extends IUserManager.Stub {
*/
public void onUserForeground(int userId) {
synchronized (mPackagesLock) {
- UserInfo user = mUsers.get(userId);
+ UserInfo user = getUserInfoNoChecks(userId);
long now = System.currentTimeMillis();
if (user == null || user.partial) {
Slog.w(LOG_TAG, "userForeground: unknown user #" + userId);
@@ -2046,7 +2112,7 @@ public class UserManagerService extends IUserManager.Stub {
}
if (now > EPOCH_PLUS_30_YEARS) {
user.lastLoggedInTime = now;
- scheduleWriteUserLocked(user);
+ scheduleWriteUserLP(user);
}
}
}
@@ -2057,8 +2123,8 @@ public class UserManagerService extends IUserManager.Stub {
* for data and battery stats collection, or unexpected cross-talk.
* @return
*/
- private int getNextAvailableIdLocked() {
- synchronized (mPackagesLock) {
+ private int getNextAvailableId() {
+ synchronized (mUsersLock) {
int i = MIN_USER_ID;
while (i < MAX_USER_ID) {
if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) {
@@ -2150,6 +2216,45 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out,
+ FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
+ (new Shell()).exec(this, in, out, err, args, resultReceiver);
+ }
+
+ int onShellCommand(Shell shell, String cmd) {
+ if (cmd == null) {
+ return shell.handleDefaultCommands(cmd);
+ }
+
+ final PrintWriter pw = shell.getOutPrintWriter();
+ try {
+ switch(cmd) {
+ case "list":
+ return runList(pw);
+ }
+ } catch (RemoteException e) {
+ pw.println("Remote exception: " + e);
+ }
+ return -1;
+ }
+
+ private int runList(PrintWriter pw) throws RemoteException {
+ final IActivityManager am = ActivityManagerNative.getDefault();
+ final List<UserInfo> users = getUsers(false);
+ if (users == null) {
+ pw.println("Error: couldn't get users");
+ return 1;
+ } else {
+ pw.println("Users:");
+ for (int i = 0; i < users.size(); i++) {
+ String running = am.isUserRunning(users.get(i).id, false) ? " running" : "";
+ pw.println("\t" + users.get(i).toString() + running);
+ }
+ return 0;
+ }
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -2164,38 +2269,49 @@ public class UserManagerService extends IUserManager.Stub {
long now = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
synchronized (mPackagesLock) {
- pw.println("Users:");
- for (int i = 0; i < mUsers.size(); i++) {
- UserInfo user = mUsers.valueAt(i);
- if (user == null) continue;
- pw.print(" "); pw.print(user); pw.print(" serialNo="); pw.print(user.serialNumber);
- if (mRemovingUserIds.get(mUsers.keyAt(i))) pw.print(" <removing> ");
- if (user.partial) pw.print(" <partial>");
- pw.println();
- pw.print(" Created: ");
- if (user.creationTime == 0) {
- pw.println("<unknown>");
- } else {
- sb.setLength(0);
- TimeUtils.formatDuration(now - user.creationTime, sb);
- sb.append(" ago");
- pw.println(sb);
- }
- pw.print(" Last logged in: ");
- if (user.lastLoggedInTime == 0) {
- pw.println("<unknown>");
- } else {
- sb.setLength(0);
- TimeUtils.formatDuration(now - user.lastLoggedInTime, sb);
- sb.append(" ago");
- pw.println(sb);
+ synchronized (mUsersLock) {
+ pw.println("Users:");
+ for (int i = 0; i < mUsers.size(); i++) {
+ UserInfo user = mUsers.valueAt(i);
+ if (user == null) {
+ continue;
+ }
+ pw.print(" "); pw.print(user);
+ pw.print(" serialNo="); pw.print(user.serialNumber);
+ if (mRemovingUserIds.get(mUsers.keyAt(i))) {
+ pw.print(" <removing> ");
+ }
+ if (user.partial) {
+ pw.print(" <partial>");
+ }
+ pw.println();
+ pw.print(" Created: ");
+ if (user.creationTime == 0) {
+ pw.println("<unknown>");
+ } else {
+ sb.setLength(0);
+ TimeUtils.formatDuration(now - user.creationTime, sb);
+ sb.append(" ago");
+ pw.println(sb);
+ }
+ pw.print(" Last logged in: ");
+ if (user.lastLoggedInTime == 0) {
+ pw.println("<unknown>");
+ } else {
+ sb.setLength(0);
+ TimeUtils.formatDuration(now - user.lastLoggedInTime, sb);
+ sb.append(" ago");
+ pw.println(sb);
+ }
+ pw.println(" Restrictions:");
+ synchronized (mRestrictionsLock) {
+ UserRestrictionsUtils.dumpRestrictions(
+ pw, " ", mBaseUserRestrictions.get(user.id));
+ pw.println(" Effective restrictions:");
+ UserRestrictionsUtils.dumpRestrictions(
+ pw, " ", mCachedEffectiveUserRestrictions.get(user.id));
+ }
}
- pw.println(" Restrictions:");
- UserRestrictionsUtils.dumpRestrictions(
- pw, " ", mBaseUserRestrictions.get(user.id));
- pw.println(" Effective restrictions:");
- UserRestrictionsUtils.dumpRestrictions(
- pw, " ", mCachedEffectiveUserRestrictions.get(user.id));
}
pw.println();
pw.println("Guest restrictions:");
@@ -2212,9 +2328,9 @@ public class UserManagerService extends IUserManager.Stub {
removeMessages(WRITE_USER_MSG, msg.obj);
synchronized (mPackagesLock) {
int userId = ((UserInfo) msg.obj).id;
- UserInfo userInfo = mUsers.get(userId);
+ UserInfo userInfo = getUserInfoNoChecks(userId);
if (userInfo != null) {
- writeUserLocked(userInfo);
+ writeUserLP(userInfo);
}
}
}
@@ -2238,14 +2354,14 @@ public class UserManagerService extends IUserManager.Stub {
@Override
@GuardedBy("mRestrictionsLock")
- public void updateEffectiveUserRestrictionsRL(int userId) {
- UserManagerService.this.updateEffectiveUserRestrictionsRL(userId);
+ public void updateEffectiveUserRestrictionsLR(int userId) {
+ UserManagerService.this.updateEffectiveUserRestrictionsLR(userId);
}
@Override
@GuardedBy("mRestrictionsLock")
- public void updateEffectiveUserRestrictionsForAllUsersRL() {
- UserManagerService.this.updateEffectiveUserRestrictionsForAllUsersRL();
+ public void updateEffectiveUserRestrictionsForAllUsersLR() {
+ UserManagerService.this.updateEffectiveUserRestrictionsForAllUsersLR();
}
@Override
@@ -2260,17 +2376,35 @@ public class UserManagerService extends IUserManager.Stub {
int userId, Bundle baseRestrictions) {
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.put(userId, new Bundle(baseRestrictions));
- invalidateEffectiveUserRestrictionsRL(userId);
+ invalidateEffectiveUserRestrictionsLR(userId);
}
+ final UserInfo userInfo = getUserInfoNoChecks(userId);
synchronized (mPackagesLock) {
- final UserInfo userInfo = mUsers.get(userId);
if (userInfo != null) {
- writeUserLocked(userInfo);
+ writeUserLP(userInfo);
} else {
Slog.w(LOG_TAG, "UserInfo not found for " + userId);
}
}
}
}
+
+ private class Shell extends ShellCommand {
+ @Override
+ public int onCommand(String cmd) {
+ return onShellCommand(this, cmd);
+ }
+
+ @Override
+ public void onHelp() {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println("User manager (user) commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println("");
+ pw.println(" list");
+ pw.println(" Prints all users on the system.");
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 23e3b35ae3da..28df9f673ed0 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -18,10 +18,19 @@ package com.android.server.pm;
import com.google.android.collect.Sets;
-import com.android.internal.util.Preconditions;
-
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.media.IAudioService;
+import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Slog;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
@@ -31,6 +40,8 @@ import java.io.PrintWriter;
import java.util.Set;
public class UserRestrictionsUtils {
+ private static final String TAG = "UserRestrictionsUtils";
+
private UserRestrictionsUtils() {
}
@@ -115,6 +126,118 @@ public class UserRestrictionsUtils {
}
}
+ /**
+ * Takes a new use restriction set and the previous set, and apply the restrictions that have
+ * changed.
+ */
+ public static void applyUserRestrictions(Context context, int userId,
+ @Nullable Bundle newRestrictions, @Nullable Bundle prevRestrictions) {
+ if (newRestrictions == null) {
+ newRestrictions = Bundle.EMPTY;
+ }
+ if (prevRestrictions == null) {
+ prevRestrictions = Bundle.EMPTY;
+ }
+ for (String key : USER_RESTRICTIONS) {
+ final boolean newValue = newRestrictions.getBoolean(key);
+ final boolean prevValue = prevRestrictions.getBoolean(key);
+
+ if (newValue != prevValue) {
+ applyUserRestriction(context, userId, key, newValue);
+ }
+ }
+ }
+
+ private static void applyUserRestriction(Context context, int userId, String key,
+ boolean newValue) {
+ // When certain restrictions are cleared, we don't update the system settings,
+ // because these settings are changeable on the Settings UI and we don't know the original
+ // value -- for example LOCATION_MODE might have been off already when the restriction was
+ // set, and in that case even if the restriction is lifted, changing it to ON would be
+ // wrong. So just don't do anything in such a case. If the user hopes to enable location
+ // later, they can do it on the Settings UI.
+
+ final ContentResolver cr = context.getContentResolver();
+ final long id = Binder.clearCallingIdentity();
+ try {
+ switch (key) {
+ case UserManager.DISALLOW_UNMUTE_MICROPHONE:
+ IAudioService.Stub.asInterface(ServiceManager.getService(Context.AUDIO_SERVICE))
+ .setMicrophoneMute(newValue, context.getPackageName(), userId);
+ break;
+ case UserManager.DISALLOW_ADJUST_VOLUME:
+ IAudioService.Stub.asInterface(ServiceManager.getService(Context.AUDIO_SERVICE))
+ .setMasterMute(newValue, 0, context.getPackageName(), userId);
+ break;
+ case UserManager.DISALLOW_CONFIG_WIFI:
+ if (newValue) {
+ android.provider.Settings.Secure.putIntForUser(cr,
+ android.provider.Settings.Secure
+ .WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0, userId);
+ }
+ break;
+ case UserManager.DISALLOW_SHARE_LOCATION:
+ if (newValue) {
+ android.provider.Settings.Secure.putIntForUser(cr,
+ android.provider.Settings.Secure.LOCATION_MODE,
+ android.provider.Settings.Secure.LOCATION_MODE_OFF,
+ userId);
+ android.provider.Settings.Secure.putStringForUser(cr,
+ android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
+ userId);
+ }
+ // Send out notifications as some clients may want to reread the
+ // value which actually changed due to a restriction having been
+ // applied.
+ final String property =
+ android.provider.Settings.Secure.SYS_PROP_SETTING_VERSION;
+ long version = SystemProperties.getLong(property, 0) + 1;
+ SystemProperties.set(property, Long.toString(version));
+
+ final String name = android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
+ final Uri url = Uri.withAppendedPath(
+ android.provider.Settings.Secure.CONTENT_URI, name);
+ context.getContentResolver().notifyChange(url, null, true, userId);
+
+ break;
+ case UserManager.DISALLOW_DEBUGGING_FEATURES:
+ if (newValue) {
+ // Only disable adb if changing for system user, since it is global
+ // TODO: should this be admin user?
+ if (userId == UserHandle.USER_SYSTEM) {
+ android.provider.Settings.Global.putStringForUser(cr,
+ android.provider.Settings.Global.ADB_ENABLED, "0",
+ userId);
+ }
+ }
+ break;
+ case UserManager.ENSURE_VERIFY_APPS:
+ if (newValue) {
+ android.provider.Settings.Global.putStringForUser(
+ context.getContentResolver(),
+ android.provider.Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
+ userId);
+ android.provider.Settings.Global.putStringForUser(
+ context.getContentResolver(),
+ android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
+ userId);
+ }
+ break;
+ case UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES:
+ if (newValue) {
+ android.provider.Settings.Secure.putIntForUser(cr,
+ android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
+ userId);
+ }
+ break;
+ }
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Failed to talk to AudioService.", re);
+ } finally {
+ Binder.restoreCallingIdentity(id);
+ }
+ }
+
public static void dumpRestrictions(PrintWriter pw, String prefix, Bundle restrictions) {
boolean noneSet = true;
if (restrictions != null) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b38b9ceb0712..209751ee4bcd 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -16,8 +16,8 @@
package com.android.server.policy;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index d4c5f8716c0e..ac79b36f7005 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -40,6 +40,8 @@ public class WebViewUpdateService extends SystemService {
private boolean mRelroReady32Bit = false;
private boolean mRelroReady64Bit = false;
+ private String oldWebViewPackageName = null;
+
private BroadcastReceiver mWebViewUpdatedReceiver;
public WebViewUpdateService(Context context) {
@@ -51,9 +53,22 @@ public class WebViewUpdateService extends SystemService {
mWebViewUpdatedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- String webviewPackage = "package:" + WebViewFactory.getWebViewPackageName();
- if (webviewPackage.equals(intent.getDataString())) {
- onWebViewUpdateInstalled();
+
+ for (String packageName : WebViewFactory.getWebViewPackageNames()) {
+ String webviewPackage = "package:" + packageName;
+
+ if (webviewPackage.equals(intent.getDataString())) {
+ String usedPackageName =
+ WebViewFactory.findPreferredWebViewPackage().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.
+ if (packageName.equals(usedPackageName) ||
+ packageName.equals(oldWebViewPackageName)) {
+ onWebViewUpdateInstalled();
+ oldWebViewPackageName = usedPackageName;
+ }
+ return;
+ }
}
}
};
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index c5bd3a79ac5b..914309765b96 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -102,6 +102,7 @@ class AppWindowToken extends WindowToken {
// Set to true when the token has been removed from the window mgr.
boolean removed;
+ boolean appDied;
// Information about an application starting window if displayed.
StartingData startingData;
WindowState startingWindow;
@@ -365,6 +366,26 @@ class AppWindowToken extends WindowToken {
windows.clear();
}
+ void removeAllDeadWindows() {
+ for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;
+ // removeWindowLocked at bottom of loop may remove multiple entries from
+ // allAppWindows if the window to be removed has child windows. It also may
+ // not remove any windows from allAppWindows at all if win is exiting and
+ // currently animating away. This ensures that winNdx is monotonically decreasing
+ // and never beyond allAppWindows bounds.
+ winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
+ WindowState win = allAppWindows.get(winNdx);
+ if (win.mAppDied) {
+ if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) {
+ Slog.w(WindowManagerService.TAG, "removeAllDeadWindows: " + win);
+ }
+ // Set mDestroying, we don't want any animation or delayed removal here.
+ win.mDestroying = true;
+ service.removeWindowLocked(win);
+ }
+ }
+ }
+
@Override
void dump(PrintWriter pw, String prefix) {
super.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/wm/DimBehindController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index 8870dd1ceef2..f9aca0009ee2 100644
--- a/services/core/java/com/android/server/wm/DimBehindController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -1,6 +1,7 @@
package com.android.server.wm;
import static com.android.server.wm.WindowManagerService.DEBUG_DIM_LAYER;
+import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM;
import android.graphics.Rect;
import android.util.ArrayMap;
@@ -11,32 +12,38 @@ import java.io.PrintWriter;
/**
* Centralizes the control of dim layers used for
- * {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}.
+ * {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}
+ * as well as other use cases (such as dimming above a dead window).
*/
-class DimBehindController {
- private static final String TAG = "DimBehindController";
+class DimLayerController {
+ private static final String TAG = "DimLayerController";
/** Amount of time in milliseconds to animate the dim surface from one value to another,
* when no window animation is driving it. */
private static final int DEFAULT_DIM_DURATION = 200;
- // Shared dim layer for fullscreen users. {@link DimBehindState#dimLayer} will point to this
+ /**
+ * The default amount of dim applied over a dead window
+ */
+ private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
+
+ // Shared dim layer for fullscreen users. {@link DimLayerState#dimLayer} will point to this
// instead of creating a new object per fullscreen task on a display.
private DimLayer mSharedFullScreenDimLayer;
- private ArrayMap<DimLayer.DimLayerUser, DimBehindState> mState = new ArrayMap<>();
+ private ArrayMap<DimLayer.DimLayerUser, DimLayerState> mState = new ArrayMap<>();
private DisplayContent mDisplayContent;
private Rect mTmpBounds = new Rect();
- DimBehindController(DisplayContent displayContent) {
+ DimLayerController(DisplayContent displayContent) {
mDisplayContent = displayContent;
}
/** Updates the dim layer bounds, recreating it if needed. */
void updateDimLayer(DimLayer.DimLayerUser dimLayerUser) {
- DimBehindState state = getOrCreateDimBehindState(dimLayerUser);
+ DimLayerState state = getOrCreateDimLayerState(dimLayerUser, false);
final boolean previousFullscreen = state.dimLayer != null
&& state.dimLayer == mSharedFullScreenDimLayer;
DimLayer newDimLayer;
@@ -60,7 +67,7 @@ class DimBehindController {
newDimLayer.setBounds(mTmpBounds);
mSharedFullScreenDimLayer = newDimLayer;
} else if (state.dimLayer != null) {
- state.dimLayer. destroySurface();
+ state.dimLayer.destroySurface();
}
} else {
newDimLayer = (state.dimLayer == null || previousFullscreen)
@@ -72,19 +79,21 @@ class DimBehindController {
state.dimLayer = newDimLayer;
}
- private DimBehindState getOrCreateDimBehindState(DimLayer.DimLayerUser dimLayerUser) {
- if (DEBUG_DIM_LAYER) Slog.v(TAG, "getDimBehindState, dimLayerUser="
+ private DimLayerState getOrCreateDimLayerState(
+ DimLayer.DimLayerUser dimLayerUser, boolean aboveApp) {
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "getOrCreateDimLayerState, dimLayerUser="
+ dimLayerUser.toShortString());
- DimBehindState state = mState.get(dimLayerUser);
+ DimLayerState state = mState.get(dimLayerUser);
if (state == null) {
- state = new DimBehindState();
+ state = new DimLayerState();
mState.put(dimLayerUser, state);
}
+ state.dimAbove = aboveApp;
return state;
}
private void setContinueDimming(DimLayer.DimLayerUser dimLayerUser) {
- DimBehindState state = mState.get(dimLayerUser);
+ DimLayerState state = mState.get(dimLayerUser);
if (state == null) {
if (DEBUG_DIM_LAYER) Slog.w(TAG, "setContinueDimming, no state for: "
+ dimLayerUser.toShortString());
@@ -95,7 +104,7 @@ class DimBehindController {
boolean isDimming() {
for (int i = mState.size() - 1; i >= 0; i--) {
- DimBehindState state = mState.valueAt(i);
+ DimLayerState state = mState.valueAt(i);
if (state.dimLayer != null && state.dimLayer.isDimming()) {
return true;
}
@@ -110,15 +119,15 @@ class DimBehindController {
}
private boolean getContinueDimming(DimLayer.DimLayerUser dimLayerUser) {
- DimBehindState state = mState.get(dimLayerUser);
+ DimLayerState state = mState.get(dimLayerUser);
return state != null && state.continueDimming;
}
void startDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser,
- WindowStateAnimator newWinAnimator) {
+ WindowStateAnimator newWinAnimator, boolean aboveApp) {
// Only set dim params on the highest dimmed layer.
// Don't turn on for an unshown surface, or for any layer but the highest dimmed layer.
- DimBehindState state = getOrCreateDimBehindState(dimLayerUser);
+ DimLayerState state = getOrCreateDimLayerState(dimLayerUser, aboveApp);
if (DEBUG_DIM_LAYER) Slog.v(TAG, "startDimmingIfNeeded,"
+ " dimLayerUser=" + dimLayerUser.toShortString()
+ " newWinAnimator=" + newWinAnimator
@@ -145,7 +154,7 @@ class DimBehindController {
private void stopDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser) {
// No need to check if state is null, we know the key has a value.
- DimBehindState state = mState.get(dimLayerUser);
+ DimLayerState state = mState.get(dimLayerUser);
if (DEBUG_DIM_LAYER) Slog.v(TAG, "stopDimmingIfNeeded,"
+ " dimLayerUser=" + dimLayerUser.toShortString()
+ " state.continueDimming=" + state.continueDimming
@@ -188,7 +197,7 @@ class DimBehindController {
}
private boolean animateDimLayers(DimLayer.DimLayerUser dimLayerUser) {
- DimBehindState state = mState.get(dimLayerUser);
+ DimLayerState state = mState.get(dimLayerUser);
if (DEBUG_DIM_LAYER) Slog.v(TAG, "animateDimLayers,"
+ " dimLayerUser=" + dimLayerUser.toShortString()
+ " state.animator=" + state.animator
@@ -199,8 +208,13 @@ class DimBehindController {
dimLayer = state.dimLayer.getLayer();
dimAmount = 0;
} else {
- dimLayer = state.animator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM;
- dimAmount = state.animator.mWin.mAttrs.dimAmount;
+ if (state.dimAbove) {
+ dimLayer = state.animator.mAnimLayer + LAYER_OFFSET_DIM;
+ dimAmount = DEFAULT_DIM_AMOUNT_DEAD_WINDOW;
+ } else {
+ dimLayer = state.animator.mAnimLayer - LAYER_OFFSET_DIM;
+ dimAmount = state.animator.mWin.mAttrs.dimAmount;
+ }
}
final float targetAlpha = state.dimLayer.getTargetAlpha();
if (targetAlpha != dimAmount) {
@@ -211,7 +225,7 @@ class DimBehindController {
? state.animator.mAnimation.computeDurationHint()
: DEFAULT_DIM_DURATION;
if (targetAlpha > dimAmount) {
- duration = getDimBehindFadeDuration(duration);
+ duration = getDimLayerFadeDuration(duration);
}
state.dimLayer.show(dimLayer, dimAmount, duration);
}
@@ -230,11 +244,11 @@ class DimBehindController {
}
boolean isDimming(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator winAnimator) {
- DimBehindState state = mState.get(dimLayerUser);
+ DimLayerState state = mState.get(dimLayerUser);
return state != null && state.animator == winAnimator && state.dimLayer.isDimming();
}
- private long getDimBehindFadeDuration(long duration) {
+ private long getDimLayerFadeDuration(long duration) {
TypedValue tv = new TypedValue();
mDisplayContent.mService.mContext.getResources().getValue(
com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true);
@@ -248,7 +262,7 @@ class DimBehindController {
void close() {
for (int i = mState.size() - 1; i >= 0; i--) {
- DimBehindState state = mState.valueAt(i);
+ DimLayerState state = mState.valueAt(i);
state.dimLayer.destroySurface();
}
mState.clear();
@@ -256,10 +270,23 @@ class DimBehindController {
}
void removeDimLayerUser(DimLayer.DimLayerUser dimLayerUser) {
- mState.remove(dimLayerUser);
+ DimLayerState state = mState.get(dimLayerUser);
+ if (state != null) {
+ state.dimLayer.destroySurface();
+ mState.remove(dimLayerUser);
+ }
}
void applyDimBehind(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) {
+ applyDim(dimLayerUser, animator, false /* aboveApp */);
+ }
+
+ void applyDimAbove(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) {
+ applyDim(dimLayerUser, animator, true /* aboveApp */);
+ }
+
+ private void applyDim(
+ DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator, boolean aboveApp) {
if (dimLayerUser == null) {
Slog.e(TAG, "Trying to apply dim layer for: " + this
+ ", but no dim layer user found.");
@@ -269,26 +296,27 @@ class DimBehindController {
setContinueDimming(dimLayerUser);
if (!isDimming(dimLayerUser, animator)) {
if (DEBUG_DIM_LAYER) Slog.v(TAG, "Win " + this + " start dimming.");
- startDimmingIfNeeded(dimLayerUser, animator);
+ startDimmingIfNeeded(dimLayerUser, animator, aboveApp);
}
}
}
- private static class DimBehindState {
- // The particular window with FLAG_DIM_BEHIND set. If null, hide dimLayer.
+ private static class DimLayerState {
+ // The particular window requesting a dim layer. If null, hide dimLayer.
WindowStateAnimator animator;
// Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the
// end then stop any dimming.
boolean continueDimming;
DimLayer dimLayer;
+ boolean dimAbove;
}
void dump(String prefix, PrintWriter pw) {
- pw.println(prefix + "DimBehindController");
+ pw.println(prefix + "DimLayerController");
for (int i = 0, n = mState.size(); i < n; i++) {
pw.println(prefix + " " + mState.keyAt(i).toShortString());
pw.print(prefix + " ");
- DimBehindState state = mState.valueAt(i);
+ DimLayerState state = mState.valueAt(i);
pw.print("dimLayer=" + (state.dimLayer == mSharedFullScreenDimLayer ? "shared" :
state.dimLayer));
pw.print(", animator=" + state.animator);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fab8ee55b22c..53f8bbd9084b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -16,14 +16,15 @@
package com.android.server.wm;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
-import static android.app.ActivityManager.HOME_STACK_ID;
-import static android.app.ActivityManager.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerService.TAG;
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
+import android.app.ActivityManager.StackId;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.DisplayMetrics;
@@ -115,7 +116,7 @@ class DisplayContent {
final DockedStackDividerController mDividerControllerLocked;
- final DimBehindController mDimBehindController;
+ final DimLayerController mDimLayerController;
/**
* @param display May not be null.
@@ -130,7 +131,7 @@ class DisplayContent {
mService = service;
initializeDisplayBaseInfo();
mDividerControllerLocked = new DockedStackDividerController(service.mContext, this);
- mDimBehindController = new DimBehindController(this);
+ mDimLayerController = new DimLayerController(this);
}
int getDisplayId() {
@@ -270,7 +271,7 @@ class DisplayContent {
}
void detachStack(TaskStack stack) {
- mDimBehindController.removeDimLayerUser(stack);
+ mDimLayerController.removeDimLayerUser(stack);
mStacks.remove(stack);
}
@@ -311,7 +312,7 @@ class DisplayContent {
final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
TaskStack stack = mStacks.get(stackNdx);
- if (!stack.allowTaskResize()) {
+ if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
break;
}
final ArrayList<Task> tasks = stack.getTasks();
@@ -414,23 +415,23 @@ class DisplayContent {
}
boolean animateDimLayers() {
- return mDimBehindController.animateDimLayers();
+ return mDimLayerController.animateDimLayers();
}
void resetDimming() {
- mDimBehindController.resetDimming();
+ mDimLayerController.resetDimming();
}
boolean isDimming() {
- return mDimBehindController.isDimming();
+ return mDimLayerController.isDimming();
}
void stopDimmingIfNeeded() {
- mDimBehindController.stopDimmingIfNeeded();
+ mDimLayerController.stopDimmingIfNeeded();
}
void close() {
- mDimBehindController.close();
+ mDimLayerController.close();
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
mStacks.get(stackNdx).close();
}
@@ -577,7 +578,7 @@ class DisplayContent {
}
}
pw.println();
- mDimBehindController.dump(prefix + " ", pw);
+ mDimLayerController.dump(prefix + " ", pw);
}
@Override
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 04cba81726ec..eafc3c6beccf 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW;
import static android.view.PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 1f62bc15024e..c47c377f4cb8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -187,6 +187,12 @@ final class Session extends IWindowSession.Stub
mService.removeWindow(this, window);
}
+ @Override
+ public void repositionChild(IWindow window, int x, int y, long deferTransactionUntilFrame,
+ Rect outFrame) {
+ mService.repositionChild(this, window, x, y, deferTransactionUntilFrame, outFrame);
+ }
+
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags,
int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index d4d99af9675d..5864b25781b0 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,22 +16,21 @@
package com.android.server.wm;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.HOME_STACK_ID;
-import static android.app.ActivityManager.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
import static com.android.server.wm.WindowManagerService.TAG;
import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE;
import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
import static com.android.server.wm.WindowManagerService.H.RESIZE_TASK;
-
+import android.app.ActivityManager.StackId;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.EventLog;
import android.util.Slog;
-import android.util.SparseArray;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -117,7 +116,7 @@ class Task implements DimLayer.DimLayerUser {
mDeferRemoval = false;
DisplayContent content = getDisplayContent();
if (content != null) {
- content.mDimBehindController.removeDimLayerUser(this);
+ content.mDimLayerController.removeDimLayerUser(this);
}
mStack.removeTask(this);
mService.mTaskIdToTask.delete(mTaskId);
@@ -221,7 +220,7 @@ class Task implements DimLayer.DimLayerUser {
mBounds.set(bounds);
mRotation = rotation;
if (displayContent != null) {
- displayContent.mDimBehindController.updateDimLayer(this);
+ displayContent.mDimLayerController.updateDimLayer(this);
}
mOverrideConfig = mFullscreen ? Configuration.EMPTY : config;
return boundsChange;
@@ -245,7 +244,7 @@ class Task implements DimLayer.DimLayerUser {
private boolean useCurrentBounds() {
final DisplayContent displayContent = mStack.getDisplayContent();
if (mFullscreen
- || mStack.allowTaskResize()
+ || !StackId.isTaskResizeableByDockedStack(mStack.mStackId)
|| displayContent == null
|| displayContent.getDockedStackLocked() != null) {
return true;
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 227b3f01fac2..aae3bd24439f 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -18,7 +18,7 @@ package com.android.server.wm;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.RESIZE_MODE_USER;
import static android.app.ActivityManager.RESIZE_MODE_USER_FORCED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index df664bd271bd..f72384c24508 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -17,17 +17,16 @@
package com.android.server.wm;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
-import static android.app.ActivityManager.FIRST_STATIC_STACK_ID;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.LAST_STATIC_STACK_ID;
-import static android.app.ActivityManager.PINNED_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static com.android.server.wm.WindowManagerService.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
import static com.android.server.wm.WindowManagerService.TAG;
import android.annotation.IntDef;
+import android.app.ActivityManager.StackId;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Debug;
@@ -122,12 +121,6 @@ public class TaskStack implements DimLayer.DimLayerUser {
}
}
- boolean allowTaskResize() {
- return mStackId == FREEFORM_WORKSPACE_STACK_ID
- || mStackId == DOCKED_STACK_ID
- || mStackId == PINNED_STACK_ID;
- }
-
/**
* Set the bounds of the stack and its containing tasks.
* @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen.
@@ -183,7 +176,7 @@ public class TaskStack implements DimLayer.DimLayerUser {
}
if (mDisplayContent != null) {
- mDisplayContent.mDimBehindController.updateDimLayer(this);
+ mDisplayContent.mDimLayerController.updateDimLayer(this);
mAnimationBackgroundSurface.setBounds(bounds);
}
@@ -203,8 +196,7 @@ public class TaskStack implements DimLayer.DimLayerUser {
/** Return true if the current bound can get outputted to the rest of the system as-is. */
private boolean useCurrentBounds() {
if (mFullscreen
- || mStackId == DOCKED_STACK_ID
- || mStackId == PINNED_STACK_ID
+ || !StackId.isResizeableByDockedStack(mStackId)
|| mDisplayContent == null
|| mDisplayContent.getDockedStackLocked() != null) {
return true;
@@ -396,9 +388,9 @@ public class TaskStack implements DimLayer.DimLayerUser {
Rect bounds = null;
final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
- if (mStackId == DOCKED_STACK_ID || (dockedStack != null && mStackId != PINNED_STACK_ID
- && mStackId >= FIRST_STATIC_STACK_ID && mStackId <= LAST_STATIC_STACK_ID)) {
- // The existence of a docked stack affects the size of any static stack created since
+ if (mStackId == DOCKED_STACK_ID
+ || (dockedStack != null && StackId.isResizeableByDockedStack(mStackId))) {
+ // The existence of a docked stack affects the size of other static stack created since
// the docked stack occupies a dedicated region on screen.
bounds = new Rect();
displayContent.getLogicalDisplayRect(mTmpRect);
@@ -424,10 +416,7 @@ public class TaskStack implements DimLayer.DimLayerUser {
}
void getStackDockedModeBoundsLocked(Rect outBounds) {
- if (mStackId == DOCKED_STACK_ID
- || mStackId == PINNED_STACK_ID
- || mStackId > LAST_STATIC_STACK_ID
- || mDisplayContent == null) {
+ if (!StackId.isResizeableByDockedStack(mStackId) || mDisplayContent == null) {
outBounds.set(mBounds);
return;
}
@@ -537,9 +526,7 @@ public class TaskStack implements DimLayer.DimLayerUser {
for (int i = 0; i < count; i++) {
final TaskStack otherStack = mService.mStackIdToStack.valueAt(i);
final int otherStackId = otherStack.mStackId;
- if (otherStackId != DOCKED_STACK_ID && mStackId != PINNED_STACK_ID
- && otherStackId >= FIRST_STATIC_STACK_ID
- && otherStackId <= LAST_STATIC_STACK_ID) {
+ if (StackId.isResizeableByDockedStack(otherStackId)) {
mService.mH.sendMessage(
mService.mH.obtainMessage(RESIZE_STACK, otherStackId,
1 /*allowResizeInDockedMode*/, bounds));
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 7f2f2cda8128..4a9d8cbdf006 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index bcfc8f22bf15..d5304c213f58 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -17,8 +17,8 @@
package com.android.server.wm;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.ActivityManager.DOCKED_STACK_ID;
-import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
@@ -1924,6 +1924,11 @@ public class WindowManagerService extends IWindowManager.Stub
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
}
+ if (atoken != null && atoken.appDied) {
+ Slog.d(TAG, "App is now revived: " + atoken);
+ atoken.appDied = false;
+ }
+
mPolicy.adjustWindowParamsLw(win.mAttrs);
win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
@@ -1935,11 +1940,7 @@ public class WindowManagerService extends IWindowManager.Stub
final boolean openInputChannels = (outInputChannel != null
&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
if (openInputChannels) {
- String name = win.makeInputChannelName();
- InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
- win.setInputChannel(inputChannels[0]);
- inputChannels[1].transferTo(outInputChannel);
- mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
+ win.openInputChannel(outInputChannel);
}
// From now on, no exceptions or errors allowed!
@@ -2183,13 +2184,31 @@ public class WindowManagerService extends IWindowManager.Stub
+ "added");
win.mExiting = true;
appToken.mReplacingRemoveRequested = true;
+ Binder.restoreCallingIdentity(origId);
return;
}
// If we are not currently running the exit animation, we
// need to see about starting one.
wasVisible = win.isWinVisibleLw();
- if (wasVisible) {
+ if (wasVisible && appToken != null && appToken.appDied) {
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG,
+ "Not removing " + win + " because app died while it's visible");
+
+ win.mAppDied = true;
+ win.setDisplayLayoutNeeded();
+ mWindowPlacerLocked.performSurfacePlacement();
+
+ // Set up a replacement input channel since the app is now dead.
+ // We need to catch tapping on the dead window to restart the app.
+ win.openInputChannel(null);
+ mInputMonitor.updateInputWindowsLw(true /*force*/);
+
+ Binder.restoreCallingIdentity(origId);
+ return;
+ }
+
+ if (wasVisible) {
final int transit = (!startingWindow)
? WindowManagerPolicy.TRANSIT_EXIT
: WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
@@ -2240,10 +2259,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
void removeWindowInnerLocked(WindowState win) {
- removeWindowInnerLocked(win, true);
- }
-
- private void removeWindowInnerLocked(WindowState win, boolean performLayout) {
if (win.mRemoved) {
// Nothing to do.
return;
@@ -2338,9 +2353,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (!mWindowPlacerLocked.isInLayout()) {
assignLayersLocked(windows);
win.setDisplayLayoutNeeded();
- if (performLayout) {
- mWindowPlacerLocked.performSurfacePlacement();
- }
+ mWindowPlacerLocked.performSurfacePlacement();
if (win.mAppToken != null) {
win.mAppToken.updateReportedVisibilityLocked();
}
@@ -2468,6 +2481,54 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ void repositionChild(Session session, IWindow client,
+ int x, int y, long deferTransactionUntilFrame, Rect outFrame) {
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild");
+ long origId = Binder.clearCallingIdentity();
+
+ try {
+ synchronized(mWindowMap) {
+ WindowState win = windowForClientLocked(session, client, false);
+ if (win == null) {
+ return;
+ }
+ if (win.mAttachedWindow == null) {
+ throw new IllegalArgumentException(
+ "repositionChild called but window is not"
+ + "attached to a parent win=" + win);
+ }
+
+ win.mFrame.left = x;
+ win.mFrame.top = y;
+
+ win.mWinAnimator.computeShownFrameLocked();
+
+ if (SHOW_TRANSACTIONS) {
+ Slog.i(TAG, ">>> OPEN TRANSACTION repositionChild");
+ }
+
+ SurfaceControl.openTransaction();
+
+ if (deferTransactionUntilFrame > 0) {
+ win.mWinAnimator.mSurfaceControl.deferTransactionUntil(
+ win.mAttachedWindow.mWinAnimator.mSurfaceControl.getHandle(),
+ deferTransactionUntilFrame);
+ }
+ win.mWinAnimator.setSurfaceBoundariesLocked(false);
+
+ SurfaceControl.closeTransaction();
+ if (SHOW_TRANSACTIONS) {
+ Slog.i(TAG, "<<< CLOSE TRANSACTION repositionChild");
+ }
+
+ outFrame = win.mCompatFrame;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ }
+ }
+
public int relayoutWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, int flags,
@@ -4070,6 +4131,14 @@ public class WindowManagerService extends IWindowManager.Stub
wtoken.waitingToShow = false;
wtoken.hiddenRequested = !visible;
+ if (!visible && wtoken.appDied) {
+ // This app is dead while it was visible, we kept its dead window on screen.
+ // Now that the app is going invisible, we can remove it. It will be restarted
+ // if made visible again.
+ wtoken.appDied = false;
+ wtoken.removeAllWindows();
+ }
+
// If we are preparing an app transition, then delay changing
// the visibility of this token until we execute that transition.
if (okToDisplay() && mAppTransition.isTransitionSet()) {
@@ -8500,7 +8569,7 @@ public class WindowManagerService extends IWindowManager.Stub
final DimLayer.DimLayerUser dimLayerUser = w.getDimLayerUser();
final DisplayContent displayContent = w.getDisplayContent();
if (layerChanged && dimLayerUser != null && displayContent != null &&
- displayContent.mDimBehindController.isDimming(dimLayerUser, winAnimator)) {
+ displayContent.mDimLayerController.isDimming(dimLayerUser, winAnimator)) {
// Force an animation pass just to update the mDimLayer layer.
scheduleAnimationLocked();
}
@@ -8619,6 +8688,13 @@ public class WindowManagerService extends IWindowManager.Stub
+ " dragResizingChanged=" + dragResizingChanged);
}
+ // If it's a dead window left on screen, and the configuration changed,
+ // there is nothing we can do about it. Remove the window now.
+ if (w.mAppToken != null && w.mAppDied) {
+ w.mAppToken.removeAllDeadWindows();
+ return;
+ }
+
w.mLastOverscanInsets.set(w.mOverscanInsets);
w.mLastContentInsets.set(w.mContentInsets);
w.mLastVisibleInsets.set(w.mVisibleInsets);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5bc329e16e65..984a353a2dc5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -340,6 +340,12 @@ final class WindowState implements WindowManagerPolicy.WindowState {
boolean mRemoveOnExit;
/**
+ * Whether the app died while it was visible, if true we might need
+ * to continue to show it until it's restarted.
+ */
+ boolean mAppDied;
+
+ /**
* Set when the orientation is changing and this window has not yet
* been updated for the new orientation.
*/
@@ -362,6 +368,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// Input channel and input window handle used by the input dispatcher.
final InputWindowHandle mInputWindowHandle;
InputChannel mInputChannel;
+ InputChannel mClientChannel;
// Used to improve performance of toString()
String mStringNameCache;
@@ -1274,16 +1281,28 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mConfigHasChanged = false;
}
- void setInputChannel(InputChannel inputChannel) {
+ void openInputChannel(InputChannel outInputChannel) {
if (mInputChannel != null) {
throw new IllegalStateException("Window already has an input channel.");
}
-
- mInputChannel = inputChannel;
- mInputWindowHandle.inputChannel = inputChannel;
+ String name = makeInputChannelName();
+ InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
+ mInputChannel = inputChannels[0];
+ mClientChannel = inputChannels[1];
+ mInputWindowHandle.inputChannel = inputChannels[0];
+ if (outInputChannel != null) {
+ mClientChannel.transferTo(outInputChannel);
+ mClientChannel.dispose();
+ mClientChannel = null;
+ }
+ mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
}
void disposeInputChannel() {
+ if (mClientChannel != null) {
+ mClientChannel.dispose();
+ mClientChannel = null;
+ }
if (mInputChannel != null) {
mService.mInputManager.unregisterInputChannel(mInputChannel);
@@ -1294,10 +1313,13 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mInputWindowHandle.inputChannel = null;
}
- void handleFlagDimBehind() {
- if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && mDisplayContent != null && !mExiting
- && isDisplayedLw()) {
- mDisplayContent.mDimBehindController.applyDimBehind(getDimLayerUser(), mWinAnimator);
+ void applyDimLayerIfNeeded() {
+ if (!mExiting && mAppDied) {
+ // If app died visible, apply a dim over the window to indicate that it's inactive
+ mDisplayContent.mDimLayerController.applyDimAbove(getDimLayerUser(), mWinAnimator);
+ } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0
+ && mDisplayContent != null && !mExiting && isDisplayedLw()) {
+ mDisplayContent.mDimLayerController.applyDimBehind(getDimLayerUser(), mWinAnimator);
}
}
@@ -1375,6 +1397,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
WindowState win = mService.windowForClientLocked(mSession, mClient, false);
Slog.i(TAG, "WIN DEATH: " + win);
if (win != null) {
+ if (win.mAppToken != null && !win.mAppToken.clientHidden) {
+ win.mAppToken.appDied = true;
+ }
mService.removeWindowLocked(win);
} else if (mHasSurface) {
Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
@@ -1574,7 +1599,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
public boolean isDimming() {
final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
return dimLayerUser != null && mDisplayContent != null &&
- mDisplayContent.mDimBehindController.isDimming(dimLayerUser, mWinAnimator);
+ mDisplayContent.mDimLayerController.isDimming(dimLayerUser, mWinAnimator);
}
public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
@@ -1833,7 +1858,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
pw.print(prefix); pw.print("mToken="); pw.println(mToken);
pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
if (mAppToken != null) {
- pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
+ pw.print(prefix); pw.print("mAppToken="); pw.print(mAppToken);
+ pw.print(" mAppDied=");pw.println(mAppDied);
}
if (mTargetAppToken != null) {
pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
@@ -1999,4 +2025,13 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
return mStringNameCache;
}
+
+ void transformFromScreenToSurfaceSpace(Rect rect) {
+ if (mHScale >= 0) {
+ rect.right = rect.left + (int)((rect.right - rect.left) / mHScale);
+ }
+ if (mVScale >= 0) {
+ rect.bottom = rect.top + (int)((rect.bottom - rect.top) / mVScale);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index aa242f1131d3..e9be2ddd9e89 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1223,14 +1223,6 @@ class WindowStateAnimator {
mShownAlpha *= appTransformation.getAlpha();
if (appTransformation.hasClipRect()) {
mClipRect.set(appTransformation.getClipRect());
- if (mWin.mHScale > 0) {
- mClipRect.left /= mWin.mHScale;
- mClipRect.right /= mWin.mHScale;
- }
- if (mWin.mVScale > 0) {
- mClipRect.top /= mWin.mVScale;
- mClipRect.bottom /= mWin.mVScale;
- }
mHasClipRect = true;
}
}
@@ -1350,11 +1342,7 @@ class WindowStateAnimator {
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
// Need to recompute a new system decor rect each time.
- if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
- // Currently can't do this cropping for scaled windows. We'll
- // just keep the crop rect the same as the source surface.
- w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
- } else if (!w.isDefaultDisplay()) {
+ if (!w.isDefaultDisplay()) {
// On a different display there is no system decor. Crop the window
// by the screen boundaries.
w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
@@ -1407,9 +1395,13 @@ class WindowStateAnimator {
clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
// We don't want to clip to stack bounds windows that are currently doing entrance
// animation for docked window, otherwise the animating window will be suddenly cut off.
+
if (!(mAnimator.mAnimating && w.inDockedWorkspace())) {
adjustCropToStackBounds(w, clipRect);
}
+
+ w.transformFromScreenToSurfaceSpace(clipRect);
+
if (!clipRect.equals(mLastClipRect)) {
mLastClipRect.set(clipRect);
try {
@@ -1434,12 +1426,13 @@ class WindowStateAnimator {
private void adjustCropToStackBounds(WindowState w, Rect clipRect) {
final AppWindowToken appToken = w.mAppToken;
+ final Task task = w.getTask();
// We don't apply the the stack bounds to the window that is being replaced, because it was
// living in a different stack. If we suddenly crop it to the new stack bounds, it might
// get cut off. We don't want it to happen, so we let it ignore the stack bounds until it
// gets removed. The window that will replace it will abide them.
- if (appToken != null && appToken.mCropWindowsToStack && !appToken.mWillReplaceWindow) {
- TaskStack stack = w.getTask().mStack;
+ if (task != null && appToken.mCropWindowsToStack && !appToken.mWillReplaceWindow) {
+ TaskStack stack = task.mStack;
stack.getBounds(mTmpStackBounds);
// When we resize we use the big surface approach, which means we can't trust the
// window frame bounds anymore. Instead, the window will be placed at 0, 0, but to avoid
@@ -1551,7 +1544,7 @@ class WindowStateAnimator {
mDsDy * w.mHScale, mDtDy * w.mVScale);
mAnimator.setPendingLayoutChanges(w.getDisplayId(),
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
- w.handleFlagDimBehind();
+ w.applyDimLayerIfNeeded();
} catch (RuntimeException e) {
// If something goes wrong with the surface (such
// as running out of memory), don't take down the
@@ -1867,6 +1860,9 @@ class WindowStateAnimator {
if (mWin.mAttrs.type != TYPE_APPLICATION_STARTING && mWin.mAppToken != null) {
mWin.mAppToken.firstWindowDrawn = true;
+ // We now have a good window to show, remove dead placeholders
+ mWin.mAppToken.removeAllDeadWindows();
+
if (mWin.mAppToken.startingData != null) {
if (WindowManagerService.DEBUG_STARTING_WINDOW ||
WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index aca0f5b6de39..eef8e17ab0fd 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -670,7 +670,7 @@ class WindowSurfacePlacer {
handleNotObscuredLocked(w, innerDw, innerDh);
}
- w.handleFlagDimBehind();
+ w.applyDimLayerIfNeeded();
if (isDefaultDisplay && obscuredChanged
&& mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) {
@@ -781,7 +781,7 @@ class WindowSurfacePlacer {
+ " a=" + winAnimator.mAnimating);
}
}
- if (w != atoken.startingWindow) {
+ if (w != atoken.startingWindow && !w.mAppDied) {
if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
atoken.numInterestingWindows++;
if (w.isDrawnLw()) {
diff --git a/services/core/jni/com_android_server_UsbMidiDevice.cpp b/services/core/jni/com_android_server_UsbMidiDevice.cpp
index 06b9bc3c01ec..e12a01661a44 100644
--- a/services/core/jni/com_android_server_UsbMidiDevice.cpp
+++ b/services/core/jni/com_android_server_UsbMidiDevice.cpp
@@ -43,12 +43,26 @@ android_server_UsbMidiDevice_get_subdevice_count(JNIEnv *env, jobject /* thiz */
jint card, jint device)
{
char path[100];
+ int fd;
+ const int kMaxRetries = 10;
+ const int kSleepMicroseconds = 2000;
snprintf(path, sizeof(path), "/dev/snd/controlC%d", card);
- int fd = open(path, O_RDWR);
- if (fd < 0) {
- ALOGE("could not open %s", path);
- return 0;
+ // This control device may not have been created yet. So we should
+ // try to open it several times to prevent intermittent failure
+ // from a race condition.
+ int retryCounter = 0;
+ while ((fd = open(path, O_RDWR)) < 0) {
+ if (++retryCounter > kMaxRetries) {
+ ALOGE("timed out after %d tries, could not open %s", retryCounter, path);
+ return 0;
+ } else {
+ ALOGW("attempt #%d, could not open %s", retryCounter, path);
+ // Increase the sleep interval each time.
+ // 10 retries will total 2 * sum(1..10) = 110 milliseconds.
+ // Typically the device should be ready in 5-10 milliseconds.
+ usleep(kSleepMicroseconds * retryCounter);
+ }
}
struct snd_rawmidi_info info;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b4c8f966ba71..aea2ecf68858 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1016,6 +1016,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ // DO NOT call it while taking the "this" lock, which could cause a dead lock.
private void handlePackagesChanged(String packageName, int userHandle) {
boolean removed = false;
if (VERBOSE_LOG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
@@ -1042,7 +1043,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
if (removed) {
validatePasswordOwnerLocked(policy);
- syncDeviceCapabilitiesLocked(policy);
saveSettingsLocked(policy.mUserHandle);
}
@@ -1061,6 +1061,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
}
+ if (removed) {
+ synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
+ synchronized (DevicePolicyManagerService.this) {
+ mUserManagerInternal.updateEffectiveUserRestrictionsLR(userHandle);
+ }
+ }
+ }
}
/**
@@ -1682,7 +1689,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) {
+ void removeActiveAdminLocked(final ComponentName adminReceiver, final int userHandle) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (admin != null) {
synchronized (this) {
@@ -1701,7 +1708,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
policy.mAdminList.remove(admin);
policy.mAdminMap.remove(adminReceiver);
validatePasswordOwnerLocked(policy);
- syncDeviceCapabilitiesLocked(policy);
if (doProxyCleanup) {
resetGlobalProxyLocked(getUserData(userHandle));
}
@@ -1709,6 +1715,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
updateMaximumTimeToLockLocked(policy);
policy.mRemovingAdmins.remove(adminReceiver);
}
+ synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
+ synchronized (DevicePolicyManagerService.this) {
+ mUserManagerInternal.updateEffectiveUserRestrictionsLR(
+ userHandle);
+ }
+ }
}
});
}
@@ -2022,7 +2034,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
validatePasswordOwnerLocked(policy);
- syncDeviceCapabilitiesLocked(policy);
updateMaximumTimeToLockLocked(policy);
updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
if (policy.mStatusBarDisabled) {
@@ -2089,31 +2100,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- /**
- * Pushes down policy information to the system for any policies related to general device
- * capabilities that need to be enforced by lower level services (e.g. Camera services).
- */
- void syncDeviceCapabilitiesLocked(DevicePolicyData policy) {
- // Ensure the status of the camera is synced down to the system. Interested native services
- // should monitor this value and act accordingly.
- String cameraPropertyForUser = SYSTEM_PROP_DISABLE_CAMERA_PREFIX + policy.mUserHandle;
- boolean systemState = mInjector.systemPropertiesGetBoolean(cameraPropertyForUser, false);
- boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle);
- if (cameraDisabled != systemState) {
- long token = mInjector.binderClearCallingIdentity();
- try {
- String value = cameraDisabled ? "1" : "0";
- if (VERBOSE_LOG) {
- Slog.v(LOG_TAG, "Change in camera state ["
- + cameraPropertyForUser + "] = " + value);
- }
- mInjector.systemPropertiesSet(cameraPropertyForUser, value);
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
- }
- }
-
@VisibleForTesting
void systemReady(int phase) {
if (!mHasFeature) {
@@ -4329,13 +4315,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
/**
- * The system property used to share the state of the camera. The native camera service
- * is expected to read this property and act accordingly. The userId should be appended
- * to this key.
- */
- public static final String SYSTEM_PROP_DISABLE_CAMERA_PREFIX = "sys.secpolicy.camera.off_";
-
- /**
* Disables all device cameras according to the specified admin.
*/
@Override
@@ -4352,7 +4331,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ap.disableCamera = disabled;
saveSettingsLocked(userHandle);
}
- syncDeviceCapabilitiesLocked(getUserData(userHandle));
+ }
+ // Tell the user manager that the restrictions have changed.
+ synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
+ synchronized (this) {
+ if (isDeviceOwner(who)) {
+ mUserManagerInternal.updateEffectiveUserRestrictionsForAllUsersLR();
+ } else {
+ mUserManagerInternal.updateEffectiveUserRestrictionsLR(userHandle);
+ }
+ }
}
}
@@ -4370,7 +4358,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
return (admin != null) ? admin.disableCamera : false;
}
+ // First, see if DO has set it. If so, it's device-wide.
+ final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
+ if (deviceOwner != null && deviceOwner.disableCamera) {
+ return true;
+ }
+ // Then check each device admin on the user.
DevicePolicyData policy = getUserData(userHandle);
// Determine whether or not the device camera is disabled for any active admins.
final int N = policy.mAdminList.size();
@@ -4404,7 +4398,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ap.disabledKeyguardFeatures = which;
saveSettingsLocked(userHandle);
}
- syncDeviceCapabilitiesLocked(getUserData(userHandle));
}
}
@@ -4657,7 +4650,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
0 /* flagValues */, userHandle.getIdentifier());
// TODO This will not revert audio mute restrictions if they were set. b/24981972
synchronized (mUserManagerInternal.getUserRestrictionsLock()) {
- mUserManagerInternal.updateEffectiveUserRestrictionsRL(userHandle.getIdentifier());
+ mUserManagerInternal.updateEffectiveUserRestrictionsLR(userHandle.getIdentifier());
}
} catch (RemoteException re) {
} finally {
@@ -5036,7 +5029,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
saveSettingsLocked(userHandle);
- syncDeviceCapabilitiesLocked(getUserData(userHandle));
}
}
@@ -5602,6 +5594,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ // DO NOT call it while taking the "this" lock, which could cause a dead lock.
@Override
public void setUserRestriction(ComponentName who, String key, boolean enabledFromThisOwner) {
Preconditions.checkNotNull(who, "ComponentName is null");
@@ -5612,7 +5605,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ActiveAdmin activeAdmin =
getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- boolean isDeviceOwner = isDeviceOwner(who);
+ final boolean isDeviceOwner = isDeviceOwner(who);
if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM
&& DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
throw new SecurityException(
@@ -5624,9 +5617,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final long id = mInjector.binderClearCallingIdentity();
try {
- // Original value.
- final boolean alreadyRestricted = mUserManager.hasUserRestriction(key, user);
-
// Save the restriction to ActiveAdmin.
// TODO When DO sets a restriction, it'll always be treated as device-wide.
// If there'll be a policy that can be set by both, we'll need scoping support,
@@ -5635,85 +5625,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
activeAdmin.ensureUserRestrictions().putBoolean(key, enabledFromThisOwner);
saveSettingsLocked(userHandle);
- // Tell UserManager the new value. Note this needs to be done before calling
- // into AudioService, because AS will check AppOps that'll be updated by UM.
+ // Tell UserManager the new value.
if (isDeviceOwner) {
- mUserManagerInternal.updateEffectiveUserRestrictionsForAllUsersRL();
+ mUserManagerInternal.updateEffectiveUserRestrictionsForAllUsersLR();
} else {
- mUserManagerInternal.updateEffectiveUserRestrictionsRL(userHandle);
+ mUserManagerInternal.updateEffectiveUserRestrictionsLR(userHandle);
}
-
- // New value.
- final boolean enabled = mUserManager.hasUserRestriction(key, user);
-
- // TODO The rest of the code should move to UserManagerService.
-
- if (enabled && !alreadyRestricted) {
- if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
- mInjector.getIAudioService()
- .setMicrophoneMute(true, mContext.getPackageName(), userHandle);
- } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
- mInjector.getIAudioService()
- .setMasterMute(true, 0, mContext.getPackageName(), userHandle);
- } else if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
- mInjector.settingsSecurePutIntForUser(
- Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
- userHandle);
- } else if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
- mInjector.settingsSecurePutIntForUser(
- Settings.Secure.LOCATION_MODE,
- Settings.Secure.LOCATION_MODE_OFF,
- userHandle);
- mInjector.settingsSecurePutStringForUser(
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
- userHandle);
- } else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) {
- // Only disable adb if changing for system user, since it is global
- // TODO: should this be admin user?
- if (userHandle == UserHandle.USER_SYSTEM) {
- mInjector.settingsGlobalPutStringForUser(
- Settings.Global.ADB_ENABLED, "0", userHandle);
- }
- } else if (UserManager.ENSURE_VERIFY_APPS.equals(key)) {
- mInjector.settingsGlobalPutStringForUser(
- Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
- userHandle);
- mInjector.settingsGlobalPutStringForUser(
- Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
- userHandle);
- } else if (UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES.equals(key)) {
- mInjector.settingsSecurePutIntForUser(
- Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
- userHandle);
- }
- }
-
- if (enabled != alreadyRestricted) {
- if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
- // Send out notifications however as some clients may want to reread the
- // value which actually changed due to a restriction having been
- // applied.
- final String property = Settings.Secure.SYS_PROP_SETTING_VERSION;
- long version = mInjector.systemPropertiesGetLong(property, 0) + 1;
- mInjector.systemPropertiesSet(property, Long.toString(version));
-
- final String name = Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
- Uri url = Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
- mContext.getContentResolver().notifyChange(url, null, true, userHandle);
- }
- }
- if (!enabled && alreadyRestricted) {
- if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
- mInjector.getIAudioService()
- .setMicrophoneMute(false, mContext.getPackageName(),
- userHandle);
- } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
- mInjector.getIAudioService()
- .setMasterMute(false, 0, mContext.getPackageName(), userHandle);
- }
- }
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
@@ -6463,8 +6380,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
deviceOwner == null ? null : deviceOwner.userRestrictions;
final Bundle profileOwnerRestrictions =
profileOwner == null ? null : profileOwner.userRestrictions;
+ final boolean cameraDisabled = getCameraDisabled(null, userId);
- if (deviceOwnerRestrictions == null && profileOwnerRestrictions == null) {
+ if (deviceOwnerRestrictions == null && profileOwnerRestrictions == null
+ && !cameraDisabled) {
// No restrictions to merge.
return inBundle;
}
@@ -6473,6 +6392,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
UserRestrictionsUtils.merge(composed, deviceOwnerRestrictions);
UserRestrictionsUtils.merge(composed, profileOwnerRestrictions);
+ // Also merge in the camera restriction.
+ if (cameraDisabled) {
+ composed.putBoolean(UserManager.DISALLOW_CAMERA, true);
+ }
+
return composed;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
index eb7eb15a491a..9e701385d59d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -46,11 +46,11 @@ public class UserManagerServiceTest extends AndroidTestCase {
public void testWriteReadApplicationRestrictions() throws IOException {
AtomicFile atomicFile = new AtomicFile(restrictionsFile);
Bundle bundle = createBundle();
- UserManagerService.writeApplicationRestrictionsLocked(bundle, atomicFile);
+ UserManagerService.writeApplicationRestrictionsLP(bundle, atomicFile);
assertTrue(atomicFile.getBaseFile().exists());
String s = FileUtils.readTextFile(restrictionsFile, 10000, "");
System.out.println("restrictionsFile: " + s);
- bundle = UserManagerService.readApplicationRestrictionsLocked(atomicFile);
+ bundle = UserManagerService.readApplicationRestrictionsLP(atomicFile);
System.out.println("readApplicationRestrictionsLocked bundle: " + bundle);
assertBundle(bundle);
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 13e600ef30e7..013154b39242 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -385,9 +385,11 @@ public class UsageStatsService extends SystemService implements
timeNow);
final int packageCount = packages.size();
for (int p = 0; p < packageCount; p++) {
- final String packageName = packages.get(p).packageName;
- final boolean isIdle = isAppIdleFiltered(packageName, userId, service, timeNow,
- screenOnTime);
+ final PackageInfo pi = packages.get(p);
+ final String packageName = pi.packageName;
+ final boolean isIdle = isAppIdleFiltered(packageName,
+ UserHandle.getAppId(pi.applicationInfo.uid),
+ userId, service, timeNow, screenOnTime);
mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
userId, isIdle ? 1 : 0, packageName));
mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow);
@@ -769,10 +771,17 @@ public class UsageStatsService extends SystemService implements
if (mAppIdleParoled) {
return false;
}
- return isAppIdleFiltered(packageName, userId, timeNow);
+ try {
+ ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(packageName,
+ PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_DISABLED_COMPONENTS);
+ return isAppIdleFiltered(packageName, ai.uid, userId, timeNow);
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ return false;
}
- boolean isAppIdleFiltered(String packageName, int userId, long timeNow) {
+ boolean isAppIdleFiltered(String packageName, int uidForAppId, int userId, long timeNow) {
final UserUsageStatsService userService;
final long screenOnTime;
synchronized (mLock) {
@@ -782,7 +791,8 @@ public class UsageStatsService extends SystemService implements
userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
screenOnTime = getScreenOnTimeLocked(timeNow);
}
- return isAppIdleFiltered(packageName, userId, userService, timeNow, screenOnTime);
+ return isAppIdleFiltered(packageName, UserHandle.getAppId(uidForAppId), userId,
+ userService, timeNow, screenOnTime);
}
/**
@@ -791,14 +801,22 @@ public class UsageStatsService extends SystemService implements
* This happens if the device is plugged in or temporarily allowed to make exceptions.
* Called by interface impls.
*/
- private boolean isAppIdleFiltered(String packageName, int userId,
+ private boolean isAppIdleFiltered(String packageName, int appId, int userId,
UserUsageStatsService userService, long timeNow, long screenOnTime) {
if (packageName == null) return false;
// If not enabled at all, of course nobody is ever idle.
if (!mAppIdleEnabled) {
return false;
}
- if (packageName.equals("android")) return false;
+ if (appId < Process.FIRST_APPLICATION_UID) {
+ // System uids never go idle.
+ return false;
+ }
+ if (packageName.equals("android")) {
+ // Nor does the framework (which should be redundant with the above, but for MR1 we will
+ // 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
@@ -865,8 +883,8 @@ public class UsageStatsService extends SystemService implements
ApplicationInfo ai = apps.get(i);
// Check whether this app is idle.
- boolean idle = isAppIdleFiltered(ai.packageName, userId, userService, timeNow,
- screenOnTime);
+ boolean idle = isAppIdleFiltered(ai.packageName, UserHandle.getAppId(ai.uid),
+ userId, userService, timeNow, screenOnTime);
int index = uidStates.indexOfKey(ai.uid);
if (index < 0) {
@@ -1352,8 +1370,8 @@ public class UsageStatsService extends SystemService implements
}
@Override
- public boolean isAppIdle(String packageName, int userId) {
- return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1);
+ public boolean isAppIdle(String packageName, int uidForAppId, int userId) {
+ return UsageStatsService.this.isAppIdleFiltered(packageName, uidForAppId, userId, -1);
}
@Override
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index e11c8d3acc43..d1d6e0dcdece 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -332,9 +332,24 @@ public class SubscriptionInfo implements Parcelable {
return 0;
}
+ /**
+ * @hide
+ */
+ public static String givePrintableIccid(String iccId) {
+ String iccIdToPrint = null;
+ if (iccId != null) {
+ if (iccId.length() > 9) {
+ iccIdToPrint = iccId.substring(0, 9) + "XXXXXXXXXXX";
+ } else {
+ iccIdToPrint = iccId;
+ }
+ }
+ return iccIdToPrint;
+ }
+
@Override
public String toString() {
- String iccIdToPrint = mIccId != null ? mIccId.substring(0, 9) + "XXXXXXXXXXX" : null;
+ String iccIdToPrint = givePrintableIccid(mIccId);
return "{id=" + mId + ", iccId=" + iccIdToPrint + " simSlotIndex=" + mSimSlotIndex
+ " displayName=" + mDisplayName + " carrierName=" + mCarrierName
+ " nameSource=" + mNameSource + " iconTint=" + mIconTint
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index 861a37990629..5f84e0ce353a 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -188,6 +188,20 @@ public class ImsCallProfile implements Parcelable {
public static final String EXTRA_CODEC = "Codec";
public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
+
+ /**
+ * Extra key which the RIL can use to indicate the radio technology used for a call.
+ * Valid values are:
+ * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_LTE},
+ * {@link android.telephony.ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}, and the other defined
+ * {@code RIL_RADIO_TECHNOLOGY_*} constants.
+ * Note: Despite the fact the {@link android.telephony.ServiceState} values are integer
+ * constants, the values passed for the {@link #EXTRA_CALL_RAT_TYPE} should be strings (e.g.
+ * "14" vs (int) 14).
+ * Note: This is used by {@link com.android.internal.telephony.imsphone.ImsPhoneConnection#
+ * updateWifiStateFromExtras(Bundle)} to determine whether to set the
+ * {@link android.telecom.Connection#CAPABILITY_WIFI} capability on a connection.
+ */
public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
public int mServiceType;
diff --git a/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java b/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java
index b4e0c707d3f3..4771b6cfc750 100644
--- a/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java
+++ b/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionMeasuringActivity.java
@@ -24,6 +24,7 @@ import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -95,11 +96,9 @@ public class SurfaceCompositionMeasuringActivity extends Activity implements OnC
private boolean mResumed;
// Drop one frame per half second.
- // TODO(khmel)
- // Add a feature flag and set the target FPS dependent on the target system as e.g.:
- // 59FPS for MULTI_WINDOW and 54 otherwise (to satisfy the default lax Android requirements).
private double mRefreshRate;
private double mTargetFPS;
+ private boolean mAndromeda;
private int mWidth;
private int mHeight;
@@ -182,6 +181,10 @@ public class SurfaceCompositionMeasuringActivity extends Activity implements OnC
return score;
}
+ public boolean isAndromeda() {
+ return mAndromeda;
+ }
+
@Override
public void onClick(View view) {
if (view == mMeasureCompositionButton) {
@@ -247,6 +250,9 @@ public class SurfaceCompositionMeasuringActivity extends Activity implements OnC
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ // Detect Andromeda devices by having free-form window management feature.
+ mAndromeda = getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT);
detectRefreshRate();
// To layouts in parent. First contains list of Surfaces and second
@@ -513,7 +519,8 @@ public class SurfaceCompositionMeasuringActivity extends Activity implements OnC
}
MemoryInfo memInfo = getMemoryInfo();
- String info = "Available " +
+ String platformName = mAndromeda ? "Andromeda" : "Android";
+ String info = platformName + ": available " +
getReadableMemory(memInfo.availMem) + " from " +
getReadableMemory(memInfo.totalMem) + ".\nVisible " +
visibleCnt + " from " + mViews.size() + " " +
diff --git a/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionTest.java b/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionTest.java
index 3f04888da637..388f91a2c3fb 100644
--- a/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionTest.java
+++ b/tests/SurfaceComposition/src/android/surfacecomposition/SurfaceCompositionTest.java
@@ -17,6 +17,7 @@ package android.surfacecomposition;
import android.app.Activity;
import android.graphics.PixelFormat;
+import android.os.Build;
import android.os.Bundle;
import android.surfacecomposition.SurfaceCompositionMeasuringActivity.AllocationScore;
import android.surfacecomposition.SurfaceCompositionMeasuringActivity.CompositorScore;
@@ -44,11 +45,16 @@ public class SurfaceCompositionTest extends
PixelFormat.OPAQUE,
};
- // Based on Nexus 9 performance which is usually < 9.0.
- private final static double[] MIN_ACCEPTED_COMPOSITION_SCORE = new double[] {
+ // Nexus 9 performance is around 8.8. We distinguish results for Andromeda and
+ // Android devices. Andromeda devices require higher performance score.
+ private final static double[] MIN_ACCEPTED_COMPOSITION_SCORE_ANDROMDEDA = new double[] {
8.0,
8.0,
};
+ private final static double[] MIN_ACCEPTED_COMPOSITION_SCORE_ANDROID = new double[] {
+ 4.0,
+ 4.0,
+ };
// Based on Nexus 6 performance which is usually < 28.0.
private final static double[] MIN_ACCEPTED_ALLOCATION_SCORE = new double[] {
@@ -66,6 +72,8 @@ public class SurfaceCompositionTest extends
@SmallTest
public void testSurfaceCompositionPerformance() {
Bundle status = new Bundle();
+ double[] minScores = getActivity().isAndromeda() ?
+ MIN_ACCEPTED_COMPOSITION_SCORE_ANDROMDEDA : MIN_ACCEPTED_COMPOSITION_SCORE_ANDROID;
for (int i = 0; i < TEST_PIXEL_FORMATS.length; ++i) {
int pixelFormat = TEST_PIXEL_FORMATS[i];
String formatName = SurfaceCompositionMeasuringActivity.getPixelFormatInfo(pixelFormat);
@@ -73,8 +81,8 @@ public class SurfaceCompositionTest extends
Log.i(TAG, "testSurfaceCompositionPerformance(" + formatName + ") = " + score);
assertTrue("Device does not support surface(" + formatName + ") composition " +
"performance score. " + score.mSurfaces + " < " +
- MIN_ACCEPTED_COMPOSITION_SCORE[i] + ".",
- score.mSurfaces >= MIN_ACCEPTED_COMPOSITION_SCORE[i]);
+ minScores[i] + ". Build: " + Build.FINGERPRINT + ".",
+ score.mSurfaces >= minScores[i]);
// Send status only for TRANSLUCENT format.
if (pixelFormat == PixelFormat.TRANSLUCENT) {
status.putDouble(KEY_SURFACE_COMPOSITION_PERFORMANCE, score.mSurfaces);
@@ -96,7 +104,8 @@ public class SurfaceCompositionTest extends
Log.i(TAG, "testSurfaceAllocationPerformance(" + formatName + ") = " + score);
assertTrue("Device does not support surface(" + formatName + ") allocation " +
"performance score. " + score.mMedian + " < " +
- MIN_ACCEPTED_ALLOCATION_SCORE[i] + ".",
+ MIN_ACCEPTED_ALLOCATION_SCORE[i] + ". Build: " +
+ Build.FINGERPRINT + ".",
score.mMedian >= MIN_ACCEPTED_ALLOCATION_SCORE[i]);
// Send status only for TRANSLUCENT format.
if (pixelFormat == PixelFormat.TRANSLUCENT) {
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index 275476cb2081..ceed21edeb1b 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -32,6 +32,7 @@ sources := \
flatten/TableFlattener.cpp \
flatten/XmlFlattener.cpp \
link/AutoVersioner.cpp \
+ link/ManifestFixer.cpp \
link/PrivateAttributeMover.cpp \
link/ReferenceLinker.cpp \
link/TableMerger.cpp \
@@ -45,9 +46,11 @@ sources := \
ConfigDescription.cpp \
Debug.cpp \
Flags.cpp \
- JavaClassGenerator.cpp \
+ java/AnnotationProcessor.cpp \
+ java/JavaClassGenerator.cpp \
+ java/ManifestClassGenerator.cpp \
+ java/ProguardRules.cpp \
Locale.cpp \
- ProguardRules.cpp \
Resource.cpp \
ResourceParser.cpp \
ResourceTable.cpp \
@@ -65,6 +68,7 @@ testSources := \
flatten/TableFlattener_test.cpp \
flatten/XmlFlattener_test.cpp \
link/AutoVersioner_test.cpp \
+ link/ManifestFixer_test.cpp \
link/PrivateAttributeMover_test.cpp \
link/ReferenceLinker_test.cpp \
link/TableMerger_test.cpp \
@@ -76,7 +80,8 @@ testSources := \
util/StringPiece_test.cpp \
util/Util_test.cpp \
ConfigDescription_test.cpp \
- JavaClassGenerator_test.cpp \
+ java/JavaClassGenerator_test.cpp \
+ java/ManifestClassGenerator_test.cpp \
Locale_test.cpp \
Resource_test.cpp \
ResourceParser_test.cpp \
@@ -110,7 +115,7 @@ else
endif
cFlags := -Wall -Werror -Wno-unused-parameter -UNDEBUG
-cppFlags := -std=c++11 -Wno-missing-field-initializers -fno-exceptions
+cppFlags := -std=c++11 -Wno-missing-field-initializers -fno-exceptions -fno-rtti
# ==========================================================
# Build the host static library: libaapt2
diff --git a/tools/aapt2/ConfigDescription.cpp b/tools/aapt2/ConfigDescription.cpp
index 8120fa709b3c..64353deb204d 100644
--- a/tools/aapt2/ConfigDescription.cpp
+++ b/tools/aapt2/ConfigDescription.cpp
@@ -164,6 +164,26 @@ static bool parseScreenLayoutLong(const char* name, ResTable_config* out) {
return false;
}
+static bool parseScreenRound(const char* name, ResTable_config* out) {
+ if (strcmp(name, kWildcardName) == 0) {
+ if (out) out->screenLayout2 =
+ (out->screenLayout2&~ResTable_config::MASK_SCREENROUND)
+ | ResTable_config::SCREENROUND_ANY;
+ return true;
+ } else if (strcmp(name, "round") == 0) {
+ if (out) out->screenLayout2 =
+ (out->screenLayout2&~ResTable_config::MASK_SCREENROUND)
+ | ResTable_config::SCREENROUND_YES;
+ return true;
+ } else if (strcmp(name, "notround") == 0) {
+ if (out) out->screenLayout2 =
+ (out->screenLayout2&~ResTable_config::MASK_SCREENROUND)
+ | ResTable_config::SCREENROUND_NO;
+ return true;
+ }
+ return false;
+}
+
static bool parseOrientation(const char* name, ResTable_config* out) {
if (strcmp(name, kWildcardName) == 0) {
if (out) out->orientation = out->ORIENTATION_ANY;
@@ -635,6 +655,13 @@ bool ConfigDescription::parse(const StringPiece& str, ConfigDescription* out) {
}
}
+ if (parseScreenRound(partIter->c_str(), &config)) {
+ ++partIter;
+ if (partIter == partsEnd) {
+ goto success;
+ }
+ }
+
if (parseOrientation(partIter->c_str(), &config)) {
++partIter;
if (partIter == partsEnd) {
@@ -725,7 +752,9 @@ success:
void ConfigDescription::applyVersionForCompatibility(ConfigDescription* config) {
uint16_t minSdk = 0;
- if (config->density == ResTable_config::DENSITY_ANY) {
+ if (config->screenLayout2 & ResTable_config::MASK_SCREENROUND) {
+ minSdk = SDK_MARSHMALLOW;
+ } else if (config->density == ResTable_config::DENSITY_ANY) {
minSdk = SDK_LOLLIPOP;
} else if (config->smallestScreenWidthDp != ResTable_config::SCREENWIDTH_ANY
|| config->screenWidthDp != ResTable_config::SCREENWIDTH_ANY
diff --git a/tools/aapt2/ConfigDescription_test.cpp b/tools/aapt2/ConfigDescription_test.cpp
index 83708165a6d7..e68d6be536df 100644
--- a/tools/aapt2/ConfigDescription_test.cpp
+++ b/tools/aapt2/ConfigDescription_test.cpp
@@ -15,6 +15,8 @@
*/
#include "ConfigDescription.h"
+#include "SdkConstants.h"
+
#include "util/StringPiece.h"
#include <gtest/gtest.h>
@@ -79,4 +81,19 @@ TEST(ConfigDescriptionTest, ParseCarAttribute) {
EXPECT_EQ(android::ResTable_config::UI_MODE_TYPE_CAR, config.uiMode);
}
+TEST(ConfigDescriptionTest, TestParsingRoundQualifier) {
+ ConfigDescription config;
+ EXPECT_TRUE(TestParse("round", &config));
+ EXPECT_EQ(android::ResTable_config::SCREENROUND_YES,
+ config.screenLayout2 & android::ResTable_config::MASK_SCREENROUND);
+ EXPECT_EQ(SDK_MARSHMALLOW, config.sdkVersion);
+ EXPECT_EQ(std::string("round-v23"), config.toString().string());
+
+ EXPECT_TRUE(TestParse("notround", &config));
+ EXPECT_EQ(android::ResTable_config::SCREENROUND_NO,
+ config.screenLayout2 & android::ResTable_config::MASK_SCREENROUND);
+ EXPECT_EQ(SDK_MARSHMALLOW, config.sdkVersion);
+ EXPECT_EQ(std::string("notround-v23"), config.toString().string());
+}
+
} // namespace aapt
diff --git a/tools/aapt2/Flags.cpp b/tools/aapt2/Flags.cpp
index 6ae5af7bb92a..9435396991df 100644
--- a/tools/aapt2/Flags.cpp
+++ b/tools/aapt2/Flags.cpp
@@ -16,6 +16,7 @@
#include "Flags.h"
#include "util/StringPiece.h"
+#include "util/Util.h"
#include <iomanip>
#include <iostream>
@@ -94,7 +95,14 @@ void Flags::usage(const StringPiece& command, std::ostream* out) {
if (flag.numArgs > 0) {
argLine += " arg";
}
- *out << " " << std::setw(30) << std::left << argLine << flag.description << "\n";
+
+ // Split the description by newlines and write out the argument (which is empty after
+ // the first line) followed by the description line. This will make sure that multiline
+ // descriptions are still right justified and aligned.
+ for (StringPiece line : util::tokenize<char>(flag.description, '\n')) {
+ *out << " " << std::setw(30) << std::left << argLine << line << "\n";
+ argLine = " ";
+ }
}
*out << " " << std::setw(30) << std::left << "-h" << "Displays this help menu\n";
out->flush();
diff --git a/tools/aapt2/ManifestValidator.cpp b/tools/aapt2/ManifestValidator.cpp
deleted file mode 100644
index 9f971fbcf728..000000000000
--- a/tools/aapt2/ManifestValidator.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "Logger.h"
-#include "ManifestValidator.h"
-#include "util/Maybe.h"
-#include "Source.h"
-#include "util/Util.h"
-
-#include <androidfw/ResourceTypes.h>
-
-namespace aapt {
-
-ManifestValidator::ManifestValidator(const android::ResTable& table)
-: mTable(table) {
-}
-
-bool ManifestValidator::validate(const Source& source, android::ResXMLParser* parser) {
- SourceLogger logger(source);
-
- android::ResXMLParser::event_code_t code;
- while ((code = parser->next()) != android::ResXMLParser::END_DOCUMENT &&
- code != android::ResXMLParser::BAD_DOCUMENT) {
- if (code != android::ResXMLParser::START_TAG) {
- continue;
- }
-
- size_t len = 0;
- const StringPiece16 namespaceUri(parser->getElementNamespace(&len), len);
- if (!namespaceUri.empty()) {
- continue;
- }
-
- const StringPiece16 name(parser->getElementName(&len), len);
- if (name.empty()) {
- logger.error(parser->getLineNumber())
- << "failed to get the element name."
- << std::endl;
- return false;
- }
-
- if (name == u"manifest") {
- if (!validateManifest(source, parser)) {
- return false;
- }
- }
- }
- return true;
-}
-
-Maybe<StringPiece16> ManifestValidator::getAttributeValue(android::ResXMLParser* parser,
- size_t idx) {
- android::Res_value value;
- if (parser->getAttributeValue(idx, &value) < 0) {
- return StringPiece16();
- }
-
- const android::ResStringPool* pool = &parser->getStrings();
- if (value.dataType == android::Res_value::TYPE_REFERENCE) {
- ssize_t strIdx = mTable.resolveReference(&value, 0x10000000u);
- if (strIdx < 0) {
- return {};
- }
- pool = mTable.getTableStringBlock(strIdx);
- }
-
- if (value.dataType != android::Res_value::TYPE_STRING || !pool) {
- return {};
- }
- return util::getString(*pool, value.data);
-}
-
-Maybe<StringPiece16> ManifestValidator::getAttributeInlineValue(android::ResXMLParser* parser,
- size_t idx) {
- android::Res_value value;
- if (parser->getAttributeValue(idx, &value) < 0) {
- return StringPiece16();
- }
-
- if (value.dataType != android::Res_value::TYPE_STRING) {
- return {};
- }
- return util::getString(parser->getStrings(), value.data);
-}
-
-bool ManifestValidator::validateInlineAttribute(android::ResXMLParser* parser, size_t idx,
- SourceLogger& logger,
- const StringPiece16& charSet) {
- size_t len = 0;
- StringPiece16 element(parser->getElementName(&len), len);
- StringPiece16 attributeName(parser->getAttributeName(idx, &len), len);
- Maybe<StringPiece16> result = getAttributeInlineValue(parser, idx);
- if (!result) {
- logger.error(parser->getLineNumber())
- << "<"
- << element
- << "> must have a '"
- << attributeName
- << "' attribute with a string literal value."
- << std::endl;
- return false;
- }
- return validateAttributeImpl(element, attributeName, result.value(), charSet,
- parser->getLineNumber(), logger);
-}
-
-bool ManifestValidator::validateAttribute(android::ResXMLParser* parser, size_t idx,
- SourceLogger& logger, const StringPiece16& charSet) {
- size_t len = 0;
- StringPiece16 element(parser->getElementName(&len), len);
- StringPiece16 attributeName(parser->getAttributeName(idx, &len), len);
- Maybe<StringPiece16> result = getAttributeValue(parser, idx);
- if (!result) {
- logger.error(parser->getLineNumber())
- << "<"
- << element
- << "> must have a '"
- << attributeName
- << "' attribute that points to a string."
- << std::endl;
- return false;
- }
- return validateAttributeImpl(element, attributeName, result.value(), charSet,
- parser->getLineNumber(), logger);
-}
-
-bool ManifestValidator::validateAttributeImpl(const StringPiece16& element,
- const StringPiece16& attributeName,
- const StringPiece16& attributeValue,
- const StringPiece16& charSet, size_t lineNumber,
- SourceLogger& logger) {
- StringPiece16::const_iterator badIter =
- util::findNonAlphaNumericAndNotInSet(attributeValue, charSet);
- if (badIter != attributeValue.end()) {
- logger.error(lineNumber)
- << "tag <"
- << element
- << "> attribute '"
- << attributeName
- << "' has invalid character '"
- << StringPiece16(badIter, 1)
- << "'."
- << std::endl;
- return false;
- }
-
- if (!attributeValue.empty()) {
- StringPiece16 trimmed = util::trimWhitespace(attributeValue);
- if (attributeValue.begin() != trimmed.begin()) {
- logger.error(lineNumber)
- << "tag <"
- << element
- << "> attribute '"
- << attributeName
- << "' can not start with whitespace."
- << std::endl;
- return false;
- }
-
- if (attributeValue.end() != trimmed.end()) {
- logger.error(lineNumber)
- << "tag <"
- << element
- << "> attribute '"
- << attributeName
- << "' can not end with whitespace."
- << std::endl;
- return false;
- }
- }
- return true;
-}
-
-constexpr const char16_t* kPackageIdentSet = u"._";
-
-bool ManifestValidator::validateManifest(const Source& source, android::ResXMLParser* parser) {
- bool error = false;
- SourceLogger logger(source);
-
- const StringPiece16 kAndroid = u"android";
- const StringPiece16 kPackage = u"package";
- const StringPiece16 kSharedUserId = u"sharedUserId";
-
- ssize_t idx;
-
- idx = parser->indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size());
- if (idx < 0) {
- logger.error(parser->getLineNumber())
- << "missing package attribute."
- << std::endl;
- error = true;
- } else {
- error |= !validateInlineAttribute(parser, idx, logger, kPackageIdentSet);
- }
-
- idx = parser->indexOfAttribute(kAndroid.data(), kAndroid.size(),
- kSharedUserId.data(), kSharedUserId.size());
- if (idx >= 0) {
- error |= !validateInlineAttribute(parser, idx, logger, kPackageIdentSet);
- }
- return !error;
-}
-
-} // namespace aapt
diff --git a/tools/aapt2/ManifestValidator.h b/tools/aapt2/ManifestValidator.h
deleted file mode 100644
index 1a7f48e9b5ac..000000000000
--- a/tools/aapt2/ManifestValidator.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_MANIFEST_VALIDATOR_H
-#define AAPT_MANIFEST_VALIDATOR_H
-
-#include "Logger.h"
-#include "util/Maybe.h"
-#include "Source.h"
-#include "util/StringPiece.h"
-
-#include <androidfw/ResourceTypes.h>
-
-namespace aapt {
-
-class ManifestValidator {
-public:
- ManifestValidator(const android::ResTable& table);
- ManifestValidator(const ManifestValidator&) = delete;
-
- bool validate(const Source& source, android::ResXMLParser* parser);
-
-private:
- bool validateManifest(const Source& source, android::ResXMLParser* parser);
-
- Maybe<StringPiece16> getAttributeInlineValue(android::ResXMLParser* parser, size_t idx);
- Maybe<StringPiece16> getAttributeValue(android::ResXMLParser* parser, size_t idx);
-
- bool validateInlineAttribute(android::ResXMLParser* parser, size_t idx,
- SourceLogger& logger, const StringPiece16& charSet);
- bool validateAttribute(android::ResXMLParser* parser, size_t idx, SourceLogger& logger,
- const StringPiece16& charSet);
- bool validateAttributeImpl(const StringPiece16& element, const StringPiece16& attributeName,
- const StringPiece16& attributeValue, const StringPiece16& charSet,
- size_t lineNumber, SourceLogger& logger);
-
- const android::ResTable& mTable;
-};
-
-} // namespace aapt
-
-#endif // AAPT_MANIFEST_VALIDATOR_H
diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp
index 1962f582ae7c..34dc1d5508e3 100644
--- a/tools/aapt2/Resource.cpp
+++ b/tools/aapt2/Resource.cpp
@@ -36,7 +36,6 @@ StringPiece16 toString(ResourceType type) {
case ResourceType::kFraction: return u"fraction";
case ResourceType::kId: return u"id";
case ResourceType::kInteger: return u"integer";
- case ResourceType::kIntegerArray: return u"integer-array";
case ResourceType::kInterpolator: return u"interpolator";
case ResourceType::kLayout: return u"layout";
case ResourceType::kMenu: return u"menu";
@@ -65,7 +64,6 @@ static const std::map<StringPiece16, ResourceType> sResourceTypeMap {
{ u"fraction", ResourceType::kFraction },
{ u"id", ResourceType::kId },
{ u"integer", ResourceType::kInteger },
- { u"integer-array", ResourceType::kIntegerArray },
{ u"interpolator", ResourceType::kInterpolator },
{ u"layout", ResourceType::kLayout },
{ u"menu", ResourceType::kMenu },
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 7ef18973d89b..a7afbb5e4018 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -47,7 +47,6 @@ enum class ResourceType {
kFraction,
kId,
kInteger,
- kIntegerArray,
kInterpolator,
kLayout,
kMenu,
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 44710ebc9dc4..2d6c0c2d5b8c 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -62,6 +62,7 @@ bool ResourceParser::flattenXmlSubtree(XmlPullParser* parser, std::u16string* ou
StyleString* outStyleString) {
std::vector<Span> spanStack;
+ bool error = false;
outRawString->clear();
outStyleString->spans.clear();
util::StringBuilder builder;
@@ -84,7 +85,6 @@ bool ResourceParser::flattenXmlSubtree(XmlPullParser* parser, std::u16string* ou
spanStack.pop_back();
} else if (event == XmlPullParser::Event::kText) {
- // TODO(adamlesinski): Verify format strings.
outRawString->append(parser->getText());
builder.append(parser->getText());
@@ -116,9 +116,10 @@ bool ResourceParser::flattenXmlSubtree(XmlPullParser* parser, std::u16string* ou
if (builder.str().size() > std::numeric_limits<uint32_t>::max()) {
mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
<< "style string '" << builder.str() << "' is too long");
- return false;
+ error = true;
+ } else {
+ spanStack.push_back(Span{ spanName, static_cast<uint32_t>(builder.str().size()) });
}
- spanStack.push_back(Span{ spanName, static_cast<uint32_t>(builder.str().size()) });
} else if (event == XmlPullParser::Event::kComment) {
// Skip
@@ -129,7 +130,7 @@ bool ResourceParser::flattenXmlSubtree(XmlPullParser* parser, std::u16string* ou
assert(spanStack.empty() && "spans haven't been fully processed");
outStyleString->str = builder.str();
- return true;
+ return !error;
}
bool ResourceParser::parse(XmlPullParser* parser) {
@@ -308,6 +309,9 @@ bool ResourceParser::parseResources(XmlPullParser* parser) {
} else if (elementName == u"dimen") {
parsedResource.name.type = ResourceType::kDimen;
result = parsePrimitive(parser, &parsedResource);
+ } else if (elementName == u"fraction") {
+ parsedResource.name.type = ResourceType::kFraction;
+ result = parsePrimitive(parser, &parsedResource);
} else if (elementName == u"style") {
parsedResource.name.type = ResourceType::kStyle;
result = parseStyle(parser, &parsedResource);
@@ -321,7 +325,7 @@ bool ResourceParser::parseResources(XmlPullParser* parser) {
parsedResource.name.type = ResourceType::kArray;
result = parseArray(parser, &parsedResource, android::ResTable_map::TYPE_STRING);
} else if (elementName == u"integer-array") {
- parsedResource.name.type = ResourceType::kIntegerArray;
+ parsedResource.name.type = ResourceType::kArray;
result = parseArray(parser, &parsedResource, android::ResTable_map::TYPE_INTEGER);
} else if (elementName == u"declare-styleable") {
parsedResource.name.type = ResourceType::kStyleable;
@@ -434,13 +438,39 @@ std::unique_ptr<Item> ResourceParser::parseXml(XmlPullParser* parser, const uint
bool ResourceParser::parseString(XmlPullParser* parser, ParsedResource* outResource) {
const Source source = mSource.withLine(parser->getLineNumber());
- // TODO(adamlesinski): Read "untranslateable" attribute.
+ bool formatted = true;
+ if (Maybe<StringPiece16> formattedAttr = findAttribute(parser, u"formatted")) {
+ if (!ResourceUtils::tryParseBool(formattedAttr.value(), &formatted)) {
+ mDiag->error(DiagMessage(source) << "invalid value for 'formatted'. Must be a boolean");
+ return false;
+ }
+ }
+
+ bool untranslateable = false;
+ if (Maybe<StringPiece16> untranslateableAttr = findAttribute(parser, u"untranslateable")) {
+ if (!ResourceUtils::tryParseBool(untranslateableAttr.value(), &untranslateable)) {
+ mDiag->error(DiagMessage(source)
+ << "invalid value for 'untranslateable'. Must be a boolean");
+ return false;
+ }
+ }
outResource->value = parseXml(parser, android::ResTable_map::TYPE_STRING, kNoRawString);
if (!outResource->value) {
mDiag->error(DiagMessage(source) << "not a valid string");
return false;
}
+
+ if (formatted || untranslateable) {
+ if (String* stringValue = valueCast<String>(outResource->value.get())) {
+ if (!util::verifyJavaStringFormat(*stringValue->value)) {
+ mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ << "multiple substitutions specified in non-positional format; "
+ "did you mean to add the formatted=\"false\" attribute?");
+ return false;
+ }
+ }
+ }
return true;
}
@@ -464,6 +494,8 @@ bool ResourceParser::parsePrimitive(XmlPullParser* parser, ParsedResource* outRe
typeMask |= android::ResTable_map::TYPE_INTEGER;
break;
+ case ResourceType::kFraction:
+ // fallthrough
case ResourceType::kDimen:
typeMask |= android::ResTable_map::TYPE_DIMENSION
| android::ResTable_map::TYPE_FLOAT
@@ -576,6 +608,12 @@ static uint32_t parseFormatAttribute(const StringPiece16& str) {
return mask;
}
+/**
+ * Returns true if the element is <skip> or <eat-comment> and can be safely ignored.
+ */
+static bool shouldIgnoreElement(const StringPiece16& ns, const StringPiece16& name) {
+ return ns.empty() && (name == u"skip" || name == u"eat-comment");
+}
bool ResourceParser::parseAttr(XmlPullParser* parser, ParsedResource* outResource) {
outResource->source = mSource.withLine(parser->getLineNumber());
@@ -613,25 +651,30 @@ bool ResourceParser::parseAttrImpl(XmlPullParser* parser, ParsedResource* outRes
bool error = false;
const size_t depth = parser->getDepth();
while (XmlPullParser::nextChildNode(parser, depth)) {
- if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
- // Skip comments and text.
+ if (parser->getEvent() == XmlPullParser::Event::kComment) {
+ comment = util::trimWhitespace(parser->getComment()).toString();
+ continue;
+ } else if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
+ // Skip text.
continue;
}
+ const Source itemSource = mSource.withLine(parser->getLineNumber());
const std::u16string& elementNamespace = parser->getElementNamespace();
const std::u16string& elementName = parser->getElementName();
- if (elementNamespace == u"" && (elementName == u"flag" || elementName == u"enum")) {
+ if (elementNamespace.empty() && (elementName == u"flag" || elementName == u"enum")) {
if (elementName == u"enum") {
if (typeMask & android::ResTable_map::TYPE_FLAGS) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ mDiag->error(DiagMessage(itemSource)
<< "can not define an <enum>; already defined a <flag>");
error = true;
continue;
}
typeMask |= android::ResTable_map::TYPE_ENUM;
+
} else if (elementName == u"flag") {
if (typeMask & android::ResTable_map::TYPE_ENUM) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ mDiag->error(DiagMessage(itemSource)
<< "can not define a <flag>; already defined an <enum>");
error = true;
continue;
@@ -642,21 +685,22 @@ bool ResourceParser::parseAttrImpl(XmlPullParser* parser, ParsedResource* outRes
if (Maybe<Attribute::Symbol> s = parseEnumOrFlagItem(parser, elementName)) {
ParsedResource childResource;
childResource.name = s.value().symbol.name.value();
- childResource.source = mSource.withLine(parser->getLineNumber());
+ childResource.source = itemSource;
childResource.value = util::make_unique<Id>();
outResource->childResources.push_back(std::move(childResource));
+
+ s.value().symbol.setComment(std::move(comment));
+ s.value().symbol.setSource(itemSource);
items.push_back(std::move(s.value()));
} else {
error = true;
}
- } else if (elementName == u"skip" || elementName == u"eat-comment") {
- comment = u"";
-
- } else {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
- << ":" << elementName << ">");
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
+ mDiag->error(DiagMessage(itemSource) << ":" << elementName << ">");
error = true;
}
+
+ comment = {};
}
if (error) {
@@ -716,11 +760,10 @@ static Maybe<ResourceName> parseXmlAttributeName(StringPiece16 str) {
p++;
}
- return ResourceName{ package.toString(), ResourceType::kAttr,
- name.empty() ? str.toString() : name.toString() };
+ return ResourceName(package.toString(), ResourceType::kAttr,
+ name.empty() ? str.toString() : name.toString());
}
-
bool ResourceParser::parseStyleItem(XmlPullParser* parser, Style* style) {
const Source source = mSource.withLine(parser->getLineNumber());
@@ -783,7 +826,6 @@ bool ResourceParser::parseStyle(XmlPullParser* parser, ParsedResource* outResour
}
bool error = false;
- std::u16string comment;
const size_t depth = parser->getDepth();
while (XmlPullParser::nextChildNode(parser, depth)) {
if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
@@ -796,11 +838,7 @@ bool ResourceParser::parseStyle(XmlPullParser* parser, ParsedResource* outResour
if (elementNamespace == u"" && elementName == u"item") {
error |= !parseStyleItem(parser, style.get());
- } else if (elementNamespace.empty() &&
- (elementName == u"skip" || elementName == u"eat-comment")) {
- comment = u"";
-
- } else {
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
<< ":" << elementName << ">");
error = true;
@@ -820,7 +858,6 @@ bool ResourceParser::parseArray(XmlPullParser* parser, ParsedResource* outResour
const Source source = mSource.withLine(parser->getLineNumber());
std::unique_ptr<Array> array = util::make_unique<Array>();
- std::u16string comment;
bool error = false;
const size_t depth = parser->getDepth();
while (XmlPullParser::nextChildNode(parser, depth)) {
@@ -839,13 +876,10 @@ bool ResourceParser::parseArray(XmlPullParser* parser, ParsedResource* outResour
error = true;
continue;
}
+ item->setSource(itemSource);
array->items.emplace_back(std::move(item));
- } else if (elementNamespace.empty() &&
- (elementName == u"skip" || elementName == u"eat-comment")) {
- comment = u"";
-
- } else {
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
<< "unknown tag <" << elementNamespace << ":" << elementName << ">");
error = true;
@@ -864,7 +898,6 @@ bool ResourceParser::parsePlural(XmlPullParser* parser, ParsedResource* outResou
const Source source = mSource.withLine(parser->getLineNumber());
std::unique_ptr<Plural> plural = util::make_unique<Plural>();
- std::u16string comment;
bool error = false;
const size_t depth = parser->getDepth();
while (XmlPullParser::nextChildNode(parser, depth)) {
@@ -873,13 +906,14 @@ bool ResourceParser::parsePlural(XmlPullParser* parser, ParsedResource* outResou
continue;
}
+ const Source itemSource = mSource.withLine(parser->getLineNumber());
const std::u16string& elementNamespace = parser->getElementNamespace();
const std::u16string& elementName = parser->getElementName();
if (elementNamespace.empty() && elementName == u"item") {
const auto endAttrIter = parser->endAttributes();
auto attrIter = parser->findAttribute(u"", u"quantity");
if (attrIter == endAttrIter || attrIter->value.empty()) {
- mDiag->error(DiagMessage(source) << "<item> in <plurals> requires attribute "
+ mDiag->error(DiagMessage(itemSource) << "<item> in <plurals> requires attribute "
<< "'quantity'");
error = true;
continue;
@@ -900,7 +934,7 @@ bool ResourceParser::parsePlural(XmlPullParser* parser, ParsedResource* outResou
} else if (trimmedQuantity == u"other") {
index = Plural::Other;
} else {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ mDiag->error(DiagMessage(itemSource)
<< "<item> in <plural> has invalid value '" << trimmedQuantity
<< "' for attribute 'quantity'");
error = true;
@@ -908,7 +942,7 @@ bool ResourceParser::parsePlural(XmlPullParser* parser, ParsedResource* outResou
}
if (plural->values[index]) {
- mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
+ mDiag->error(DiagMessage(itemSource)
<< "duplicate quantity '" << trimmedQuantity << "'");
error = true;
continue;
@@ -918,11 +952,10 @@ bool ResourceParser::parsePlural(XmlPullParser* parser, ParsedResource* outResou
kNoRawString))) {
error = true;
}
- } else if (elementNamespace.empty() &&
- (elementName == u"skip" || elementName == u"eat-comment")) {
- comment = u"";
- } else {
- mDiag->error(DiagMessage(source) << "unknown tag <" << elementNamespace << ":"
+ plural->values[index]->setSource(itemSource);
+
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
+ mDiag->error(DiagMessage(itemSource) << "unknown tag <" << elementNamespace << ":"
<< elementName << ">");
error = true;
}
@@ -944,43 +977,52 @@ bool ResourceParser::parseDeclareStyleable(XmlPullParser* parser, ParsedResource
bool error = false;
const size_t depth = parser->getDepth();
while (XmlPullParser::nextChildNode(parser, depth)) {
- if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
- // Ignore text and comments.
+ if (parser->getEvent() == XmlPullParser::Event::kComment) {
+ comment = util::trimWhitespace(parser->getComment()).toString();
+ continue;
+ } else if (parser->getEvent() != XmlPullParser::Event::kStartElement) {
+ // Ignore text.
continue;
}
+ const Source itemSource = mSource.withLine(parser->getLineNumber());
const std::u16string& elementNamespace = parser->getElementNamespace();
const std::u16string& elementName = parser->getElementName();
if (elementNamespace.empty() && elementName == u"attr") {
const auto endAttrIter = parser->endAttributes();
auto attrIter = parser->findAttribute(u"", u"name");
if (attrIter == endAttrIter || attrIter->value.empty()) {
- mDiag->error(DiagMessage(source) << "<attr> tag must have a 'name' attribute");
+ mDiag->error(DiagMessage(itemSource) << "<attr> tag must have a 'name' attribute");
error = true;
continue;
}
+ // Create the ParsedResource that will add the attribute to the table.
ParsedResource childResource;
childResource.name = ResourceName({}, ResourceType::kAttr, attrIter->value);
- childResource.source = mSource.withLine(parser->getLineNumber());
+ childResource.source = itemSource;
+ childResource.comment = std::move(comment);
if (!parseAttrImpl(parser, &childResource, true)) {
error = true;
continue;
}
- styleable->entries.push_back(Reference(childResource.name));
- outResource->childResources.push_back(std::move(childResource));
+ // Create the reference to this attribute.
+ Reference childRef(childResource.name);
+ childRef.setComment(childResource.comment);
+ childRef.setSource(itemSource);
+ styleable->entries.push_back(std::move(childRef));
- } else if (elementNamespace.empty() &&
- (elementName == u"skip" || elementName == u"eat-comment")) {
- comment = u"";
+ outResource->childResources.push_back(std::move(childResource));
- } else {
- mDiag->error(DiagMessage(source) << "unknown tag <" << elementNamespace << ":"
+ } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
+ mDiag->error(DiagMessage(itemSource) << "unknown tag <" << elementNamespace << ":"
<< elementName << ">");
error = true;
}
+
+ comment = {};
}
if (error) {
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index af6bf67c4a3b..2f5daae80fd7 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -414,6 +414,34 @@ TEST_F(ResourceParserTest, IgnoreCommentBeforeEndTag) {
EXPECT_EQ(value->getComment(), u"One");
}
+TEST_F(ResourceParserTest, ParseNestedComments) {
+ // We only care about declare-styleable and enum/flag attributes because comments
+ // from those end up in R.java
+ std::string input = R"EOF(
+ <declare-styleable name="foo">
+ <!-- The name of the bar -->
+ <attr name="barName" format="string|reference" />
+ </declare-styleable>
+
+ <attr name="foo">
+ <!-- The very first -->
+ <enum name="one" value="1" />
+ </attr>)EOF";
+ ASSERT_TRUE(testParse(input));
+
+ Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo");
+ ASSERT_NE(nullptr, styleable);
+ ASSERT_EQ(1u, styleable->entries.size());
+
+ EXPECT_EQ(StringPiece16(u"The name of the bar"), styleable->entries.front().getComment());
+
+ Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo");
+ ASSERT_NE(nullptr, attr);
+ ASSERT_EQ(1u, attr->symbols.size());
+
+ EXPECT_EQ(StringPiece16(u"The very first"), attr->symbols.front().symbol.getComment());
+}
+
/*
* Declaring an ID as public should not require a separate definition
* (as an ID has no value).
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 0db1c372c901..d3c3c1044ae7 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -74,9 +74,11 @@ bool tryParseReference(const StringPiece16& str, ResourceNameRef* outRef, bool*
return false;
}
- outRef->package = package;
- outRef->type = *parsedType;
- outRef->entry = entry;
+ if (outRef != nullptr) {
+ outRef->package = package;
+ outRef->type = *parsedType;
+ outRef->entry = entry;
+ }
if (outCreate) {
*outCreate = create;
}
@@ -88,6 +90,10 @@ bool tryParseReference(const StringPiece16& str, ResourceNameRef* outRef, bool*
return false;
}
+bool isReference(const StringPiece16& str) {
+ return tryParseReference(str, nullptr, nullptr, nullptr);
+}
+
bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outRef) {
StringPiece16 trimmedStr(util::trimWhitespace(str));
if (trimmedStr.empty()) {
@@ -322,18 +328,36 @@ std::unique_ptr<BinaryPrimitive> tryParseColor(const StringPiece16& str) {
return error ? std::unique_ptr<BinaryPrimitive>() : util::make_unique<BinaryPrimitive>(value);
}
-std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece16& str) {
+bool tryParseBool(const StringPiece16& str, bool* outValue) {
StringPiece16 trimmedStr(util::trimWhitespace(str));
- uint32_t data = 0;
if (trimmedStr == u"true" || trimmedStr == u"TRUE") {
- data = 0xffffffffu;
- } else if (trimmedStr != u"false" && trimmedStr != u"FALSE") {
- return {};
+ if (outValue) {
+ *outValue = true;
+ }
+ return true;
+ } else if (trimmedStr == u"false" || trimmedStr == u"FALSE") {
+ if (outValue) {
+ *outValue = false;
+ }
+ return true;
}
- android::Res_value value = { };
- value.dataType = android::Res_value::TYPE_INT_BOOLEAN;
- value.data = data;
- return util::make_unique<BinaryPrimitive>(value);
+ return false;
+}
+
+std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece16& str) {
+ bool result = false;
+ if (tryParseBool(str, &result)) {
+ android::Res_value value = {};
+ value.dataType = android::Res_value::TYPE_INT_BOOLEAN;
+
+ if (result) {
+ value.data = 0xffffffffu;
+ } else {
+ value.data = 0;
+ }
+ return util::make_unique<BinaryPrimitive>(value);
+ }
+ return {};
}
std::unique_ptr<BinaryPrimitive> tryParseInt(const StringPiece16& str) {
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index 118a2ee9d769..851edc89fa90 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -49,11 +49,21 @@ bool tryParseReference(const StringPiece16& str, ResourceNameRef* outReference,
bool* outCreate = nullptr, bool* outPrivate = nullptr);
/*
+ * Returns true if the string is in the form of a resource reference (@[+][package:]type/name).
+ */
+bool isReference(const StringPiece16& str);
+
+/*
* Returns true if the string was parsed as an attribute reference (?[package:]type/name),
* with `outReference` set to the parsed reference.
*/
bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outReference);
+/**
+ * Returns true if the value is a boolean, putting the result in `outValue`.
+ */
+bool tryParseBool(const StringPiece16& str, bool* outValue);
+
/*
* Returns a Reference, or None Maybe instance if the string `str` was parsed as a
* valid reference to a style.
diff --git a/tools/aapt2/Resource_test.cpp b/tools/aapt2/Resource_test.cpp
index d957999f492b..48dc521d843c 100644
--- a/tools/aapt2/Resource_test.cpp
+++ b/tools/aapt2/Resource_test.cpp
@@ -69,10 +69,6 @@ TEST(ResourceTypeTest, ParseResourceTypes) {
ASSERT_NE(type, nullptr);
EXPECT_EQ(*type, ResourceType::kInteger);
- type = parseResourceType(u"integer-array");
- ASSERT_NE(type, nullptr);
- EXPECT_EQ(*type, ResourceType::kIntegerArray);
-
type = parseResourceType(u"interpolator");
ASSERT_NE(type, nullptr);
EXPECT_EQ(*type, ResourceType::kInterpolator);
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index 803da03743c5..282ed9a56f5c 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -42,6 +42,7 @@ enum {
SDK_KITKAT_WATCH = 20,
SDK_LOLLIPOP = 21,
SDK_LOLLIPOP_MR1 = 22,
+ SDK_MARSHMALLOW = 23,
};
size_t findAttributeSdkLevel(ResourceId id);
diff --git a/tools/aapt2/XmlDom.cpp b/tools/aapt2/XmlDom.cpp
index d948775cc623..b769c7620658 100644
--- a/tools/aapt2/XmlDom.cpp
+++ b/tools/aapt2/XmlDom.cpp
@@ -125,7 +125,7 @@ static void XMLCALL endElementHandler(void* userData, const char* name) {
Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
assert(!stack->nodeStack.empty());
- stack->nodeStack.top()->comment = std::move(stack->pendingComment);
+ //stack->nodeStack.top()->comment = std::move(stack->pendingComment);
stack->nodeStack.pop();
}
@@ -194,7 +194,7 @@ std::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const
XML_ParserFree(parser);
if (stack.root) {
- return util::make_unique<XmlResource>(ResourceFile{}, std::move(stack.root));
+ return util::make_unique<XmlResource>(ResourceFile{ {}, {}, source }, std::move(stack.root));
}
return {};
}
@@ -317,6 +317,22 @@ std::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnost
return util::make_unique<XmlResource>(ResourceFile{}, std::move(root));
}
+Element* findRootElement(Node* node) {
+ if (!node) {
+ return nullptr;
+ }
+
+ Element* el = nullptr;
+ while ((el = nodeCast<Element>(node)) == nullptr) {
+ if (node->children.empty()) {
+ return nullptr;
+ }
+ // We are looking for the first element, and namespaces can only have one child.
+ node = node->children.front().get();
+ }
+ return el;
+}
+
void Node::addChild(std::unique_ptr<Node> child) {
child->parent = this;
children.push_back(std::move(child));
diff --git a/tools/aapt2/XmlDom.h b/tools/aapt2/XmlDom.h
index c095f085f1fa..9a46bcb9fc5c 100644
--- a/tools/aapt2/XmlDom.h
+++ b/tools/aapt2/XmlDom.h
@@ -34,6 +34,8 @@
namespace aapt {
namespace xml {
+constexpr const char16_t* kSchemaAndroid = u"http://schemas.android.com/apk/res/android";
+
struct RawVisitor;
/**
@@ -132,6 +134,8 @@ std::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const
std::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag,
const Source& source);
+Element* findRootElement(Node* node);
+
/**
* A visitor interface for the different XML Node subtypes. This will not traverse into
* children. Use Visitor for that.
diff --git a/tools/aapt2/flatten/ResourceTypeExtensions.h b/tools/aapt2/flatten/ResourceTypeExtensions.h
index 38cda097c927..c1ff556ac0cf 100644
--- a/tools/aapt2/flatten/ResourceTypeExtensions.h
+++ b/tools/aapt2/flatten/ResourceTypeExtensions.h
@@ -132,6 +132,32 @@ struct Public_header {
uint32_t count;
};
+/**
+ * A structure representing source data for a resource entry.
+ * Appears after an android::ResTable_entry or android::ResTable_map_entry.
+ *
+ * TODO(adamlesinski): This causes some issues when runtime code checks
+ * the size of an android::ResTable_entry. It assumes it is an
+ * android::ResTable_map_entry if the size is bigger than an android::ResTable_entry
+ * which may not be true if this structure is present.
+ */
+struct ResTable_entry_source {
+ /**
+ * File path reference.
+ */
+ android::ResStringPool_ref path;
+
+ /**
+ * Line number this resource was defined on.
+ */
+ uint32_t line;
+
+ /**
+ * Comment string reference.
+ */
+ android::ResStringPool_ref comment;
+};
+
struct Public_entry {
uint16_t entryId;
@@ -143,8 +169,7 @@ struct Public_entry {
uint16_t state;
android::ResStringPool_ref key;
- android::ResStringPool_ref source;
- uint32_t sourceLine;
+ ResTable_entry_source source;
};
/**
@@ -173,28 +198,7 @@ struct SymbolTable_entry {
* The index into the string pool where the name of this
* symbol exists.
*/
- uint32_t stringIndex;
-};
-
-/**
- * A structure representing the source of a resourc entry.
- * Appears after an android::ResTable_entry or android::ResTable_map_entry.
- *
- * TODO(adamlesinski): This causes some issues when runtime code checks
- * the size of an android::ResTable_entry. It assumes it is an
- * android::ResTable_map_entry if the size is bigger than an android::ResTable_entry
- * which may not be true if this structure is present.
- */
-struct ResTable_entry_source {
- /**
- * Index into the source string pool.
- */
- uint32_t pathIndex;
-
- /**
- * Line number this resource was defined on.
- */
- uint32_t line;
+ android::ResStringPool_ref name;
};
/**
diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp
index 47fa2a63d553..6b90fb276b6d 100644
--- a/tools/aapt2/flatten/TableFlattener.cpp
+++ b/tools/aapt2/flatten/TableFlattener.cpp
@@ -54,9 +54,16 @@ static void strcpy16_htod(uint16_t* dst, size_t len, const StringPiece16& src) {
struct FlatEntry {
ResourceEntry* entry;
Value* value;
+
+ // The entry string pool index to the entry's name.
uint32_t entryKey;
+
+ // The source string pool index to the source file path.
uint32_t sourcePathKey;
uint32_t sourceLine;
+
+ // The source string pool index to the comment.
+ uint32_t commentKey;
};
class SymbolWriter {
@@ -318,8 +325,9 @@ private:
if (mOptions.useExtendedChunks) {
// Write the extra source block. This will be ignored by the Android runtime.
ResTable_entry_source* sourceBlock = buffer->nextBlock<ResTable_entry_source>();
- sourceBlock->pathIndex = util::hostToDevice32(entry->sourcePathKey);
+ sourceBlock->path.index = util::hostToDevice32(entry->sourcePathKey);
sourceBlock->line = util::hostToDevice32(entry->sourceLine);
+ sourceBlock->comment.index = util::hostToDevice32(entry->commentKey);
outEntry->size += sizeof(*sourceBlock);
}
@@ -486,12 +494,14 @@ private:
publicEntry->entryId = util::hostToDevice32(entry->id.value());
publicEntry->key.index = util::hostToDevice32(mKeyPool.makeRef(
entry->name).getIndex());
- publicEntry->source.index = util::hostToDevice32(mSourcePool->makeRef(
+ publicEntry->source.path.index = util::hostToDevice32(mSourcePool->makeRef(
util::utf8ToUtf16(entry->symbolStatus.source.path)).getIndex());
if (entry->symbolStatus.source.line) {
- publicEntry->sourceLine = util::hostToDevice32(
+ publicEntry->source.line = util::hostToDevice32(
entry->symbolStatus.source.line.value());
}
+ publicEntry->source.comment.index = util::hostToDevice32(mSourcePool->makeRef(
+ entry->symbolStatus.comment).getIndex());
switch (entry->symbolStatus.state) {
case SymbolState::kPrivate:
@@ -565,13 +575,16 @@ private:
lineNumber = value->getSource().line.value();
}
+ const StringPool::Ref commentRef = mSourcePool->makeRef(value->getComment());
+
configToEntryListMap[configValue.config]
.push_back(FlatEntry{
entry,
value,
keyIndex,
(uint32_t) sourceRef.getIndex(),
- lineNumber });
+ lineNumber,
+ (uint32_t) commentRef.getIndex() });
}
}
@@ -680,7 +693,7 @@ bool TableFlattener::consume(IAaptContext* context, ResourceTable* table) {
// Update the offsets to their final values.
if (symbolEntryData) {
for (SymbolWriter::Entry& entry : symbolOffsets) {
- symbolEntryData->stringIndex = util::hostToDevice32(entry.name.getIndex());
+ symbolEntryData->name.index = util::hostToDevice32(entry.name.getIndex());
// The symbols were all calculated with the packageBuffer offset. We need to
// add the beginning of the output buffer.
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
new file mode 100644
index 000000000000..b36682d98bfd
--- /dev/null
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "java/AnnotationProcessor.h"
+#include "util/Util.h"
+
+#include <algorithm>
+
+namespace aapt {
+
+void AnnotationProcessor::appendCommentLine(const std::string& comment) {
+ static const std::string sDeprecated = "@deprecated";
+ static const std::string sSystemApi = "@SystemApi";
+
+ if (comment.find(sDeprecated) != std::string::npos && !mDeprecated) {
+ mDeprecated = true;
+ if (!mAnnotations.empty()) {
+ mAnnotations += "\n";
+ }
+ mAnnotations += mPrefix;
+ mAnnotations += "@Deprecated";
+ }
+
+ if (comment.find(sSystemApi) != std::string::npos && !mSystemApi) {
+ mSystemApi = true;
+ if (!mAnnotations.empty()) {
+ mAnnotations += "\n";
+ }
+ mAnnotations += mPrefix;
+ mAnnotations += "@android.annotations.SystemApi";
+ }
+
+ if (mComment.empty()) {
+ mComment += mPrefix;
+ mComment += "/**";
+ }
+
+ mComment += "\n";
+ mComment += mPrefix;
+ mComment += " * ";
+ mComment += std::move(comment);
+}
+
+void AnnotationProcessor::appendComment(const StringPiece16& comment) {
+ // We need to process line by line to clean-up whitespace and append prefixes.
+ for (StringPiece16 line : util::tokenize(comment, u'\n')) {
+ line = util::trimWhitespace(line);
+ if (!line.empty()) {
+ appendCommentLine(util::utf16ToUtf8(line));
+ }
+ }
+}
+
+void AnnotationProcessor::appendComment(const StringPiece& comment) {
+ for (StringPiece line : util::tokenize(comment, '\n')) {
+ line = util::trimWhitespace(line);
+ if (!line.empty()) {
+ appendCommentLine(line.toString());
+ }
+ }
+}
+
+std::string AnnotationProcessor::buildComment() {
+ if (!mComment.empty()) {
+ mComment += "\n";
+ mComment += mPrefix;
+ mComment += " */";
+ }
+ return std::move(mComment);
+}
+
+std::string AnnotationProcessor::buildAnnotations() {
+ return std::move(mAnnotations);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h
new file mode 100644
index 000000000000..81a6f6e42759
--- /dev/null
+++ b/tools/aapt2/java/AnnotationProcessor.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_JAVA_ANNOTATIONPROCESSOR_H
+#define AAPT_JAVA_ANNOTATIONPROCESSOR_H
+
+#include "util/StringPiece.h"
+
+#include <string>
+
+namespace aapt {
+
+/**
+ * Builds a JavaDoc comment from a set of XML comments.
+ * This will also look for instances of @SystemApi and convert them to
+ * actual Java annotations.
+ *
+ * Example:
+ *
+ * Input XML:
+ *
+ * <!-- This is meant to be hidden because
+ * It is system api. Also it is @deprecated
+ * @SystemApi
+ * -->
+ *
+ * Output JavaDoc:
+ *
+ * /\*
+ * * This is meant to be hidden because
+ * * It is system api. Also it is @deprecated
+ * * @SystemApi
+ * *\/
+ *
+ * Output Annotations:
+ *
+ * @Deprecated
+ * @android.annotation.SystemApi
+ *
+ */
+class AnnotationProcessor {
+public:
+ /**
+ * Creates an AnnotationProcessor with a given prefix for each line generated.
+ * This is usually a set of spaces for indentation.
+ */
+ AnnotationProcessor(const StringPiece& prefix) : mPrefix(prefix.toString()) {
+ }
+
+ /**
+ * Adds more comments. Since resources can have various values with different configurations,
+ * we need to collect all the comments.
+ */
+ void appendComment(const StringPiece16& comment);
+ void appendComment(const StringPiece& comment);
+
+ /**
+ * Finishes the comment and moves it to the caller. Subsequent calls to buildComment() have
+ * undefined results.
+ */
+ std::string buildComment();
+
+ /**
+ * Finishes the annotation and moves it to the caller. Subsequent calls to buildAnnotations()
+ * have undefined results.
+ */
+ std::string buildAnnotations();
+
+private:
+ std::string mPrefix;
+ std::string mComment;
+ std::string mAnnotations;
+ bool mDeprecated = false;
+ bool mSystemApi = false;
+
+ void appendCommentLine(const std::string& line);
+};
+
+} // namespace aapt
+
+#endif /* AAPT_JAVA_ANNOTATIONPROCESSOR_H */
diff --git a/tools/aapt2/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index cdf1b6ad600b..dfd2ef6f5372 100644
--- a/tools/aapt2/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -14,11 +14,14 @@
* limitations under the License.
*/
-#include "JavaClassGenerator.h"
#include "NameMangler.h"
#include "Resource.h"
#include "ResourceTable.h"
#include "ResourceValues.h"
+#include "ValueVisitor.h"
+
+#include "java/AnnotationProcessor.h"
+#include "java/JavaClassGenerator.h"
#include "util/StringPiece.h"
#include <algorithm>
@@ -108,13 +111,13 @@ void JavaClassGenerator::generateStyleable(const StringPiece16& packageNameToGen
std::sort(sortedAttributes.begin(), sortedAttributes.end());
// First we emit the array containing the IDs of each attribute.
- *out << " "
+ *out << " "
<< "public static final int[] " << transform(entryName) << " = {";
const size_t attrCount = sortedAttributes.size();
for (size_t i = 0; i < attrCount; i++) {
if (i % kAttribsPerLine == 0) {
- *out << "\n ";
+ *out << "\n ";
}
*out << sortedAttributes[i].first;
@@ -122,11 +125,11 @@ void JavaClassGenerator::generateStyleable(const StringPiece16& packageNameToGen
*out << ", ";
}
}
- *out << "\n };\n";
+ *out << "\n };\n";
// Now we emit the indices into the array.
for (size_t i = 0; i < attrCount; i++) {
- *out << " "
+ *out << " "
<< "public static" << finalModifier
<< " int " << transform(entryName);
@@ -140,6 +143,85 @@ void JavaClassGenerator::generateStyleable(const StringPiece16& packageNameToGen
}
}
+static void addAttributeFormatDoc(AnnotationProcessor* processor, Attribute* attr) {
+ const uint32_t typeMask = attr->typeMask;
+ if (typeMask & android::ResTable_map::TYPE_REFERENCE) {
+ processor->appendComment(
+ "<p>May be a reference to another resource, in the form\n"
+ "\"<code>@[+][<i>package</i>:]<i>type</i>/<i>name</i></code>\" or a theme\n"
+ "attribute in the form\n"
+ "\"<code>?[<i>package</i>:]<i>type</i>/<i>name</i></code>\".");
+ }
+
+ if (typeMask & android::ResTable_map::TYPE_STRING) {
+ processor->appendComment(
+ "<p>May be a string value, using '\\;' to escape characters such as\n"
+ "'\\n' or '\\uxxxx' for a unicode character;");
+ }
+
+ if (typeMask & android::ResTable_map::TYPE_INTEGER) {
+ processor->appendComment("<p>May be an integer value, such as \"<code>100</code>\".");
+ }
+
+ if (typeMask & android::ResTable_map::TYPE_BOOLEAN) {
+ processor->appendComment(
+ "<p>May be a boolean value, such as \"<code>true</code>\" or\n"
+ "\"<code>false</code>\".");
+ }
+
+ if (typeMask & android::ResTable_map::TYPE_COLOR) {
+ processor->appendComment(
+ "<p>May be a color value, in the form of \"<code>#<i>rgb</i></code>\",\n"
+ "\"<code>#<i>argb</i></code>\", \"<code>#<i>rrggbb</i></code\", or \n"
+ "\"<code>#<i>aarrggbb</i></code>\".");
+ }
+
+ if (typeMask & android::ResTable_map::TYPE_FLOAT) {
+ processor->appendComment(
+ "<p>May be a floating point value, such as \"<code>1.2</code>\".");
+ }
+
+ if (typeMask & android::ResTable_map::TYPE_DIMENSION) {
+ processor->appendComment(
+ "<p>May be a dimension value, which is a floating point number appended with a\n"
+ "unit such as \"<code>14.5sp</code>\".\n"
+ "Available units are: px (pixels), dp (density-independent pixels),\n"
+ "sp (scaled pixels based on preferred font size), in (inches), and\n"
+ "mm (millimeters).");
+ }
+
+ if (typeMask & android::ResTable_map::TYPE_FRACTION) {
+ processor->appendComment(
+ "<p>May be a fractional value, which is a floating point number appended with\n"
+ "either % or %p, such as \"<code>14.5%</code>\".\n"
+ "The % suffix always means a percentage of the base size;\n"
+ "the optional %p suffix provides a size relative to some parent container.");
+ }
+
+ if (typeMask & (android::ResTable_map::TYPE_FLAGS | android::ResTable_map::TYPE_ENUM)) {
+ if (typeMask & android::ResTable_map::TYPE_FLAGS) {
+ processor->appendComment(
+ "<p>Must be one or more (separated by '|') of the following "
+ "constant values.</p>");
+ } else {
+ processor->appendComment("<p>Must be one of the following constant values.</p>");
+ }
+
+ processor->appendComment("<table>\n<colgroup align=\"left\" />\n"
+ "<colgroup align=\"left\" />\n"
+ "<colgroup align=\"left\" />\n"
+ "<tr><th>Constant</th><th>Value</th><th>Description</th></tr>\n");
+ for (const Attribute::Symbol& symbol : attr->symbols) {
+ std::stringstream line;
+ line << "<tr><td>" << symbol.symbol.name.value().entry << "</td>"
+ << "<td>" << std::hex << symbol.value << std::dec << "</td>"
+ << "<td>" << util::trimWhitespace(symbol.symbol.getComment()) << "</td></tr>";
+ processor->appendComment(line.str());
+ }
+ processor->appendComment("</table>");
+ }
+}
+
bool JavaClassGenerator::generateType(const StringPiece16& packageNameToGenerate,
const ResourceTablePackage* package,
const ResourceTableType* type,
@@ -185,7 +267,33 @@ bool JavaClassGenerator::generateType(const StringPiece16& packageNameToGenerate
generateStyleable(packageNameToGenerate, unmangledName, static_cast<const Styleable*>(
entry->values.front().value.get()), out);
} else {
- *out << " " << "public static" << finalModifier
+ AnnotationProcessor processor(" ");
+ if (entry->symbolStatus.state != SymbolState::kUndefined) {
+ processor.appendComment(entry->symbolStatus.comment);
+ }
+
+ for (const auto& configValue : entry->values) {
+ processor.appendComment(configValue.value->getComment());
+ }
+
+ if (!entry->values.empty()) {
+ if (Attribute* attr = valueCast<Attribute>(entry->values.front().value.get())) {
+ // We list out the available values for the given attribute.
+ addAttributeFormatDoc(&processor, attr);
+ }
+ }
+
+ std::string comment = processor.buildComment();
+ if (!comment.empty()) {
+ *out << comment << "\n";
+ }
+
+ std::string annotations = processor.buildAnnotations();
+ if (!annotations.empty()) {
+ *out << annotations << "\n";
+ }
+
+ *out << " " << "public static" << finalModifier
<< " int " << transform(unmangledName) << " = " << id << ";\n";
}
}
@@ -210,11 +318,11 @@ bool JavaClassGenerator::generate(const StringPiece16& packageNameToGenerate,
} else {
typeStr = toString(type->type);
}
- *out << " public static final class " << typeStr << " {\n";
+ *out << " public static final class " << typeStr << " {\n";
if (!generateType(packageNameToGenerate, package.get(), type.get(), out)) {
return false;
}
- *out << " }\n";
+ *out << " }\n";
}
}
diff --git a/tools/aapt2/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index e53a765ae0d8..e53a765ae0d8 100644
--- a/tools/aapt2/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
diff --git a/tools/aapt2/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index cc5e98150ae3..2dc387bea8b9 100644
--- a/tools/aapt2/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "JavaClassGenerator.h"
+#include "java/JavaClassGenerator.h"
#include "util/Util.h"
#include "test/Builders.h"
@@ -198,4 +198,35 @@ TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
EXPECT_NE(std::string::npos, output.find("int foo_com_lib_bar ="));
}
+TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
+ std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
+ .setPackageId(u"android", 0x01)
+ .addSimple(u"@android:id/foo", ResourceId(0x01010000))
+ .build();
+ test::getValue<Id>(table.get(), u"@android:id/foo")
+ ->setComment(std::u16string(u"This is a comment\n@deprecated"));
+
+ JavaClassGenerator generator(table.get(), {});
+
+ std::stringstream out;
+ ASSERT_TRUE(generator.generate(u"android", &out));
+ std::string actual = out.str();
+
+ EXPECT_NE(std::string::npos, actual.find(
+ R"EOF(/**
+ * This is a comment
+ * @deprecated
+ */
+ @Deprecated
+ public static final int foo = 0x01010000;)EOF"));
+}
+
+TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {
+
+}
+
+TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
+
+}
+
} // namespace aapt
diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp
new file mode 100644
index 000000000000..901a344881fc
--- /dev/null
+++ b/tools/aapt2/java/ManifestClassGenerator.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Source.h"
+#include "XmlDom.h"
+
+#include "java/AnnotationProcessor.h"
+#include "java/ManifestClassGenerator.h"
+#include "util/Maybe.h"
+
+#include <algorithm>
+
+namespace aapt {
+
+static Maybe<StringPiece16> extractJavaIdentifier(IDiagnostics* diag, const Source& source,
+ const StringPiece16& value) {
+ const StringPiece16 sep = u".";
+ auto iter = std::find_end(value.begin(), value.end(), sep.begin(), sep.end());
+
+ StringPiece16 result;
+ if (iter != value.end()) {
+ result.assign(iter + sep.size(), value.end() - (iter + sep.size()));
+ } else {
+ result = value;
+ }
+
+ if (result.empty()) {
+ diag->error(DiagMessage(source) << "empty symbol");
+ return {};
+ }
+
+ iter = util::findNonAlphaNumericAndNotInSet(result, u"_");
+ if (iter != result.end()) {
+ diag->error(DiagMessage(source)
+ << "invalid character '" << StringPiece16(iter, 1)
+ << "' in '" << result << "'");
+ return {};
+ }
+
+ if (*result.begin() >= u'0' && *result.begin() <= u'9') {
+ diag->error(DiagMessage(source) << "symbol can not start with a digit");
+ return {};
+ }
+
+ return result;
+}
+
+static bool writeSymbol(IDiagnostics* diag, const Source& source, xml::Element* el,
+ std::ostream* out) {
+ xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name");
+ if (!attr) {
+ diag->error(DiagMessage(source) << "<" << el->name << "> must define 'android:name'");
+ return false;
+ }
+
+ Maybe<StringPiece16> result = extractJavaIdentifier(diag, source.withLine(el->lineNumber),
+ attr->value);
+ if (!result) {
+ return false;
+ }
+
+ *out << "\n";
+
+ if (!util::trimWhitespace(el->comment).empty()) {
+ AnnotationProcessor processor(" ");
+ processor.appendComment(el->comment);
+ *out << processor.buildComment() << "\n";
+ std::string annotations = processor.buildAnnotations();
+ if (!annotations.empty()) {
+ *out << annotations << "\n";
+ }
+ }
+ *out << " public static final String " << result.value() << "=\"" << attr->value << "\";\n";
+ return true;
+}
+
+bool ManifestClassGenerator::generate(IDiagnostics* diag, const StringPiece16& package,
+ XmlResource* res, std::ostream* out) {
+ xml::Element* el = xml::findRootElement(res->root.get());
+ if (!el) {
+ return false;
+ }
+
+ if (el->name != u"manifest" && !el->namespaceUri.empty()) {
+ diag->error(DiagMessage(res->file.source) << "no <manifest> root tag defined");
+ return false;
+ }
+
+ *out << "package " << package << ";\n\n"
+ << "public class Manifest {\n";
+
+ bool error = false;
+ std::vector<xml::Element*> children = el->getChildElements();
+
+
+ // First write out permissions.
+ *out << " public static class permission {\n";
+ for (xml::Element* childEl : children) {
+ if (childEl->namespaceUri.empty() && childEl->name == u"permission") {
+ error |= !writeSymbol(diag, res->file.source, childEl, out);
+ }
+ }
+ *out << " }\n";
+
+ // Next write out permission groups.
+ *out << " public static class permission_group {\n";
+ for (xml::Element* childEl : children) {
+ if (childEl->namespaceUri.empty() && childEl->name == u"permission-group") {
+ error |= !writeSymbol(diag, res->file.source, childEl, out);
+ }
+ }
+ *out << " }\n";
+
+ *out << "}\n";
+ return !error;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/java/ManifestClassGenerator.h b/tools/aapt2/java/ManifestClassGenerator.h
new file mode 100644
index 000000000000..0f0998f8e2ba
--- /dev/null
+++ b/tools/aapt2/java/ManifestClassGenerator.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_JAVA_MANIFESTCLASSGENERATOR_H
+#define AAPT_JAVA_MANIFESTCLASSGENERATOR_H
+
+#include "Diagnostics.h"
+#include "process/IResourceTableConsumer.h"
+#include "util/StringPiece.h"
+
+#include <iostream>
+
+namespace aapt {
+
+struct ManifestClassGenerator {
+ bool generate(IDiagnostics* diag, const StringPiece16& package, XmlResource* res,
+ std::ostream* out);
+};
+
+} // namespace aapt
+
+#endif /* AAPT_JAVA_MANIFESTCLASSGENERATOR_H */
diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp
new file mode 100644
index 000000000000..1b5bc0586f43
--- /dev/null
+++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "java/ManifestClassGenerator.h"
+
+#include "test/Builders.h"
+#include "test/Context.h"
+
+#include <gtest/gtest.h>
+
+namespace aapt {
+
+TEST(ManifestClassGeneratorTest, NameIsProperlyGeneratedFromSymbol) {
+ std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
+ std::unique_ptr<XmlResource> manifest = test::buildXmlDom(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <permission android:name="android.permission.ACCESS_INTERNET" />
+ <permission android:name="android.DO_DANGEROUS_THINGS" />
+ <permission android:name="com.test.sample.permission.HUH" />
+ <permission-group android:name="foo.bar.PERMISSION" />
+ </manifest>)EOF");
+
+ std::stringstream out;
+ ManifestClassGenerator generator;
+ ASSERT_TRUE(generator.generate(context->getDiagnostics(), u"android", manifest.get(), &out));
+
+ std::string actual = out.str();
+
+ const size_t permissionClassPos = actual.find("public static class permission {");
+ const size_t permissionGroupClassPos = actual.find("public static class permission_group {");
+ ASSERT_NE(std::string::npos, permissionClassPos);
+ ASSERT_NE(std::string::npos, permissionGroupClassPos);
+
+ //
+ // Make sure these permissions are in the permission class.
+ //
+
+ size_t pos = actual.find("public static final String ACCESS_INTERNET="
+ "\"android.permission.ACCESS_INTERNET\";");
+ EXPECT_GT(pos, permissionClassPos);
+ EXPECT_LT(pos, permissionGroupClassPos);
+
+ pos = actual.find("public static final String DO_DANGEROUS_THINGS="
+ "\"android.DO_DANGEROUS_THINGS\";");
+ EXPECT_GT(pos, permissionClassPos);
+ EXPECT_LT(pos, permissionGroupClassPos);
+
+ pos = actual.find("public static final String HUH=\"com.test.sample.permission.HUH\";");
+ EXPECT_GT(pos, permissionClassPos);
+ EXPECT_LT(pos, permissionGroupClassPos);
+
+ //
+ // Make sure these permissions are in the permission_group class
+ //
+
+ pos = actual.find("public static final String PERMISSION="
+ "\"foo.bar.PERMISSION\";");
+ EXPECT_GT(pos, permissionGroupClassPos);
+ EXPECT_LT(pos, std::string::npos);
+}
+
+TEST(ManifestClassGeneratorTest, CommentsAndAnnotationsArePresent) {
+ std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
+ std::unique_ptr<XmlResource> manifest = test::buildXmlDom(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- Required to access the internet.
+ Added in API 1. -->
+ <permission android:name="android.permission.ACCESS_INTERNET" />
+ <!-- @deprecated This permission is for playing outside. -->
+ <permission android:name="android.permission.PLAY_OUTSIDE" />
+ <!-- This is a private permission for system only!
+ @hide
+ @SystemApi -->
+ <permission android:name="android.permission.SECRET" />
+ </manifest>)EOF");
+
+ std::stringstream out;
+ ManifestClassGenerator generator;
+ ASSERT_TRUE(generator.generate(context->getDiagnostics(), u"android", manifest.get(), &out));
+
+ std::string actual = out.str();
+
+ EXPECT_NE(std::string::npos, actual.find(
+R"EOF( /**
+ * Required to access the internet.
+ * Added in API 1.
+ */
+ public static final String ACCESS_INTERNET="android.permission.ACCESS_INTERNET";)EOF"));
+
+ EXPECT_NE(std::string::npos, actual.find(
+R"EOF( /**
+ * @deprecated This permission is for playing outside.
+ */
+ @Deprecated
+ public static final String PLAY_OUTSIDE="android.permission.PLAY_OUTSIDE";)EOF"));
+
+ EXPECT_NE(std::string::npos, actual.find(
+R"EOF( /**
+ * This is a private permission for system only!
+ * @hide
+ * @SystemApi
+ */
+ @android.annotations.SystemApi
+ public static final String SECRET="android.permission.SECRET";)EOF"));
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp
index 7f4dc91eae9f..44314772fbd4 100644
--- a/tools/aapt2/ProguardRules.cpp
+++ b/tools/aapt2/java/ProguardRules.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include "ProguardRules.h"
#include "XmlDom.h"
+#include "java/ProguardRules.h"
#include "util/Util.h"
#include <memory>
@@ -25,8 +25,6 @@
namespace aapt {
namespace proguard {
-constexpr const char16_t* kSchemaAndroid = u"http://schemas.android.com/apk/res/android";
-
class BaseVisitor : public xml::Visitor {
public:
BaseVisitor(const Source& source, KeepSet* keepSet) : mSource(source), mKeepSet(keepSet) {
@@ -83,7 +81,7 @@ struct LayoutVisitor : public BaseVisitor {
bool checkName = false;
if (node->namespaceUri.empty()) {
checkClass = node->name == u"view" || node->name == u"fragment";
- } else if (node->namespaceUri == kSchemaAndroid) {
+ } else if (node->namespaceUri == xml::kSchemaAndroid) {
checkName = node->name == u"fragment";
}
@@ -91,10 +89,10 @@ struct LayoutVisitor : public BaseVisitor {
if (checkClass && attr.namespaceUri.empty() && attr.name == u"class" &&
util::isJavaClassName(attr.value)) {
addClass(node->lineNumber, attr.value);
- } else if (checkName && attr.namespaceUri == kSchemaAndroid && attr.name == u"name" &&
- util::isJavaClassName(attr.value)) {
+ } else if (checkName && attr.namespaceUri == xml::kSchemaAndroid &&
+ attr.name == u"name" && util::isJavaClassName(attr.value)) {
addClass(node->lineNumber, attr.value);
- } else if (attr.namespaceUri == kSchemaAndroid && attr.name == u"onClick") {
+ } else if (attr.namespaceUri == xml::kSchemaAndroid && attr.name == u"onClick") {
addMethod(node->lineNumber, attr.value);
}
}
@@ -114,7 +112,7 @@ struct XmlResourceVisitor : public BaseVisitor {
}
if (checkFragment) {
- xml::Attribute* attr = node->findAttribute(kSchemaAndroid, u"fragment");
+ xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"fragment");
if (attr && util::isJavaClassName(attr->value)) {
addClass(node->lineNumber, attr->value);
}
@@ -156,7 +154,7 @@ struct ManifestVisitor : public BaseVisitor {
}
} else if (node->name == u"application") {
getName = true;
- xml::Attribute* attr = node->findAttribute(kSchemaAndroid, u"backupAgent");
+ xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"backupAgent");
if (attr) {
Maybe<std::u16string> result = util::getFullyQualifiedClassName(mPackage,
attr->value);
@@ -171,7 +169,7 @@ struct ManifestVisitor : public BaseVisitor {
}
if (getName) {
- xml::Attribute* attr = node->findAttribute(kSchemaAndroid, u"name");
+ xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"name");
if (attr) {
Maybe<std::u16string> result = util::getFullyQualifiedClassName(mPackage,
attr->value);
diff --git a/tools/aapt2/ProguardRules.h b/tools/aapt2/java/ProguardRules.h
index be61eb9095c2..be61eb9095c2 100644
--- a/tools/aapt2/ProguardRules.h
+++ b/tools/aapt2/java/ProguardRules.h
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index ad701deac16f..0236e988162a 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -17,16 +17,18 @@
#include "AppInfo.h"
#include "Debug.h"
#include "Flags.h"
-#include "JavaClassGenerator.h"
#include "NameMangler.h"
-#include "ProguardRules.h"
#include "XmlDom.h"
#include "compile/IdAssigner.h"
#include "flatten/Archive.h"
#include "flatten/TableFlattener.h"
#include "flatten/XmlFlattener.h"
+#include "java/JavaClassGenerator.h"
+#include "java/ManifestClassGenerator.h"
+#include "java/ProguardRules.h"
#include "link/Linkers.h"
+#include "link/ManifestFixer.h"
#include "link/TableMerger.h"
#include "process/IResourceTableConsumer.h"
#include "process/SymbolTable.h"
@@ -53,6 +55,8 @@ struct LinkOptions {
bool verbose = false;
bool outputToDirectory = false;
Maybe<std::u16string> privateSymbols;
+ Maybe<std::u16string> minSdkVersionDefault;
+ Maybe<std::u16string> targetSdkVersionDefault;
};
struct LinkContext : public IAaptContext {
@@ -239,15 +243,8 @@ struct LinkCommand {
}
Maybe<AppInfo> extractAppInfoFromManifest(XmlResource* xmlRes) {
- xml::Node* node = xmlRes->root.get();
-
- // Find the first xml::Element.
- while (node && !xml::nodeCast<xml::Element>(node)) {
- node = !node->children.empty() ? node->children.front().get() : nullptr;
- }
-
// Make sure the first element is <manifest> with package attribute.
- if (xml::Element* manifestEl = xml::nodeCast<xml::Element>(node)) {
+ if (xml::Element* manifestEl = xml::findRootElement(xmlRes->root.get())) {
if (manifestEl->namespaceUri.empty() && manifestEl->name == u"manifest") {
if (xml::Attribute* packageAttr = manifestEl->findAttribute({}, u"package")) {
return AppInfo{ packageAttr->value };
@@ -354,6 +351,36 @@ struct LinkCommand {
return true;
}
+ bool writeManifestJavaFile(XmlResource* manifestXml) {
+ if (!mOptions.generateJavaClassPath) {
+ return true;
+ }
+
+ std::string outPath = mOptions.generateJavaClassPath.value();
+ file::appendPath(&outPath,
+ file::packageToPath(util::utf16ToUtf8(mContext.getCompilationPackage())));
+ file::mkdirs(outPath);
+ file::appendPath(&outPath, "Manifest.java");
+
+ std::ofstream fout(outPath, std::ofstream::binary);
+ if (!fout) {
+ mContext.getDiagnostics()->error(DiagMessage() << strerror(errno));
+ return false;
+ }
+
+ ManifestClassGenerator generator;
+ if (!generator.generate(mContext.getDiagnostics(), mContext.getCompilationPackage(),
+ manifestXml, &fout)) {
+ return false;
+ }
+
+ if (!fout) {
+ mContext.getDiagnostics()->error(DiagMessage() << strerror(errno));
+ return false;
+ }
+ return true;
+ }
+
bool writeProguardFile(const proguard::KeepSet& keepSet) {
if (!mOptions.generateProguardRulesPath) {
return true;
@@ -539,15 +566,28 @@ struct LinkCommand {
}
{
+ ManifestFixerOptions manifestFixerOptions;
+ manifestFixerOptions.minSdkVersionDefault = mOptions.minSdkVersionDefault;
+ manifestFixerOptions.targetSdkVersionDefault = mOptions.targetSdkVersionDefault;
+ ManifestFixer manifestFixer(manifestFixerOptions);
+ if (!manifestFixer.consume(&mContext, manifestXml.get())) {
+ error = true;
+ }
+
XmlReferenceLinker manifestLinker;
if (manifestLinker.consume(&mContext, manifestXml.get())) {
-
if (!proguard::collectProguardRulesForManifest(Source(mOptions.manifestPath),
manifestXml.get(),
&proguardKeepSet)) {
error = true;
}
+ if (mOptions.generateJavaClassPath) {
+ if (!writeManifestJavaFile(manifestXml.get())) {
+ error = true;
+ }
+ }
+
if (!flattenXml(manifestXml.get(), "AndroidManifest.xml", {},
archiveWriter.get())) {
error = true;
@@ -705,6 +745,7 @@ struct LinkCommand {
int link(const std::vector<StringPiece>& args) {
LinkOptions options;
Maybe<std::string> privateSymbolsPackage;
+ Maybe<std::string> minSdkVersion, targetSdkVersion;
Flags flags = Flags()
.requiredFlag("-o", "Output path", &options.outputPath)
.requiredFlag("--manifest", "Path to the Android manifest to build",
@@ -720,10 +761,15 @@ int link(const std::vector<StringPiece>& args) {
.optionalSwitch("--output-to-dir", "Outputs the APK contents to a directory specified "
"by -o",
&options.outputToDirectory)
+ .optionalFlag("--min-sdk-version", "Default minimum SDK version to use for "
+ "AndroidManifest.xml", &minSdkVersion)
+ .optionalFlag("--target-sdk-version", "Default target SDK version to use for "
+ "AndroidManifest.xml", &targetSdkVersion)
.optionalSwitch("--static-lib", "Generate a static Android library", &options.staticLib)
.optionalFlag("--private-symbols", "Package name to use when generating R.java for "
- "private symbols. If not specified, public and private symbols will "
- "use the application's package name", &privateSymbolsPackage)
+ "private symbols.\n"
+ "If not specified, public and private symbols will use the application's "
+ "package name", &privateSymbolsPackage)
.optionalSwitch("-v", "Enables verbose logging", &options.verbose);
if (!flags.parse("aapt2 link", args, &std::cerr)) {
@@ -734,6 +780,14 @@ int link(const std::vector<StringPiece>& args) {
options.privateSymbols = util::utf8ToUtf16(privateSymbolsPackage.value());
}
+ if (minSdkVersion) {
+ options.minSdkVersionDefault = util::utf8ToUtf16(minSdkVersion.value());
+ }
+
+ if (targetSdkVersion) {
+ options.targetSdkVersionDefault = util::utf8ToUtf16(targetSdkVersion.value());
+ }
+
LinkCommand cmd = { options };
return cmd.run(flags.getArgs());
}
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
new file mode 100644
index 000000000000..52d942670243
--- /dev/null
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ResourceUtils.h"
+#include "XmlDom.h"
+
+#include "link/ManifestFixer.h"
+#include "util/Util.h"
+
+namespace aapt {
+
+static bool verifyManifest(IAaptContext* context, const Source& source, xml::Element* manifestEl) {
+ bool error = false;
+
+ xml::Attribute* attr = manifestEl->findAttribute({}, u"package");
+ if (!attr) {
+ context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
+ << "missing 'package' attribute");
+ error = true;
+ } else if (ResourceUtils::isReference(attr->value)) {
+ context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
+ << "value for attribute 'package' must not be a "
+ "reference");
+ error = true;
+ } else if (!util::isJavaPackageName(attr->value)) {
+ context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
+ << "invalid package name '" << attr->value << "'");
+ error = true;
+ }
+
+ return !error;
+}
+
+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() });
+ }
+
+ 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() });
+ }
+ return true;
+}
+
+bool ManifestFixer::consume(IAaptContext* context, XmlResource* doc) {
+ xml::Element* root = xml::findRootElement(doc->root.get());
+ if (!root || !root->namespaceUri.empty() || root->name != u"manifest") {
+ context->getDiagnostics()->error(DiagMessage(doc->file.source)
+ << "root tag must be <manifest>");
+ return false;
+ }
+
+ if (!verifyManifest(context, doc->file.source, 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;
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
new file mode 100644
index 000000000000..16e161dc40d8
--- /dev/null
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_LINK_MANIFESTFIXER_H
+#define AAPT_LINK_MANIFESTFIXER_H
+
+#include "process/IResourceTableConsumer.h"
+
+namespace aapt {
+
+struct ManifestFixerOptions {
+ Maybe<std::u16string> minSdkVersionDefault;
+ Maybe<std::u16string> targetSdkVersionDefault;
+};
+
+/**
+ * Verifies that the manifest is correctly formed and inserts defaults
+ * where specified with ManifestFixerOptions.
+ */
+struct ManifestFixer : public IXmlResourceConsumer {
+ ManifestFixerOptions mOptions;
+
+ ManifestFixer(const ManifestFixerOptions& options) : mOptions(options) {
+ }
+
+ bool consume(IAaptContext* context, XmlResource* doc) override;
+};
+
+} // namespace aapt
+
+#endif /* AAPT_LINK_MANIFESTFIXER_H */
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
new file mode 100644
index 000000000000..5c5d8afa610d
--- /dev/null
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "link/ManifestFixer.h"
+
+#include "test/Builders.h"
+#include "test/Context.h"
+
+#include <gtest/gtest.h>
+
+namespace aapt {
+
+struct ManifestFixerTest : public ::testing::Test {
+ std::unique_ptr<IAaptContext> mContext;
+
+ void SetUp() override {
+ mContext = test::ContextBuilder()
+ .setCompilationPackage(u"android")
+ .setPackageId(0x01)
+ .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+ .setSymbolTable(test::StaticSymbolTableBuilder()
+ .addSymbol(u"@android:attr/package", ResourceId(0x01010000),
+ test::AttributeBuilder()
+ .setTypeMask(android::ResTable_map::TYPE_STRING)
+ .build())
+ .addSymbol(u"@android:attr/minSdkVersion", ResourceId(0x01010001),
+ test::AttributeBuilder()
+ .setTypeMask(android::ResTable_map::TYPE_STRING |
+ android::ResTable_map::TYPE_INTEGER)
+ .build())
+ .addSymbol(u"@android:attr/targetSdkVersion", ResourceId(0x01010002),
+ test::AttributeBuilder()
+ .setTypeMask(android::ResTable_map::TYPE_STRING |
+ android::ResTable_map::TYPE_INTEGER)
+ .build())
+ .addSymbol(u"@android:string/str", ResourceId(0x01060000))
+ .build())
+ .build();
+ }
+
+ std::unique_ptr<XmlResource> verify(const StringPiece& str) {
+ return verifyWithOptions(str, {});
+ }
+
+ std::unique_ptr<XmlResource> verifyWithOptions(const StringPiece& str,
+ const ManifestFixerOptions& options) {
+ std::unique_ptr<XmlResource> doc = test::buildXmlDom(str);
+ ManifestFixer fixer(options);
+ if (fixer.consume(mContext.get(), doc.get())) {
+ return doc;
+ }
+ return {};
+ }
+};
+
+TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) {
+ EXPECT_EQ(nullptr, verify("<other-tag />"));
+ EXPECT_EQ(nullptr, verify("<ns:manifest xmlns:ns=\"com\" />"));
+ EXPECT_NE(nullptr, verify("<manifest package=\"android\"></manifest>"));
+}
+
+TEST_F(ManifestFixerTest, EnsureManifestHasPackage) {
+ EXPECT_NE(nullptr, verify("<manifest package=\"android\" />"));
+ EXPECT_NE(nullptr, verify("<manifest package=\"com.android\" />"));
+ EXPECT_NE(nullptr, verify("<manifest package=\"com.android.google\" />"));
+ EXPECT_EQ(nullptr, verify("<manifest package=\"com.android.google.Class$1\" />"));
+ EXPECT_EQ(nullptr,
+ verify("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "
+ "android:package=\"com.android\" />"));
+ EXPECT_EQ(nullptr, verify("<manifest package=\"@string/str\" />"));
+}
+
+
+
+TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
+ ManifestFixerOptions options = { std::u16string(u"8"), std::u16string(u"22") };
+
+ std::unique_ptr<XmlResource> doc = verifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
+ </manifest>)EOF", options);
+ ASSERT_NE(nullptr, doc);
+
+ xml::Element* el;
+ xml::Attribute* attr;
+
+ el = xml::findRootElement(doc->root.get());
+ ASSERT_NE(nullptr, el);
+ el = el->findChild({}, u"uses-sdk");
+ ASSERT_NE(nullptr, el);
+ attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
+ ASSERT_NE(nullptr, attr);
+ EXPECT_EQ(u"7", attr->value);
+ attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
+ ASSERT_NE(nullptr, attr);
+ EXPECT_EQ(u"21", attr->value);
+
+ doc = verifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <uses-sdk android:targetSdkVersion="21" />
+ </manifest>)EOF", options);
+ ASSERT_NE(nullptr, doc);
+
+ el = xml::findRootElement(doc->root.get());
+ ASSERT_NE(nullptr, el);
+ el = el->findChild({}, u"uses-sdk");
+ ASSERT_NE(nullptr, el);
+ attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
+ ASSERT_NE(nullptr, attr);
+ EXPECT_EQ(u"8", attr->value);
+ attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
+ ASSERT_NE(nullptr, attr);
+ EXPECT_EQ(u"21", attr->value);
+
+ doc = verifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <uses-sdk />
+ </manifest>)EOF", options);
+ ASSERT_NE(nullptr, doc);
+
+ el = xml::findRootElement(doc->root.get());
+ ASSERT_NE(nullptr, el);
+ el = el->findChild({}, u"uses-sdk");
+ ASSERT_NE(nullptr, el);
+ attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
+ ASSERT_NE(nullptr, attr);
+ EXPECT_EQ(u"8", attr->value);
+ attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
+ ASSERT_NE(nullptr, attr);
+ EXPECT_EQ(u"22", attr->value);
+
+ doc = verifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android" />)EOF", options);
+ ASSERT_NE(nullptr, doc);
+
+ el = xml::findRootElement(doc->root.get());
+ ASSERT_NE(nullptr, el);
+ el = el->findChild({}, u"uses-sdk");
+ ASSERT_NE(nullptr, el);
+ attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
+ ASSERT_NE(nullptr, attr);
+ EXPECT_EQ(u"8", attr->value);
+ attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
+ ASSERT_NE(nullptr, attr);
+ EXPECT_EQ(u"22", attr->value);
+}
+
+} // namespace aapt
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 1b510e756855..89cd9725227a 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -19,8 +19,8 @@
#include "ResourceTable.h"
#include "ResourceValues.h"
-#include "util/Util.h"
#include "XmlDom.h"
+#include "util/Util.h"
#include "test/Common.h"
diff --git a/tools/aapt2/unflatten/BinaryResourceParser.cpp b/tools/aapt2/unflatten/BinaryResourceParser.cpp
index 314c1e84f44f..0d17e8467d32 100644
--- a/tools/aapt2/unflatten/BinaryResourceParser.cpp
+++ b/tools/aapt2/unflatten/BinaryResourceParser.cpp
@@ -116,7 +116,7 @@ bool BinaryResourceParser::getSymbol(const void* data, ResourceNameRef* outSymbo
if (util::deviceToHost32(mSymbolEntries[i].offset) == offset) {
// This offset is a symbol!
const StringPiece16 str = util::getString(
- mSymbolPool, util::deviceToHost32(mSymbolEntries[i].stringIndex));
+ mSymbolPool, util::deviceToHost32(mSymbolEntries[i].name.index));
StringPiece16 typeStr;
ResourceUtils::extractResourceName(str, &outSymbol->package, &typeStr,
@@ -425,8 +425,14 @@ bool BinaryResourceParser::parsePublic(const ResourceTablePackage* package,
Symbol symbol;
if (mSourcePool.getError() == NO_ERROR) {
symbol.source.path = util::utf16ToUtf8(util::getString(
- mSourcePool, util::deviceToHost32(entry->source.index)));
- symbol.source.line = util::deviceToHost32(entry->sourceLine);
+ mSourcePool, util::deviceToHost32(entry->source.path.index)));
+ symbol.source.line = util::deviceToHost32(entry->source.line);
+ }
+
+ StringPiece16 comment = util::getString(mSourcePool,
+ util::deviceToHost32(entry->source.comment.index));
+ if (!comment.empty()) {
+ symbol.comment = comment.toString();
}
switch (util::deviceToHost16(entry->state)) {
@@ -560,7 +566,7 @@ bool BinaryResourceParser::parseType(const ResourceTablePackage* package,
Source source = mSource;
if (sourceBlock) {
size_t len;
- const char* str = mSourcePool.string8At(util::deviceToHost32(sourceBlock->pathIndex),
+ const char* str = mSourcePool.string8At(util::deviceToHost32(sourceBlock->path.index),
&len);
if (str) {
source.path.assign(str, len);
@@ -568,6 +574,12 @@ bool BinaryResourceParser::parseType(const ResourceTablePackage* package,
source.line = util::deviceToHost32(sourceBlock->line);
}
+ StringPiece16 comment = util::getString(mSourcePool,
+ util::deviceToHost32(sourceBlock->comment.index));
+ if (!comment.empty()) {
+ resourceValue->setComment(comment);
+ }
+
resourceValue->setSource(source);
if (!mTable->addResourceAllowMangled(name, config, std::move(resourceValue),
mContext->getDiagnostics())) {
@@ -678,8 +690,6 @@ std::unique_ptr<Value> BinaryResourceParser::parseMapEntry(const ResourceNameRef
// fallthrough
case ResourceType::kAttr:
return parseAttr(name, config, map);
- case ResourceType::kIntegerArray:
- // fallthrough
case ResourceType::kArray:
return parseArray(name, config, map);
case ResourceType::kStyleable:
diff --git a/tools/aapt2/util/StringPiece.h b/tools/aapt2/util/StringPiece.h
index 8cbdeae5e892..31deb452b53c 100644
--- a/tools/aapt2/util/StringPiece.h
+++ b/tools/aapt2/util/StringPiece.h
@@ -36,6 +36,7 @@ template <typename TChar>
class BasicStringPiece {
public:
using const_iterator = const TChar*;
+ using difference_type = size_t;
BasicStringPiece();
BasicStringPiece(const BasicStringPiece<TChar>& str);
diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp
index f219b65378ff..59b838587a6a 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -76,6 +76,25 @@ StringPiece16 trimWhitespace(const StringPiece16& str) {
return StringPiece16(start, end - start);
}
+StringPiece trimWhitespace(const StringPiece& str) {
+ if (str.size() == 0 || str.data() == nullptr) {
+ return str;
+ }
+
+ const char* start = str.data();
+ const char* end = str.data() + str.length();
+
+ while (start != end && isspace(*start)) {
+ start++;
+ }
+
+ while (end != start && isspace(*(end - 1))) {
+ end--;
+ }
+
+ return StringPiece(start, end - start);
+}
+
StringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str,
const StringPiece16& allowedChars) {
const auto endIter = str.end();
@@ -170,6 +189,105 @@ Maybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package,
return result;
}
+static size_t consumeDigits(const char16_t* start, const char16_t* end) {
+ const char16_t* c = start;
+ for (; c != end && *c >= u'0' && *c <= u'9'; c++) {}
+ return static_cast<size_t>(c - start);
+}
+
+bool verifyJavaStringFormat(const StringPiece16& str) {
+ const char16_t* c = str.begin();
+ const char16_t* const end = str.end();
+
+ size_t argCount = 0;
+ bool nonpositional = false;
+ while (c != end) {
+ if (*c == u'%' && c + 1 < end) {
+ c++;
+
+ if (*c == u'%') {
+ c++;
+ continue;
+ }
+
+ argCount++;
+
+ size_t numDigits = consumeDigits(c, end);
+ if (numDigits > 0) {
+ c += numDigits;
+ if (c != end && *c != u'$') {
+ // The digits were a size, but not a positional argument.
+ nonpositional = true;
+ }
+ } else if (*c == u'<') {
+ // Reusing last argument, bad idea since positions can be moved around
+ // during translation.
+ nonpositional = true;
+
+ c++;
+
+ // Optionally we can have a $ after
+ if (c != end && *c == u'$') {
+ c++;
+ }
+ } else {
+ nonpositional = true;
+ }
+
+ // Ignore size, width, flags, etc.
+ while (c != end && (*c == u'-' ||
+ *c == u'#' ||
+ *c == u'+' ||
+ *c == u' ' ||
+ *c == u',' ||
+ *c == u'(' ||
+ (*c >= u'0' && *c <= '9'))) {
+ c++;
+ }
+
+ /*
+ * This is a shortcut to detect strings that are going to Time.format()
+ * instead of String.format()
+ *
+ * Comparison of String.format() and Time.format() args:
+ *
+ * String: ABC E GH ST X abcdefgh nost x
+ * Time: DEFGHKMS W Za d hkm s w yz
+ *
+ * Therefore we know it's definitely Time if we have:
+ * DFKMWZkmwyz
+ */
+ if (c != end) {
+ switch (*c) {
+ case 'D':
+ case 'F':
+ case 'K':
+ case 'M':
+ case 'W':
+ case 'Z':
+ case 'k':
+ case 'm':
+ case 'w':
+ case 'y':
+ case 'z':
+ return true;
+ }
+ }
+ }
+
+ if (c != end) {
+ c++;
+ }
+ }
+
+ if (argCount > 1 && nonpositional) {
+ // Multiple arguments were specified, but some or all were non positional. Translated
+ // strings may rearrange the order of the arguments, which will break the string.
+ return false;
+ }
+ return true;
+}
+
static Maybe<char16_t> parseUnicodeCodepoint(const char16_t** start, const char16_t* end) {
char16_t code = 0;
for (size_t i = 0; i < 4 && *start != end; i++, (*start)++) {
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index 402147de32b2..80552a540ec3 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -62,6 +62,8 @@ bool stringEndsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& s
*/
StringPiece16 trimWhitespace(const StringPiece16& str);
+StringPiece trimWhitespace(const StringPiece& str);
+
/**
* UTF-16 isspace(). It basically checks for lower range characters that are
* whitespace.
@@ -156,6 +158,14 @@ inline StringPiece16 getString(const android::ResStringPool& pool, size_t idx) {
return StringPiece16();
}
+/**
+ * Checks that the Java string format contains no non-positional arguments (arguments without
+ * explicitly specifying an index) when there are more than one argument. This is an error
+ * because translations may rearrange the order of the arguments in the string, which will
+ * break the string interpolation.
+ */
+bool verifyJavaStringFormat(const StringPiece16& str);
+
class StringBuilder {
public:
StringBuilder& append(const StringPiece16& str);
diff --git a/tools/aapt2/util/Util_test.cpp b/tools/aapt2/util/Util_test.cpp
index cdba960b8670..9db9fb7f112a 100644
--- a/tools/aapt2/util/Util_test.cpp
+++ b/tools/aapt2/util/Util_test.cpp
@@ -185,4 +185,12 @@ TEST(UtilTest, ExtractResourcePathComponents) {
EXPECT_EQ(suffix, u".");
}
+TEST(UtilTest, VerifyJavaStringFormat) {
+ ASSERT_TRUE(util::verifyJavaStringFormat(u"%09.34f"));
+ ASSERT_TRUE(util::verifyJavaStringFormat(u"%9$.34f %8$"));
+ ASSERT_TRUE(util::verifyJavaStringFormat(u"%% %%"));
+ ASSERT_FALSE(util::verifyJavaStringFormat(u"%09$f %f"));
+ ASSERT_FALSE(util::verifyJavaStringFormat(u"%09f %08s"));
+}
+
} // namespace aapt
diff --git a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
index 5a595970e195..44ce7311a95c 100644
--- a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
@@ -20,9 +20,10 @@ import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import java.io.File;
+import java.nio.ByteBuffer;
/**
- * Delegate that overrides implementation for certain methods in {@link android.text.StaticLayout}
+ * Delegate that overrides implementation for certain methods in {@link android.text.Hyphenator}
* <p/>
* Through the layoutlib_create tool, selected methods of StaticLayout have been replaced
* by calls to methods of the same name in this delegate class.
@@ -38,7 +39,7 @@ public class Hyphenator_Delegate {
return null;
}
- /*package*/ static long loadHyphenator(String patternData) {
+ /*package*/ static long loadHyphenator(ByteBuffer buf, int offset) {
return sDelegateManager.addNewDelegate(new Hyphenator_Delegate());
}
}
diff --git a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
index 1b0ba5156acd..65c0a07bbac4 100644
--- a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
@@ -13,6 +13,7 @@ import android.icu.util.ULocale;
import android.text.Primitive.PrimitiveType;
import android.text.StaticLayout.LineBreaks;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -52,8 +53,8 @@ public class StaticLayout_Delegate {
}
@LayoutlibDelegate
- /*package*/ static long nLoadHyphenator(String patternData) {
- return Hyphenator_Delegate.loadHyphenator(patternData);
+ /*package*/ static long nLoadHyphenator(ByteBuffer buf, int offset) {
+ return Hyphenator_Delegate.loadHyphenator(buf, offset);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 007d07553e80..498be5afe852 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -513,4 +513,8 @@ public class IWindowManagerImpl implements IWindowManager {
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ public void cancelTaskWindowTransition(int taskId) {
+ }
}
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 93b3f4f6710d..4a5702de6096 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
@@ -410,7 +410,7 @@ public final class BridgeContext extends Context {
pushParser(blockParser);
return Pair.of(
mBridgeInflater.inflate(blockParser, parent, attachToRoot),
- true);
+ Boolean.TRUE);
} finally {
popParser();
}
@@ -448,7 +448,7 @@ public final class BridgeContext extends Context {
pushParser(blockParser);
return Pair.of(
mBridgeInflater.inflate(blockParser, parent, attachToRoot),
- false);
+ Boolean.FALSE);
} finally {
popParser();
}
@@ -471,7 +471,7 @@ public final class BridgeContext extends Context {
resource.getName()), null);
}
- return Pair.of(null, false);
+ return Pair.of(null, Boolean.FALSE);
}
@SuppressWarnings("deprecation")
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 299790765e39..11bd15d780fc 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -95,6 +95,13 @@ public final class BridgeWindowSession implements IWindowSession {
}
@Override
+ public void repositionChild(IWindow childWindow, int x, int y, long deferTransactionUntilFrame,
+ Rect outFrame) {
+ // pass for now.
+ return;
+ }
+
+ @Override
public void performDeferredDestroy(IWindow window) {
// pass for now.
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 567002e564b7..42e55e2504de 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -117,11 +117,11 @@ abstract class CustomBar extends LinearLayout {
density = iconLoader.getDensity();
String path = iconLoader.getPath();
// look for a cached bitmap
- Bitmap bitmap = Bridge.getCachedBitmap(path, true /*isFramework*/);
+ Bitmap bitmap = Bridge.getCachedBitmap(path, Boolean.TRUE /*isFramework*/);
if (bitmap == null) {
try {
bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density);
- Bridge.setCachedBitmap(path, bitmap, true /*isFramework*/);
+ Bridge.setCachedBitmap(path, bitmap, Boolean.TRUE /*isFramework*/);
} catch (IOException e) {
return;
}