summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk5
-rw-r--r--api/current.txt79
-rw-r--r--api/system-current.txt58
-rw-r--r--api/test-current.txt79
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java4
-rw-r--r--cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java19
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java38
-rw-r--r--core/java/android/animation/AnimatorSet.java6
-rw-r--r--core/java/android/app/Activity.java14
-rw-r--r--core/java/android/app/ActivityManagerInternal.java10
-rw-r--r--core/java/android/app/ActivityManagerNative.java21
-rw-r--r--core/java/android/app/ActivityThread.java12
-rw-r--r--core/java/android/app/ContextImpl.java47
-rw-r--r--core/java/android/app/IActivityManager.java7
-rw-r--r--core/java/android/app/LoadedApk.java9
-rw-r--r--core/java/android/app/Notification.java64
-rw-r--r--core/java/android/app/PendingIntent.java35
-rw-r--r--core/java/android/app/Presentation.java2
-rw-r--r--core/java/android/app/ResourcesManager.java30
-rw-r--r--core/java/android/app/RetailDemoModeServiceInternal.java (renamed from services/core/java/com/android/server/am/RetailDemoModeServiceInternal.java)10
-rw-r--r--core/java/android/app/SystemServiceRegistry.java2
-rw-r--r--core/java/android/app/WallpaperInfo.java7
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java2
-rw-r--r--core/java/android/app/backup/IBackupManager.aidl8
-rw-r--r--core/java/android/app/job/JobInfo.java15
-rw-r--r--core/java/android/app/usage/NetworkStatsManager.java3
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java272
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java18
-rw-r--r--core/java/android/bluetooth/BluetoothSocket.java21
-rw-r--r--core/java/android/content/ContentResolver.java2
-rw-r--r--core/java/android/content/Context.java8
-rw-r--r--core/java/android/content/ContextWrapper.java8
-rw-r--r--core/java/android/content/pm/EphemeralResolveInfo.java16
-rw-r--r--core/java/android/content/pm/IOtaDexopt.aidl7
-rw-r--r--core/java/android/content/pm/IShortcutService.aidl2
-rw-r--r--core/java/android/content/pm/LauncherApps.java62
-rw-r--r--core/java/android/content/pm/PackageManager.java10
-rw-r--r--core/java/android/content/pm/PackageManagerInternal.java4
-rw-r--r--core/java/android/content/pm/PackageParser.java5
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java136
-rw-r--r--core/java/android/content/pm/ShortcutManager.java5
-rw-r--r--core/java/android/content/res/Configuration.java50
-rw-r--r--core/java/android/content/res/Resources.java11
-rw-r--r--core/java/android/content/res/ResourcesImpl.java34
-rw-r--r--core/java/android/hardware/Sensor.java61
-rw-r--r--core/java/android/hardware/input/InputManagerInternal.java5
-rw-r--r--core/java/android/inputmethodservice/AbstractInputMethodService.java28
-rw-r--r--core/java/android/inputmethodservice/IInputMethodWrapper.java6
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java25
-rw-r--r--core/java/android/net/ConnectivityMetricsLogger.java15
-rw-r--r--core/java/android/net/metrics/DefaultNetworkEvent.java8
-rw-r--r--core/java/android/net/metrics/DhcpClientEvent.java8
-rw-r--r--core/java/android/net/metrics/DhcpErrorEvent.java7
-rw-r--r--core/java/android/net/metrics/DnsEvent.java6
-rw-r--r--core/java/android/net/metrics/IpConnectivityEvent.java28
-rw-r--r--core/java/android/net/metrics/IpConnectivityLog.java22
-rw-r--r--core/java/android/net/metrics/IpManagerEvent.java8
-rw-r--r--core/java/android/net/metrics/IpReachabilityEvent.java10
-rw-r--r--core/java/android/net/metrics/NetworkEvent.java15
-rw-r--r--core/java/android/net/metrics/ValidationProbeEvent.java8
-rw-r--r--core/java/android/os/BatteryStats.java20
-rw-r--r--core/java/android/os/IUserManager.aidl1
-rw-r--r--core/java/android/os/Parcel.java37
-rw-r--r--core/java/android/os/Process.java2
-rw-r--r--core/java/android/os/UserManager.java14
-rw-r--r--core/java/android/print/PrintServiceRecommendationsLoader.java6
-rw-r--r--core/java/android/print/PrintServicesLoader.java11
-rwxr-xr-xcore/java/android/provider/Settings.java25
-rw-r--r--core/java/android/provider/VoicemailContract.java25
-rw-r--r--core/java/android/security/NetworkSecurityPolicy.java15
-rw-r--r--core/java/android/service/quicksettings/IQSService.aidl1
-rw-r--r--core/java/android/service/quicksettings/IQSTileService.aidl5
-rw-r--r--core/java/android/service/quicksettings/TileService.java59
-rw-r--r--core/java/android/util/ArraySet.java26
-rw-r--r--core/java/android/view/Choreographer.java13
-rw-r--r--core/java/android/view/DisplayAdjustments.java10
-rw-r--r--core/java/android/view/DragAndDropPermissions.java57
-rw-r--r--core/java/android/view/KeyEvent.java29
-rw-r--r--core/java/android/view/Surface.java1
-rw-r--r--core/java/android/view/SurfaceControl.java18
-rw-r--r--core/java/android/view/SurfaceView.java69
-rw-r--r--core/java/android/view/View.java13
-rw-r--r--core/java/android/view/ViewRootImpl.java45
-rw-r--r--core/java/android/view/WindowManagerImpl.java20
-rw-r--r--core/java/android/view/WindowManagerPolicy.java2
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java4
-rw-r--r--core/java/android/view/inputmethod/EditorInfo.java4
-rw-r--r--core/java/android/view/inputmethod/InputConnection.java24
-rw-r--r--core/java/android/view/inputmethod/InputConnectionInspector.java20
-rw-r--r--core/java/android/view/inputmethod/InputConnectionWrapper.java4
-rw-r--r--core/java/android/view/inputmethod/InputContentInfo.java66
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java37
-rw-r--r--core/java/android/webkit/WebViewFactory.java49
-rw-r--r--core/java/android/widget/AbsListView.java5
-rw-r--r--core/java/android/widget/PopupWindow.java78
-rw-r--r--core/java/android/widget/Toolbar.java21
-rw-r--r--core/java/com/android/internal/app/LocaleStore.java3
-rw-r--r--core/java/com/android/internal/app/PlatLogoActivity.java6
-rw-r--r--core/java/com/android/internal/app/UnlaunchableAppActivity.java4
-rw-r--r--core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl27
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java32
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java2
-rw-r--r--core/java/com/android/internal/policy/BackdropFrameRenderer.java1
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl1
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl1
-rw-r--r--core/java/com/android/internal/util/StateMachine.java26
-rw-r--r--core/java/com/android/internal/view/IInputConnectionWrapper.java33
-rw-r--r--core/java/com/android/internal/view/IInputContext.aidl2
-rw-r--r--core/java/com/android/internal/view/IInputContextCallback.aidl2
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl5
-rw-r--r--core/java/com/android/internal/view/InputConnectionWrapper.java39
-rw-r--r--core/jni/android_app_ApplicationLoaders.cpp13
-rw-r--r--core/jni/android_hardware_SensorManager.cpp17
-rw-r--r--core/jni/android_util_Process.cpp10
-rw-r--r--core/jni/android_view_DisplayEventReceiver.cpp8
-rw-r--r--core/jni/android_view_RenderNode.cpp51
-rw-r--r--core/jni/android_view_SurfaceControl.cpp22
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp10
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/res/res/drawable-nodpi/platlogo.xml6
-rw-r--r--core/res/res/layout/immersive_mode_cling.xml4
-rw-r--r--core/res/res/layout/unsupported_display_size_dialog_content.xml31
-rw-r--r--core/res/res/values-af/strings.xml22
-rw-r--r--core/res/res/values-am/strings.xml22
-rw-r--r--core/res/res/values-ar/strings.xml14
-rw-r--r--core/res/res/values-az-rAZ/strings.xml14
-rw-r--r--core/res/res/values-bg/strings.xml22
-rw-r--r--core/res/res/values-bn-rBD/strings.xml31
-rw-r--r--core/res/res/values-ca/strings.xml22
-rw-r--r--core/res/res/values-cs/strings.xml22
-rw-r--r--core/res/res/values-da/strings.xml22
-rw-r--r--core/res/res/values-de/strings.xml22
-rw-r--r--core/res/res/values-el/strings.xml22
-rw-r--r--core/res/res/values-en-rAU/strings.xml14
-rw-r--r--core/res/res/values-en-rGB/strings.xml14
-rw-r--r--core/res/res/values-en-rIN/strings.xml14
-rw-r--r--core/res/res/values-es-rUS/strings.xml22
-rw-r--r--core/res/res/values-es/strings.xml22
-rw-r--r--core/res/res/values-et-rEE/strings.xml22
-rw-r--r--core/res/res/values-eu-rES-watch/styles_material.xml35
-rw-r--r--core/res/res/values-eu-rES/strings.xml31
-rw-r--r--core/res/res/values-fa/strings.xml22
-rw-r--r--core/res/res/values-fi/strings.xml22
-rw-r--r--core/res/res/values-fr-rCA/strings.xml22
-rw-r--r--core/res/res/values-fr/strings.xml22
-rw-r--r--core/res/res/values-gl-rES/strings.xml31
-rw-r--r--core/res/res/values-gu-rIN/strings.xml31
-rw-r--r--core/res/res/values-hi-watch/styles_material.xml35
-rw-r--r--core/res/res/values-hi/strings.xml22
-rw-r--r--core/res/res/values-hr/strings.xml22
-rw-r--r--core/res/res/values-hu/strings.xml22
-rw-r--r--core/res/res/values-hy-rAM-watch/styles_material.xml35
-rw-r--r--core/res/res/values-hy-rAM/strings.xml22
-rw-r--r--core/res/res/values-in/strings.xml22
-rw-r--r--core/res/res/values-is-rIS/strings.xml31
-rw-r--r--core/res/res/values-it/strings.xml22
-rw-r--r--core/res/res/values-iw/strings.xml22
-rw-r--r--core/res/res/values-ja/strings.xml22
-rw-r--r--core/res/res/values-ka-rGE-watch/styles_material.xml35
-rw-r--r--core/res/res/values-ka-rGE/strings.xml22
-rw-r--r--core/res/res/values-kk-rKZ-watch/styles_material.xml35
-rw-r--r--core/res/res/values-kk-rKZ/strings.xml31
-rw-r--r--core/res/res/values-km-rKH/strings.xml22
-rw-r--r--core/res/res/values-kn-rIN/strings.xml31
-rw-r--r--core/res/res/values-ko-watch/styles_material.xml2
-rw-r--r--core/res/res/values-ko/strings.xml22
-rw-r--r--core/res/res/values-ky-rKG-watch/styles_material.xml35
-rw-r--r--core/res/res/values-ky-rKG/strings.xml22
-rw-r--r--core/res/res/values-lo-rLA/strings.xml22
-rw-r--r--core/res/res/values-lt/strings.xml22
-rw-r--r--core/res/res/values-lv/strings.xml22
-rw-r--r--core/res/res/values-mk-rMK/strings.xml31
-rw-r--r--core/res/res/values-ml-rIN/strings.xml31
-rw-r--r--core/res/res/values-mn-rMN/strings.xml22
-rw-r--r--core/res/res/values-mr-rIN-watch/styles_material.xml2
-rw-r--r--core/res/res/values-mr-rIN/strings.xml31
-rw-r--r--core/res/res/values-ms-rMY/strings.xml22
-rw-r--r--core/res/res/values-my-rMM-watch/styles_material.xml2
-rw-r--r--core/res/res/values-my-rMM/strings.xml23
-rw-r--r--core/res/res/values-nb/strings.xml22
-rw-r--r--core/res/res/values-ne-rNP/strings.xml14
-rw-r--r--core/res/res/values-nl/strings.xml22
-rw-r--r--core/res/res/values-pa-rIN/strings.xml31
-rw-r--r--core/res/res/values-pl/strings.xml22
-rw-r--r--core/res/res/values-pt-rBR/strings.xml22
-rw-r--r--core/res/res/values-pt-rPT/strings.xml24
-rw-r--r--core/res/res/values-pt/strings.xml22
-rw-r--r--core/res/res/values-ro-watch/styles_material.xml35
-rw-r--r--core/res/res/values-ro/strings.xml22
-rw-r--r--core/res/res/values-ru-watch/styles_material.xml35
-rw-r--r--core/res/res/values-ru/strings.xml22
-rw-r--r--core/res/res/values-si-rLK/strings.xml14
-rw-r--r--core/res/res/values-sk/strings.xml22
-rw-r--r--core/res/res/values-sl/strings.xml22
-rw-r--r--core/res/res/values-sq-rAL/strings.xml31
-rw-r--r--core/res/res/values-sr-watch/styles_material.xml35
-rw-r--r--core/res/res/values-sr/strings.xml22
-rw-r--r--core/res/res/values-sv/strings.xml22
-rw-r--r--core/res/res/values-sw-watch/styles_material.xml2
-rw-r--r--core/res/res/values-sw/strings.xml22
-rw-r--r--core/res/res/values-ta-rIN-watch/styles_material.xml35
-rw-r--r--core/res/res/values-ta-rIN/strings.xml31
-rw-r--r--core/res/res/values-te-rIN/strings.xml31
-rw-r--r--core/res/res/values-th/strings.xml22
-rw-r--r--core/res/res/values-tl/strings.xml22
-rw-r--r--core/res/res/values-tr/strings.xml22
-rw-r--r--core/res/res/values-uk/strings.xml22
-rw-r--r--core/res/res/values-ur-rPK-watch/styles_material.xml35
-rw-r--r--core/res/res/values-ur-rPK/strings.xml31
-rw-r--r--core/res/res/values-uz-rUZ/strings.xml89
-rw-r--r--core/res/res/values-vi/strings.xml22
-rw-r--r--core/res/res/values-zh-rCN-watch/styles_material.xml35
-rw-r--r--core/res/res/values-zh-rCN/strings.xml22
-rw-r--r--core/res/res/values-zh-rHK/strings.xml14
-rw-r--r--core/res/res/values-zh-rTW/strings.xml14
-rw-r--r--core/res/res/values-zu/strings.xml14
-rw-r--r--core/res/res/values/attrs.xml17
-rw-r--r--core/res/res/values/colors_device_defaults.xml1
-rw-r--r--core/res/res/values/colors_material.xml2
-rw-r--r--core/res/res/values/config.xml8
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--core/res/res/values/strings.xml23
-rw-r--r--core/res/res/values/styles.xml2
-rw-r--r--core/res/res/values/symbols.xml12
-rw-r--r--core/res/res/values/themes.xml2
-rw-r--r--core/res/res/values/themes_device_defaults.xml60
-rw-r--r--core/res/res/values/themes_material.xml9
-rw-r--r--core/tests/coretests/src/android/content/res/ResourcesManagerTest.java4
-rw-r--r--core/tests/notificationtests/src/android/app/NotificationStressTest.java12
-rw-r--r--docs/html-intl/intl/es/preview/images/bundles.pngbin102120 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/bundles_2x.pngbin330229 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/datasaver.pngbin32646 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/doze-diagram-1.pngbin19173 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/doze-diagram-2.pngbin28396 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/inline-reply.pngbin28843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/inline-reply_2x.pngbin68982 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/inline-type-reply.pngbin84611 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/inline-type-reply_2x.pngbin267875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/m-preview-timeline-crop.pngbin10205 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/m-preview-timeline.pngbin13002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/mw-portrait.pngbin110834 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/mw-splitscreen.pngbin170688 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/mw-splitscreen_2x.pngbin558952 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/n-preview-setup.pngbin67824 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/notifications-1.pngbin146036 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/notifications-2.pngbin129506 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/notifications-3.pngbin201758 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/notifications-card.pngbin59002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/pip-active.pngbin382631 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/pip-button.pngbin3942 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/quicksettings.pngbin124419 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/sample-activenotifications.pngbin15593 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/sample-directboot.pngbin12825 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/sample-messagingservice.pngbin18875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/sample-multiwindow.pngbin24034 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/sample-scopeddirectoryaccess.pngbin8296 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/scoped-folder-access-dont-ask.pngbin67327 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/scoped-folder-access-dont-ask_2x.pngbin226699 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/scoped-folder-access-framed.pngbin70150 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/scoped-folder-access-framed_2x.pngbin255217 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/screen-zoom-1.pngbin787843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/screen-zoom-2.pngbin933219 -> 0 bytes
-rw-r--r--docs/html-intl/intl/es/preview/images/studio-jdk-location.jpgbin82534 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/bundles.pngbin102120 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/bundles_2x.pngbin330229 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/datasaver.pngbin32646 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/doze-diagram-1.pngbin19173 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/doze-diagram-2.pngbin28396 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/inline-reply.pngbin28843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/inline-reply_2x.pngbin68982 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/inline-type-reply.pngbin84611 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/inline-type-reply_2x.pngbin267875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/m-preview-timeline-crop.pngbin10205 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/m-preview-timeline.pngbin13002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/mw-portrait.pngbin110834 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/mw-splitscreen.pngbin170688 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/mw-splitscreen_2x.pngbin558952 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/n-preview-setup.pngbin67824 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/notifications-1.pngbin146036 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/notifications-2.pngbin129506 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/notifications-3.pngbin201758 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/notifications-card.pngbin59002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/pip-active.pngbin382631 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/pip-button.pngbin3942 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/quicksettings.pngbin124419 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/sample-activenotifications.pngbin15593 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/sample-directboot.pngbin12825 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/sample-messagingservice.pngbin18875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/sample-multiwindow.pngbin24034 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/sample-scopeddirectoryaccess.pngbin8296 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/scoped-folder-access-dont-ask.pngbin67327 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/scoped-folder-access-dont-ask_2x.pngbin226699 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/scoped-folder-access-framed.pngbin70150 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/scoped-folder-access-framed_2x.pngbin255217 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/screen-zoom-1.pngbin787843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/screen-zoom-2.pngbin933219 -> 0 bytes
-rw-r--r--docs/html-intl/intl/in/preview/images/studio-jdk-location.jpgbin82534 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/bundles.pngbin102120 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/bundles_2x.pngbin330229 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/datasaver.pngbin32646 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/doze-diagram-1.pngbin19173 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/doze-diagram-2.pngbin28396 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/inline-reply.pngbin28843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/inline-reply_2x.pngbin68982 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/inline-type-reply.pngbin84611 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/inline-type-reply_2x.pngbin267875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/m-preview-timeline-crop.pngbin10205 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/m-preview-timeline.pngbin13002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/mw-portrait.pngbin110834 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/mw-splitscreen.pngbin170688 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/mw-splitscreen_2x.pngbin558952 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/n-preview-setup.pngbin67824 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/notifications-1.pngbin146036 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/notifications-2.pngbin129506 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/notifications-3.pngbin201758 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/notifications-card.pngbin59002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/pip-active.pngbin382631 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/pip-button.pngbin3942 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/quicksettings.pngbin124419 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/sample-activenotifications.pngbin15593 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/sample-directboot.pngbin12825 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/sample-messagingservice.pngbin18875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/sample-multiwindow.pngbin24034 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/sample-scopeddirectoryaccess.pngbin8296 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/scoped-folder-access-dont-ask.pngbin67327 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/scoped-folder-access-dont-ask_2x.pngbin226699 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/scoped-folder-access-framed.pngbin70150 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/scoped-folder-access-framed_2x.pngbin255217 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/screen-zoom-1.pngbin787843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/screen-zoom-2.pngbin933219 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ja/preview/images/studio-jdk-location.jpgbin82534 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/bundles.pngbin102120 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/bundles_2x.pngbin330229 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/datasaver.pngbin32646 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/doze-diagram-1.pngbin19173 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/doze-diagram-2.pngbin28396 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/inline-reply.pngbin28843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/inline-reply_2x.pngbin68982 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/inline-type-reply.pngbin84611 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/inline-type-reply_2x.pngbin267875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/m-preview-timeline-crop.pngbin10205 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/m-preview-timeline.pngbin13002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/mw-portrait.pngbin110834 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/mw-splitscreen.pngbin170688 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/mw-splitscreen_2x.pngbin558952 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/n-preview-setup.pngbin67824 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/notifications-1.pngbin146036 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/notifications-2.pngbin129506 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/notifications-3.pngbin201758 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/notifications-card.pngbin59002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/pip-active.pngbin382631 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/pip-button.pngbin3942 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/quicksettings.pngbin124419 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/sample-activenotifications.pngbin15593 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/sample-directboot.pngbin12825 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/sample-messagingservice.pngbin18875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/sample-multiwindow.pngbin24034 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/sample-scopeddirectoryaccess.pngbin8296 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/scoped-folder-access-dont-ask.pngbin67327 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/scoped-folder-access-dont-ask_2x.pngbin226699 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/scoped-folder-access-framed.pngbin70150 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/scoped-folder-access-framed_2x.pngbin255217 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/screen-zoom-1.pngbin787843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/screen-zoom-2.pngbin933219 -> 0 bytes
-rw-r--r--docs/html-intl/intl/ko/preview/images/studio-jdk-location.jpgbin82534 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/bundles.pngbin102120 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/bundles_2x.pngbin330229 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/datasaver.pngbin32646 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/doze-diagram-1.pngbin19173 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/doze-diagram-2.pngbin28396 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/inline-reply.pngbin28843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/inline-reply_2x.pngbin68982 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/inline-type-reply.pngbin84611 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/inline-type-reply_2x.pngbin267875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/m-preview-timeline-crop.pngbin10205 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/m-preview-timeline.pngbin13002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/mw-portrait.pngbin110834 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/mw-splitscreen.pngbin170688 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/mw-splitscreen_2x.pngbin558952 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/n-preview-setup.pngbin67824 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/notifications-1.pngbin146036 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/notifications-2.pngbin129506 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/notifications-3.pngbin201758 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/notifications-card.pngbin59002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/pip-active.pngbin382631 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/pip-button.pngbin3942 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/quicksettings.pngbin124419 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/sample-activenotifications.pngbin15593 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/sample-directboot.pngbin12825 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/sample-messagingservice.pngbin18875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/sample-multiwindow.pngbin24034 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/sample-scopeddirectoryaccess.pngbin8296 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-dont-ask.pngbin67327 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-dont-ask_2x.pngbin226699 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-framed.pngbin70150 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-framed_2x.pngbin255217 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/screen-zoom-1.pngbin787843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/screen-zoom-2.pngbin933219 -> 0 bytes
-rw-r--r--docs/html-intl/intl/pt-br/preview/images/studio-jdk-location.jpgbin82534 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/bundles.pngbin102120 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/bundles_2x.pngbin330229 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/datasaver.pngbin32646 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/doze-diagram-1.pngbin19173 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/doze-diagram-2.pngbin28396 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/inline-reply.pngbin28843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/inline-reply_2x.pngbin68982 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/inline-type-reply.pngbin84611 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/inline-type-reply_2x.pngbin267875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/m-preview-timeline-crop.pngbin10205 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/m-preview-timeline.pngbin13002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/mw-portrait.pngbin110834 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/mw-splitscreen.pngbin170688 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/mw-splitscreen_2x.pngbin558952 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/n-preview-setup.pngbin67824 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/notifications-1.pngbin146036 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/notifications-2.pngbin129506 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/notifications-3.pngbin201758 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/notifications-card.pngbin59002 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/pip-active.pngbin382631 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/pip-button.pngbin3942 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/quicksettings.pngbin124419 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/sample-activenotifications.pngbin15593 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/sample-directboot.pngbin12825 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/sample-messagingservice.pngbin18875 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/sample-multiwindow.pngbin24034 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/sample-scopeddirectoryaccess.pngbin8296 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-dont-ask.pngbin67327 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-dont-ask_2x.pngbin226699 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-framed.pngbin70150 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-framed_2x.pngbin255217 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/screen-zoom-1.pngbin787843 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/screen-zoom-2.pngbin933219 -> 0 bytes
-rw-r--r--docs/html-intl/intl/zh-cn/preview/images/studio-jdk-location.jpgbin82534 -> 0 bytes
-rw-r--r--docs/html/_redirects.yaml104
-rw-r--r--docs/html/distribute/essentials/quality/core.jd2
-rw-r--r--docs/html/distribute/googleplay/guide.jd102
-rw-r--r--docs/html/google/play/billing/billing_admin.jd9
-rw-r--r--docs/html/google/play/billing/billing_testing.jd44
-rwxr-xr-xdocs/html/guide/topics/renderscript/compute.jd2
-rw-r--r--docs/html/images/cards/card-secrets-playbook_2x.jpgbin0 -> 12270 bytes
-rw-r--r--docs/html/images/gp-secrets-playbook-lg.pngbin0 -> 148384 bytes
-rw-r--r--docs/html/images/gp-secrets-playbook.pngbin0 -> 12009 bytes
-rw-r--r--docs/html/images/testing/test-types.zipbin0 -> 15136 bytes
-rw-r--r--docs/html/images/testing/test-types_2x.pngbin0 -> 89115 bytes
-rw-r--r--docs/html/jd_extras_en.js4
-rw-r--r--docs/html/ndk/downloads/index.jd222
-rw-r--r--docs/html/ndk/downloads/revision_history.jd38
-rw-r--r--docs/html/ndk/guides/setup.jd3
-rw-r--r--docs/html/preview/features/picture-in-picture.jd8
-rw-r--r--docs/html/sdk/sdk_vars.cs25
-rw-r--r--docs/html/topic/libraries/data-binding/index.jd235
-rw-r--r--docs/html/training/articles/user-data-ids.jd15
-rw-r--r--docs/html/training/auto/audio/index.jd30
-rw-r--r--docs/html/training/material/animations.jd16
-rw-r--r--docs/html/training/testing/start/index.jd739
-rw-r--r--docs/html/training/testing/unit-testing/instrumented-unit-tests.jd309
-rw-r--r--docs/html/training/testing/unit-testing/local-unit-tests.jd78
-rw-r--r--docs/html/wear/preview/api-overview.jd52
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java49
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java4
-rw-r--r--libs/hwui/AnimationContext.cpp2
-rw-r--r--libs/hwui/FrameBuilder.cpp1
-rw-r--r--libs/hwui/LayerUpdateQueue.cpp1
-rw-r--r--libs/hwui/PropertyValuesAnimatorSet.cpp4
-rw-r--r--libs/hwui/RecordingCanvas.cpp3
-rw-r--r--libs/hwui/RenderNode.h6
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp1
-rw-r--r--libs/hwui/renderthread/TimeLord.cpp4
-rw-r--r--libs/hwui/renderthread/TimeLord.h1
-rw-r--r--libs/hwui/tests/unit/FrameBuilderTests.cpp34
-rw-r--r--libs/hwui/tests/unit/LayerUpdateQueueTests.cpp6
-rw-r--r--libs/hwui/tests/unit/RecordingCanvasTests.cpp30
-rw-r--r--media/java/android/media/AudioRecord.java6
-rw-r--r--media/java/android/media/AudioTrack.java6
-rw-r--r--media/java/android/media/MediaCodec.java125
-rw-r--r--media/java/android/media/MediaCodecInfo.java95
-rw-r--r--media/java/android/media/MediaCodecList.java6
-rw-r--r--media/java/android/media/MediaExtractor.java106
-rw-r--r--media/java/android/media/MediaFormat.java14
-rw-r--r--media/java/android/media/MediaMuxer.java115
-rw-r--r--media/java/android/media/MediaPlayer.java18
-rw-r--r--packages/CtsShim/CtsShim.apkbin4824 -> 4807 bytes
-rw-r--r--packages/CtsShim/CtsShimPriv.apkbin6068 -> 6044 bytes
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java8
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java18
-rw-r--r--packages/EasterEgg/Android.mk21
-rw-r--r--packages/EasterEgg/AndroidManifest.xml75
-rw-r--r--packages/EasterEgg/res/drawable/back.xml22
-rw-r--r--packages/EasterEgg/res/drawable/belly.xml22
-rw-r--r--packages/EasterEgg/res/drawable/body.xml22
-rw-r--r--packages/EasterEgg/res/drawable/bowtie.xml22
-rw-r--r--packages/EasterEgg/res/drawable/cap.xml22
-rw-r--r--packages/EasterEgg/res/drawable/collar.xml22
-rw-r--r--packages/EasterEgg/res/drawable/face_spot.xml22
-rw-r--r--packages/EasterEgg/res/drawable/food_bits.xml33
-rw-r--r--packages/EasterEgg/res/drawable/food_chicken.xml39
-rw-r--r--packages/EasterEgg/res/drawable/food_dish.xml24
-rw-r--r--packages/EasterEgg/res/drawable/food_donut.xml24
-rw-r--r--packages/EasterEgg/res/drawable/food_sysuituna.xml24
-rw-r--r--packages/EasterEgg/res/drawable/foot1.xml22
-rw-r--r--packages/EasterEgg/res/drawable/foot2.xml22
-rw-r--r--packages/EasterEgg/res/drawable/foot3.xml22
-rw-r--r--packages/EasterEgg/res/drawable/foot4.xml22
-rw-r--r--packages/EasterEgg/res/drawable/head.xml22
-rw-r--r--packages/EasterEgg/res/drawable/ic_close.xml24
-rw-r--r--packages/EasterEgg/res/drawable/ic_share.xml24
-rw-r--r--packages/EasterEgg/res/drawable/icon.xml37
-rw-r--r--packages/EasterEgg/res/drawable/left_ear.xml22
-rw-r--r--packages/EasterEgg/res/drawable/left_ear_inside.xml22
-rw-r--r--packages/EasterEgg/res/drawable/left_eye.xml22
-rw-r--r--packages/EasterEgg/res/drawable/leg1.xml22
-rw-r--r--packages/EasterEgg/res/drawable/leg2.xml22
-rw-r--r--packages/EasterEgg/res/drawable/leg2_shadow.xml22
-rw-r--r--packages/EasterEgg/res/drawable/leg3.xml22
-rw-r--r--packages/EasterEgg/res/drawable/leg4.xml22
-rw-r--r--packages/EasterEgg/res/drawable/mouth.xml27
-rw-r--r--packages/EasterEgg/res/drawable/nose.xml22
-rw-r--r--packages/EasterEgg/res/drawable/right_ear.xml22
-rw-r--r--packages/EasterEgg/res/drawable/right_ear_inside.xml23
-rw-r--r--packages/EasterEgg/res/drawable/right_eye.xml22
-rw-r--r--packages/EasterEgg/res/drawable/stat_icon.xml30
-rw-r--r--packages/EasterEgg/res/drawable/tail.xml26
-rw-r--r--packages/EasterEgg/res/drawable/tail_cap.xml22
-rw-r--r--packages/EasterEgg/res/drawable/tail_shadow.xml22
-rw-r--r--packages/EasterEgg/res/layout/cat_view.xml79
-rw-r--r--packages/EasterEgg/res/layout/edit_text.xml30
-rw-r--r--packages/EasterEgg/res/layout/food_layout.xml31
-rw-r--r--packages/EasterEgg/res/layout/neko_activity.xml25
-rw-r--r--packages/EasterEgg/res/values/strings.xml52
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/Cat.java375
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/Food.java60
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java53
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java105
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoLand.java280
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoLockedActivity.java45
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoService.java136
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoTile.java96
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/PrefState.java94
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java5
-rw-r--r--packages/MtpDocumentsProvider/res/values-af/strings.xml25
-rw-r--r--packages/MtpDocumentsProvider/res/values-sv/strings.xml25
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java12
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java39
-rw-r--r--packages/SettingsLib/res/values/colors.xml2
-rw-r--r--packages/SettingsLib/res/values/strings.xml2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java14
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java2
-rw-r--r--packages/SystemUI/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/res/color/notification_guts_buttons.xml2
-rw-r--r--packages/SystemUI/res/color/qs_detail_progress_track.xml20
-rw-r--r--packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml2
-rw-r--r--packages/SystemUI/res/color/qs_user_detail_name.xml2
-rw-r--r--packages/SystemUI/res/color/screen_pinning_nav_icon_highlight_outer.xml (renamed from packages/SystemUI/res/drawable/fab_background.xml)13
-rw-r--r--packages/SystemUI/res/drawable/brightness_mirror_background.xml2
-rw-r--r--packages/SystemUI/res/drawable/ic_brightness_thumb.xml2
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml37
-rw-r--r--packages/SystemUI/res/drawable/notification_header_bg.xml21
-rw-r--r--packages/SystemUI/res/drawable/qs_background_primary.xml2
-rw-r--r--packages/SystemUI/res/drawable/qs_customizer_background.xml2
-rw-r--r--packages/SystemUI/res/drawable/qs_detail_background.xml2
-rw-r--r--packages/SystemUI/res/drawable/quick_header_bg.xml2
-rw-r--r--packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml2
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml37
-rw-r--r--packages/SystemUI/res/drawable/switchbar_background.xml2
-rw-r--r--packages/SystemUI/res/drawable/volume_dialog_background.xml2
-rw-r--r--packages/SystemUI/res/drawable/zen_introduction_message_background.xml2
-rw-r--r--packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml3
-rw-r--r--packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml2
-rw-r--r--packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml3
-rw-r--r--packages/SystemUI/res/layout/notification_guts.xml7
-rw-r--r--packages/SystemUI/res/layout/screen_pinning_request.xml5
-rw-r--r--packages/SystemUI/res/layout/screen_pinning_request_buttons.xml5
-rw-r--r--packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml7
-rw-r--r--packages/SystemUI/res/layout/screen_pinning_request_land_phone.xml3
-rw-r--r--packages/SystemUI/res/layout/screen_pinning_request_text_area.xml4
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded_header.xml195
-rw-r--r--packages/SystemUI/res/layout/switch_bar.xml6
-rw-r--r--packages/SystemUI/res/layout/tile_listing.xml55
-rw-r--r--packages/SystemUI/res/layout/tuner_qs.xml47
-rw-r--r--packages/SystemUI/res/layout/volume_dialog.xml10
-rw-r--r--packages/SystemUI/res/layout/volume_dialog_row.xml56
-rw-r--r--packages/SystemUI/res/layout/volume_zen_footer.xml2
-rw-r--r--packages/SystemUI/res/layout/zen_mode_panel.xml3
-rw-r--r--packages/SystemUI/res/values-af/strings.xml8
-rw-r--r--packages/SystemUI/res/values-af/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-am/strings.xml8
-rw-r--r--packages/SystemUI/res/values-am/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ar/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-az-rAZ/strings.xml13
-rw-r--r--packages/SystemUI/res/values-az-rAZ/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml8
-rw-r--r--packages/SystemUI/res/values-bg/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-bn-rBD/strings.xml8
-rw-r--r--packages/SystemUI/res/values-bn-rBD/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ca/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml10
-rw-r--r--packages/SystemUI/res/values-cs/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-da/strings.xml8
-rw-r--r--packages/SystemUI/res/values-da/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-de/strings.xml8
-rw-r--r--packages/SystemUI/res/values-de/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-el/strings.xml8
-rw-r--r--packages/SystemUI/res/values-el/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml13
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml13
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml13
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml8
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-es/strings.xml8
-rw-r--r--packages/SystemUI/res/values-es/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-et-rEE/strings.xml8
-rw-r--r--packages/SystemUI/res/values-et-rEE/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-eu-rES/strings.xml8
-rw-r--r--packages/SystemUI/res/values-eu-rES/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml8
-rw-r--r--packages/SystemUI/res/values-fa/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml8
-rw-r--r--packages/SystemUI/res/values-fi/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml8
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml8
-rw-r--r--packages/SystemUI/res/values-fr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-gl-rES/strings.xml8
-rw-r--r--packages/SystemUI/res/values-gl-rES/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-gu-rIN/strings.xml11
-rw-r--r--packages/SystemUI/res/values-gu-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml8
-rw-r--r--packages/SystemUI/res/values-hi/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml8
-rw-r--r--packages/SystemUI/res/values-hr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml8
-rw-r--r--packages/SystemUI/res/values-hu/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-hy-rAM/strings.xml8
-rw-r--r--packages/SystemUI/res/values-hy-rAM/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-in/strings.xml8
-rw-r--r--packages/SystemUI/res/values-in/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-is-rIS/strings.xml8
-rw-r--r--packages/SystemUI/res/values-is-rIS/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-it/strings.xml8
-rw-r--r--packages/SystemUI/res/values-it/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml8
-rw-r--r--packages/SystemUI/res/values-iw/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ja/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ka-rGE/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ka-rGE/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-kk-rKZ/strings.xml8
-rw-r--r--packages/SystemUI/res/values-kk-rKZ/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-km-rKH/strings.xml8
-rw-r--r--packages/SystemUI/res/values-km-rKH/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-kn-rIN/strings.xml8
-rw-r--r--packages/SystemUI/res/values-kn-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ko/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ky-rKG/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ky-rKG/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings.xml8
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml8
-rw-r--r--packages/SystemUI/res/values-lt/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml8
-rw-r--r--packages/SystemUI/res/values-lv/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-mk-rMK/strings.xml8
-rw-r--r--packages/SystemUI/res/values-mk-rMK/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ml-rIN/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ml-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-mn-rMN/strings.xml8
-rw-r--r--packages/SystemUI/res/values-mn-rMN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-mr-rIN/strings.xml8
-rw-r--r--packages/SystemUI/res/values-mr-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-my-rMM/strings.xml13
-rw-r--r--packages/SystemUI/res/values-my-rMM/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml8
-rw-r--r--packages/SystemUI/res/values-nb/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ne-rNP/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ne-rNP/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml8
-rw-r--r--packages/SystemUI/res/values-nl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pa-rIN/strings.xml11
-rw-r--r--packages/SystemUI/res/values-pa-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml8
-rw-r--r--packages/SystemUI/res/values-pl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml8
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml8
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml8
-rw-r--r--packages/SystemUI/res/values-pt/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml10
-rw-r--r--packages/SystemUI/res/values-ro/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ru/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-si-rLK/strings.xml13
-rw-r--r--packages/SystemUI/res/values-si-rLK/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml8
-rw-r--r--packages/SystemUI/res/values-sk/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml8
-rw-r--r--packages/SystemUI/res/values-sl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sq-rAL/strings.xml11
-rw-r--r--packages/SystemUI/res/values-sq-rAL/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml8
-rw-r--r--packages/SystemUI/res/values-sr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml8
-rw-r--r--packages/SystemUI/res/values-sv/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml8
-rw-r--r--packages/SystemUI/res/values-sw/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ta-rIN/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ta-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-te-rIN/strings.xml8
-rw-r--r--packages/SystemUI/res/values-te-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-th/strings.xml8
-rw-r--r--packages/SystemUI/res/values-th/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml8
-rw-r--r--packages/SystemUI/res/values-tl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml8
-rw-r--r--packages/SystemUI/res/values-tr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml8
-rw-r--r--packages/SystemUI/res/values-uk/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ur-rPK/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ur-rPK/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-uz-rUZ/strings.xml8
-rw-r--r--packages/SystemUI/res/values-uz-rUZ/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml8
-rw-r--r--packages/SystemUI/res/values-vi/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml8
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml13
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml13
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml13
-rw-r--r--packages/SystemUI/res/values-zu/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values/colors.xml20
-rw-r--r--packages/SystemUI/res/values/dimens.xml13
-rw-r--r--packages/SystemUI/res/values/strings.xml13
-rw-r--r--packages/SystemUI/res/values/strings_tv.xml4
-rw-r--r--packages/SystemUI/res/values/styles.xml34
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUI.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTile.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java101
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java842
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java3
-rw-r--r--packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java5
-rw-r--r--proto/src/metrics_constants.proto21
-rw-r--r--services/Android.mk1
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java72
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java157
-rw-r--r--services/backup/java/com/android/server/backup/Trampoline.java6
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java3
-rw-r--r--services/core/java/com/android/server/AttributeCache.java27
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java74
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java74
-rw-r--r--services/core/java/com/android/server/InputContentUriTokenHandler.java121
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java48
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java9
-rw-r--r--services/core/java/com/android/server/MountService.java25
-rw-r--r--services/core/java/com/android/server/SystemServiceManager.java15
-rw-r--r--services/core/java/com/android/server/VibratorService.java2
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java12
-rwxr-xr-xservices/core/java/com/android/server/am/ActiveServices.java51
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java307
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityRecord.java31
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java62
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java38
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java21
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java2
-rw-r--r--services/core/java/com/android/server/am/CompatModePackages.java56
-rw-r--r--services/core/java/com/android/server/am/PreBootBroadcaster.java49
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java5
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java17
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java1
-rw-r--r--services/core/java/com/android/server/am/UnsupportedDisplaySizeDialog.java78
-rw-r--r--services/core/java/com/android/server/am/UserController.java70
-rw-r--r--services/core/java/com/android/server/connectivity/DnsEventListenerService.java24
-rw-r--r--services/core/java/com/android/server/connectivity/MetricsLoggerService.java24
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkMonitor.java50
-rw-r--r--services/core/java/com/android/server/content/ContentService.java13
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java18
-rw-r--r--services/core/java/com/android/server/content/SyncOperation.java2
-rw-r--r--services/core/java/com/android/server/dreams/DreamManagerService.java21
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintService.java14
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java28
-rw-r--r--services/core/java/com/android/server/job/controllers/ContentObserverController.java49
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java9
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java891
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsObservers.java8
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsRecorder.java8
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java11
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java120
-rw-r--r--services/core/java/com/android/server/notification/NotificationUsageStats.java20
-rw-r--r--services/core/java/com/android/server/notification/RateEstimator.java13
-rw-r--r--services/core/java/com/android/server/pm/Installer.java7
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java6
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptService.java161
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptShellCommand.java9
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java130
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java3
-rw-r--r--services/core/java/com/android/server/pm/ProtectedPackages.java85
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java47
-rw-r--r--services/core/java/com/android/server/pm/ShortcutParser.java36
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java366
-rw-r--r--services/core/java/com/android/server/pm/ShortcutUser.java12
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java40
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java54
-rw-r--r--services/core/java/com/android/server/power/Notifier.java2
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java14
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java5
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java51
-rw-r--r--services/core/java/com/android/server/wm/WallpaperController.java28
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java99
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java9
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java149
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java60
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfacePlacer.java9
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java6
-rw-r--r--services/java/com/android/server/SystemServer.java2
-rw-r--r--services/net/java/android/net/apf/ApfFilter.java9
-rw-r--r--services/net/java/android/net/dhcp/DhcpClient.java12
-rw-r--r--services/net/java/android/net/ip/IpManager.java6
-rw-r--r--services/net/java/android/net/ip/IpReachabilityMonitor.java13
-rw-r--r--services/print/java/com/android/server/print/UserState.java54
-rw-r--r--services/retaildemo/Android.mk12
-rw-r--r--services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java (renamed from services/core/java/com/android/server/am/RetailDemoModeService.java)197
-rw-r--r--services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java105
-rw-r--r--services/tests/servicestests/res/xml/shortcut_3.xml56
-rw-r--r--services/tests/servicestests/src/android/net/apf/ApfTest.java21
-rw-r--r--services/tests/servicestests/src/android/net/metrics/IpConnectivityLogTest.java162
-rw-r--r--services/tests/servicestests/src/com/android/internal/util/FakeSettingsProviderTest.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/connectivity/DnsEventListenerServiceTest.java197
-rw-r--r--services/tests/servicestests/src/com/android/server/connectivity/MetricsLoggerServiceTest.java181
-rw-r--r--services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java157
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java831
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java168
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java124
-rw-r--r--services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java229
-rw-r--r--telecomm/java/android/telecom/Connection.java31
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java57
-rw-r--r--telephony/java/android/telephony/RadioAccessFamily.java44
-rw-r--r--telephony/java/android/telephony/ServiceState.java21
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java14
-rw-r--r--telephony/java/com/android/ims/ImsCallProfile.java9
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneConstants.java10
-rw-r--r--test-runner/src/android/test/mock/MockContext.java6
-rw-r--r--tools/aapt/ResourceFilter.cpp58
-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/BridgeIInputMethodManager.java9
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java8
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java6
-rw-r--r--wifi/java/android/net/wifi/WifiScanner.java38
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pGroup.java1
913 files changed, 15459 insertions, 5293 deletions
diff --git a/Android.mk b/Android.mk
index 50bed92fd2db..0b33301ce5ac 100644
--- a/Android.mk
+++ b/Android.mk
@@ -318,6 +318,7 @@ LOCAL_SRC_FILES += \
core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
core/java/com/android/internal/backup/IBackupTransport.aidl \
core/java/com/android/internal/backup/IObbBackupService.aidl \
+ core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl \
core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl \
core/java/com/android/internal/policy/IKeyguardExitCallback.aidl \
core/java/com/android/internal/policy/IKeyguardService.aidl \
@@ -495,6 +496,10 @@ LOCAL_JACK_FLAGS := --multi-dex native
LOCAL_RMTYPEDEFS := true
+ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
+LOCAL_EMMA_INSTRUMENT := true
+endif
+
include $(BUILD_JAVA_LIBRARY)
framework_module := $(LOCAL_INSTALLED_MODULE)
diff --git a/api/current.txt b/api/current.txt
index 57f1f65253f2..08c9fd6eac1a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -397,6 +397,7 @@ package android {
field public static final int colorPressedHighlight = 16843661; // 0x101038d
field public static final int colorPrimary = 16843827; // 0x1010433
field public static final int colorPrimaryDark = 16843828; // 0x1010434
+ field public static final int colorSecondary = 16844080; // 0x1010530
field public static final int columnCount = 16843639; // 0x1010377
field public static final int columnDelay = 16843215; // 0x10101cf
field public static final int columnOrderPreserved = 16843640; // 0x1010378
@@ -9518,8 +9519,6 @@ package android.content.pm {
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int);
method public android.graphics.drawable.Drawable getShortcutIconDrawable(android.content.pm.ShortcutInfo, int);
- method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
- method public android.os.ParcelFileDescriptor getShortcutIconFd(java.lang.String, java.lang.String, android.os.UserHandle);
method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
method public boolean hasShortcutHostPermission();
method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
@@ -9554,10 +9553,10 @@ package android.content.pm {
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
- field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final int FLAG_GET_MANIFEST = 8; // 0x8
- field public static final int FLAG_GET_PINNED = 2; // 0x2
+ field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
+ field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
+ field public static final int FLAG_MATCH_PINNED = 2; // 0x2
}
public class PackageInfo implements android.os.Parcelable {
@@ -10065,7 +10064,6 @@ package android.content.pm {
method public java.lang.CharSequence getDisabledMessage();
method public int getDisabledMessageResourceId();
method public android.os.PersistableBundle getExtras();
- method public int getIconResourceId();
method public java.lang.String getId();
method public android.content.Intent getIntent();
method public long getLastChangedTimestamp();
@@ -10076,14 +10074,11 @@ package android.content.pm {
method public java.lang.CharSequence getShortLabel();
method public int getShortLabelResourceId();
method public android.os.UserHandle getUserHandle();
- method public boolean hasIconFile();
- method public boolean hasIconResource();
method public boolean hasKeyFieldsOnly();
- method public boolean hasStringResourcesResolved();
+ method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
method public boolean isImmutable();
- method public boolean isManifestShortcut();
method public boolean isPinned();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
@@ -10091,14 +10086,15 @@ package android.content.pm {
}
public static class ShortcutInfo.Builder {
- ctor public ShortcutInfo.Builder(android.content.Context);
+ ctor public deprecated ShortcutInfo.Builder(android.content.Context);
+ ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
- method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
+ method public deprecated android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setRank(int);
@@ -29366,6 +29362,7 @@ package android.os {
method public android.os.Bundle getUserRestrictions();
method public android.os.Bundle getUserRestrictions(android.os.UserHandle);
method public boolean hasUserRestriction(java.lang.String);
+ method public boolean isDemoUser();
method public boolean isQuietModeEnabled(android.os.UserHandle);
method public boolean isSystemUser();
method public boolean isUserAGoat();
@@ -32477,6 +32474,7 @@ package android.provider {
field public static final java.lang.String DATA_ROAMING = "data_roaming";
field public static final java.lang.String DEBUG_APP = "debug_app";
field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+ field public static final java.lang.String DEVICE_NAME = "device_name";
field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned";
field public static final java.lang.String HTTP_PROXY = "http_proxy";
field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
@@ -33062,6 +33060,7 @@ package android.provider {
field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.provider.action.SYNC_VOICEMAIL";
field public static final java.lang.String AUTHORITY = "com.android.voicemail";
+ field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.provider.extra.PHONE_ACCOUNT_HANDLE";
field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
}
@@ -33070,6 +33069,9 @@ package android.provider {
method public static android.net.Uri buildSourceUri(java.lang.String);
field public static final java.lang.String CONFIGURATION_STATE = "configuration_state";
field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2
+ field public static final int CONFIGURATION_STATE_CONFIGURING = 3; // 0x3
+ field public static final int CONFIGURATION_STATE_DISABLED = 5; // 0x5
+ field public static final int CONFIGURATION_STATE_FAILED = 4; // 0x4
field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1
field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
field public static final android.net.Uri CONTENT_URI;
@@ -36315,6 +36317,7 @@ package android.telecom {
field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
+ field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -36766,9 +36769,11 @@ package android.telephony {
field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
field public static final java.lang.String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
+ field public static final java.lang.String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call";
field public static final java.lang.String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
field public static final java.lang.String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL = "allow_emergency_video_calls_bool";
field public static final java.lang.String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool";
+ field public static final java.lang.String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool";
field public static final java.lang.String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool";
field public static final java.lang.String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool";
field public static final java.lang.String KEY_APN_EXPAND_BOOL = "apn_expand_bool";
@@ -36800,6 +36805,7 @@ package android.telephony {
field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+ field public static final java.lang.String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool";
field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int";
field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
@@ -36857,6 +36863,7 @@ package android.telephony {
field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
field public static final java.lang.String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool";
field public static final java.lang.String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
+ field public static final java.lang.String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool";
field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
field public static final java.lang.String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
@@ -37352,26 +37359,6 @@ package android.telephony {
method public void onSubscriptionsChanged();
}
- public final class TelephonyHistogram implements android.os.Parcelable {
- ctor public TelephonyHistogram(int, int, int);
- ctor public TelephonyHistogram(android.telephony.TelephonyHistogram);
- ctor public TelephonyHistogram(android.os.Parcel);
- method public void addTimeTaken(int);
- method public int describeContents();
- method public int getAverageTime();
- method public int getBucketCount();
- method public int[] getBucketCounters();
- method public int[] getBucketEndPoints();
- method public int getCategory();
- method public int getId();
- method public int getMaxTime();
- method public int getMinTime();
- method public int getSampleCount();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.TelephonyHistogram> CREATOR;
- field public static final int TELEPHONY_CATEGORY_RIL = 1; // 0x1
- }
-
public class TelephonyManager {
method public boolean canChangeDtmfToneLength();
method public android.telephony.TelephonyManager createForSubscriptionId(int);
@@ -37402,7 +37389,6 @@ package android.telephony {
method public java.lang.String getSimSerialNumber();
method public int getSimState();
method public java.lang.String getSubscriberId();
- method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
method public java.lang.String getVoiceMailAlphaTag();
method public java.lang.String getVoiceMailNumber();
method public int getVoiceNetworkType();
@@ -37462,12 +37448,15 @@ package android.telephony {
field public static final int NETWORK_TYPE_EVDO_A = 6; // 0x6
field public static final int NETWORK_TYPE_EVDO_B = 12; // 0xc
field public static final int NETWORK_TYPE_GPRS = 1; // 0x1
+ field public static final int NETWORK_TYPE_GSM = 16; // 0x10
field public static final int NETWORK_TYPE_HSDPA = 8; // 0x8
field public static final int NETWORK_TYPE_HSPA = 10; // 0xa
field public static final int NETWORK_TYPE_HSPAP = 15; // 0xf
field public static final int NETWORK_TYPE_HSUPA = 9; // 0x9
field public static final int NETWORK_TYPE_IDEN = 11; // 0xb
+ field public static final int NETWORK_TYPE_IWLAN = 18; // 0x12
field public static final int NETWORK_TYPE_LTE = 13; // 0xd
+ field public static final int NETWORK_TYPE_TD_SCDMA = 17; // 0x11
field public static final int NETWORK_TYPE_UMTS = 3; // 0x3
field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
field public static final int PHONE_TYPE_CDMA = 2; // 0x2
@@ -40996,8 +40985,11 @@ package android.view {
field public static final android.os.Parcelable.Creator<android.view.Display.Mode> CREATOR;
}
- public final class DragAndDropPermissions {
+ public final class DragAndDropPermissions implements android.os.Parcelable {
+ method public int describeContents();
method public void release();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.DragAndDropPermissions> CREATOR;
}
public class DragEvent implements android.os.Parcelable {
@@ -41480,10 +41472,6 @@ package android.view {
field public static final int KEYCODE_FOCUS = 80; // 0x50
field public static final int KEYCODE_FORWARD = 125; // 0x7d
field public static final int KEYCODE_FORWARD_DEL = 112; // 0x70
- field public static final int KEYCODE_FP_NAV_DOWN = 281; // 0x119
- field public static final int KEYCODE_FP_NAV_LEFT = 282; // 0x11a
- field public static final int KEYCODE_FP_NAV_RIGHT = 283; // 0x11b
- field public static final int KEYCODE_FP_NAV_UP = 280; // 0x118
field public static final int KEYCODE_FUNCTION = 119; // 0x77
field public static final int KEYCODE_G = 35; // 0x23
field public static final int KEYCODE_GRAVE = 68; // 0x44
@@ -41602,6 +41590,10 @@ package android.view {
field public static final int KEYCODE_SWITCH_CHARSET = 95; // 0x5f
field public static final int KEYCODE_SYM = 63; // 0x3f
field public static final int KEYCODE_SYSRQ = 120; // 0x78
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_DOWN = 281; // 0x119
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_LEFT = 282; // 0x11a
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283; // 0x11b
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_UP = 280; // 0x118
field public static final int KEYCODE_T = 48; // 0x30
field public static final int KEYCODE_TAB = 61; // 0x3d
field public static final int KEYCODE_TV = 170; // 0xaa
@@ -44692,6 +44684,7 @@ package android.view.inputmethod {
method public boolean clearMetaKeyStates(int);
method public void closeConnection();
method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+ method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
method public boolean commitText(java.lang.CharSequence, int);
method public boolean deleteSurroundingText(int, int);
@@ -44707,7 +44700,6 @@ package android.view.inputmethod {
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
- method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -44862,6 +44854,7 @@ package android.view.inputmethod {
method public abstract boolean clearMetaKeyStates(int);
method public abstract void closeConnection();
method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+ method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
method public abstract boolean commitText(java.lang.CharSequence, int);
method public abstract boolean deleteSurroundingText(int, int);
@@ -44874,7 +44867,6 @@ package android.view.inputmethod {
method public abstract java.lang.CharSequence getSelectedText(int);
method public abstract java.lang.CharSequence getTextAfterCursor(int, int);
method public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
- method public abstract boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
method public abstract boolean performContextMenuAction(int);
method public abstract boolean performEditorAction(int);
method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -44888,6 +44880,7 @@ package android.view.inputmethod {
field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2
field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
+ field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1
}
public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
@@ -44896,6 +44889,7 @@ package android.view.inputmethod {
method public boolean clearMetaKeyStates(int);
method public void closeConnection();
method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+ method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
method public boolean commitText(java.lang.CharSequence, int);
method public boolean deleteSurroundingText(int, int);
@@ -44908,7 +44902,6 @@ package android.view.inputmethod {
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
- method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -44921,13 +44914,15 @@ package android.view.inputmethod {
method public void setTarget(android.view.inputmethod.InputConnection);
}
- public class InputContentInfo implements android.os.Parcelable {
+ public final class InputContentInfo implements android.os.Parcelable {
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription);
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription, android.net.Uri);
method public int describeContents();
method public android.net.Uri getContentUri();
method public android.content.ClipDescription getDescription();
method public android.net.Uri getLinkUri();
+ method public void releasePermission();
+ method public void requestPermission();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.inputmethod.InputContentInfo> CREATOR;
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 0f37751021b8..7aa5394a9021 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -504,6 +504,7 @@ package android {
field public static final int colorPressedHighlight = 16843661; // 0x101038d
field public static final int colorPrimary = 16843827; // 0x1010433
field public static final int colorPrimaryDark = 16843828; // 0x1010434
+ field public static final int colorSecondary = 16844080; // 0x1010530
field public static final int columnCount = 16843639; // 0x1010377
field public static final int columnDelay = 16843215; // 0x10101cf
field public static final int columnOrderPreserved = 16843640; // 0x1010378
@@ -9872,8 +9873,6 @@ package android.content.pm {
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int);
method public android.graphics.drawable.Drawable getShortcutIconDrawable(android.content.pm.ShortcutInfo, int);
- method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
- method public android.os.ParcelFileDescriptor getShortcutIconFd(java.lang.String, java.lang.String, android.os.UserHandle);
method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
method public boolean hasShortcutHostPermission();
method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
@@ -9908,10 +9907,10 @@ package android.content.pm {
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
- field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final int FLAG_GET_MANIFEST = 8; // 0x8
- field public static final int FLAG_GET_PINNED = 2; // 0x2
+ field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
+ field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
+ field public static final int FLAG_MATCH_PINNED = 2; // 0x2
}
public class PackageInfo implements android.os.Parcelable {
@@ -10489,7 +10488,6 @@ package android.content.pm {
method public java.lang.CharSequence getDisabledMessage();
method public int getDisabledMessageResourceId();
method public android.os.PersistableBundle getExtras();
- method public int getIconResourceId();
method public java.lang.String getId();
method public android.content.Intent getIntent();
method public long getLastChangedTimestamp();
@@ -10500,14 +10498,11 @@ package android.content.pm {
method public java.lang.CharSequence getShortLabel();
method public int getShortLabelResourceId();
method public android.os.UserHandle getUserHandle();
- method public boolean hasIconFile();
- method public boolean hasIconResource();
method public boolean hasKeyFieldsOnly();
- method public boolean hasStringResourcesResolved();
+ method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
method public boolean isImmutable();
- method public boolean isManifestShortcut();
method public boolean isPinned();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
@@ -10515,14 +10510,15 @@ package android.content.pm {
}
public static class ShortcutInfo.Builder {
- ctor public ShortcutInfo.Builder(android.content.Context);
+ ctor public deprecated ShortcutInfo.Builder(android.content.Context);
+ ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
- method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
+ method public deprecated android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setRank(int);
@@ -31891,6 +31887,7 @@ package android.os {
method public android.os.Bundle getUserRestrictions();
method public android.os.Bundle getUserRestrictions(android.os.UserHandle);
method public boolean hasUserRestriction(java.lang.String);
+ method public boolean isDemoUser();
method public boolean isManagedProfile();
method public boolean isManagedProfile(int);
method public boolean isQuietModeEnabled(android.os.UserHandle);
@@ -35182,6 +35179,7 @@ package android.provider {
field public static final java.lang.String DATA_ROAMING = "data_roaming";
field public static final java.lang.String DEBUG_APP = "debug_app";
field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+ field public static final java.lang.String DEVICE_NAME = "device_name";
field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned";
field public static final java.lang.String HTTP_PROXY = "http_proxy";
field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
@@ -35770,6 +35768,7 @@ package android.provider {
field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.provider.action.SYNC_VOICEMAIL";
field public static final java.lang.String AUTHORITY = "com.android.voicemail";
+ field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.provider.extra.PHONE_ACCOUNT_HANDLE";
field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
}
@@ -35778,6 +35777,9 @@ package android.provider {
method public static android.net.Uri buildSourceUri(java.lang.String);
field public static final java.lang.String CONFIGURATION_STATE = "configuration_state";
field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2
+ field public static final int CONFIGURATION_STATE_CONFIGURING = 3; // 0x3
+ field public static final int CONFIGURATION_STATE_DISABLED = 5; // 0x5
+ field public static final int CONFIGURATION_STATE_FAILED = 4; // 0x4
field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1
field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
field public static final android.net.Uri CONTENT_URI;
@@ -39164,6 +39166,7 @@ package android.telecom {
field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
+ field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -39805,9 +39808,11 @@ package android.telephony {
field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
field public static final java.lang.String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
+ field public static final java.lang.String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call";
field public static final java.lang.String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
field public static final java.lang.String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL = "allow_emergency_video_calls_bool";
field public static final java.lang.String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool";
+ field public static final java.lang.String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool";
field public static final java.lang.String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool";
field public static final java.lang.String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool";
field public static final java.lang.String KEY_APN_EXPAND_BOOL = "apn_expand_bool";
@@ -39839,6 +39844,7 @@ package android.telephony {
field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+ field public static final java.lang.String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool";
field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int";
field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
@@ -39896,6 +39902,7 @@ package android.telephony {
field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
field public static final java.lang.String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool";
field public static final java.lang.String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
+ field public static final java.lang.String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool";
field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
field public static final java.lang.String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
@@ -40549,12 +40556,15 @@ package android.telephony {
field public static final int NETWORK_TYPE_EVDO_A = 6; // 0x6
field public static final int NETWORK_TYPE_EVDO_B = 12; // 0xc
field public static final int NETWORK_TYPE_GPRS = 1; // 0x1
+ field public static final int NETWORK_TYPE_GSM = 16; // 0x10
field public static final int NETWORK_TYPE_HSDPA = 8; // 0x8
field public static final int NETWORK_TYPE_HSPA = 10; // 0xa
field public static final int NETWORK_TYPE_HSPAP = 15; // 0xf
field public static final int NETWORK_TYPE_HSUPA = 9; // 0x9
field public static final int NETWORK_TYPE_IDEN = 11; // 0xb
+ field public static final int NETWORK_TYPE_IWLAN = 18; // 0x12
field public static final int NETWORK_TYPE_LTE = 13; // 0xd
+ field public static final int NETWORK_TYPE_TD_SCDMA = 17; // 0x11
field public static final int NETWORK_TYPE_UMTS = 3; // 0x3
field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
field public static final int PHONE_TYPE_CDMA = 2; // 0x2
@@ -44100,8 +44110,11 @@ package android.view {
field public static final android.os.Parcelable.Creator<android.view.Display.Mode> CREATOR;
}
- public final class DragAndDropPermissions {
+ public final class DragAndDropPermissions implements android.os.Parcelable {
+ method public int describeContents();
method public void release();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.DragAndDropPermissions> CREATOR;
}
public class DragEvent implements android.os.Parcelable {
@@ -44584,10 +44597,6 @@ package android.view {
field public static final int KEYCODE_FOCUS = 80; // 0x50
field public static final int KEYCODE_FORWARD = 125; // 0x7d
field public static final int KEYCODE_FORWARD_DEL = 112; // 0x70
- field public static final int KEYCODE_FP_NAV_DOWN = 281; // 0x119
- field public static final int KEYCODE_FP_NAV_LEFT = 282; // 0x11a
- field public static final int KEYCODE_FP_NAV_RIGHT = 283; // 0x11b
- field public static final int KEYCODE_FP_NAV_UP = 280; // 0x118
field public static final int KEYCODE_FUNCTION = 119; // 0x77
field public static final int KEYCODE_G = 35; // 0x23
field public static final int KEYCODE_GRAVE = 68; // 0x44
@@ -44706,6 +44715,10 @@ package android.view {
field public static final int KEYCODE_SWITCH_CHARSET = 95; // 0x5f
field public static final int KEYCODE_SYM = 63; // 0x3f
field public static final int KEYCODE_SYSRQ = 120; // 0x78
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_DOWN = 281; // 0x119
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_LEFT = 282; // 0x11a
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283; // 0x11b
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_UP = 280; // 0x118
field public static final int KEYCODE_T = 48; // 0x30
field public static final int KEYCODE_TAB = 61; // 0x3d
field public static final int KEYCODE_TV = 170; // 0xaa
@@ -47799,6 +47812,7 @@ package android.view.inputmethod {
method public boolean clearMetaKeyStates(int);
method public void closeConnection();
method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+ method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
method public boolean commitText(java.lang.CharSequence, int);
method public boolean deleteSurroundingText(int, int);
@@ -47814,7 +47828,6 @@ package android.view.inputmethod {
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
- method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -47969,6 +47982,7 @@ package android.view.inputmethod {
method public abstract boolean clearMetaKeyStates(int);
method public abstract void closeConnection();
method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+ method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
method public abstract boolean commitText(java.lang.CharSequence, int);
method public abstract boolean deleteSurroundingText(int, int);
@@ -47981,7 +47995,6 @@ package android.view.inputmethod {
method public abstract java.lang.CharSequence getSelectedText(int);
method public abstract java.lang.CharSequence getTextAfterCursor(int, int);
method public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
- method public abstract boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
method public abstract boolean performContextMenuAction(int);
method public abstract boolean performEditorAction(int);
method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -47995,6 +48008,7 @@ package android.view.inputmethod {
field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2
field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
+ field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1
}
public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
@@ -48003,6 +48017,7 @@ package android.view.inputmethod {
method public boolean clearMetaKeyStates(int);
method public void closeConnection();
method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+ method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
method public boolean commitText(java.lang.CharSequence, int);
method public boolean deleteSurroundingText(int, int);
@@ -48015,7 +48030,6 @@ package android.view.inputmethod {
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
- method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -48028,13 +48042,15 @@ package android.view.inputmethod {
method public void setTarget(android.view.inputmethod.InputConnection);
}
- public class InputContentInfo implements android.os.Parcelable {
+ public final class InputContentInfo implements android.os.Parcelable {
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription);
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription, android.net.Uri);
method public int describeContents();
method public android.net.Uri getContentUri();
method public android.content.ClipDescription getDescription();
method public android.net.Uri getLinkUri();
+ method public void releasePermission();
+ method public void requestPermission();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.inputmethod.InputContentInfo> CREATOR;
}
diff --git a/api/test-current.txt b/api/test-current.txt
index ec10ccc8c251..003e50b96533 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -397,6 +397,7 @@ package android {
field public static final int colorPressedHighlight = 16843661; // 0x101038d
field public static final int colorPrimary = 16843827; // 0x1010433
field public static final int colorPrimaryDark = 16843828; // 0x1010434
+ field public static final int colorSecondary = 16844080; // 0x1010530
field public static final int columnCount = 16843639; // 0x1010377
field public static final int columnDelay = 16843215; // 0x10101cf
field public static final int columnOrderPreserved = 16843640; // 0x1010378
@@ -9530,8 +9531,6 @@ package android.content.pm {
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
method public android.graphics.drawable.Drawable getShortcutBadgedIconDrawable(android.content.pm.ShortcutInfo, int);
method public android.graphics.drawable.Drawable getShortcutIconDrawable(android.content.pm.ShortcutInfo, int);
- method public android.os.ParcelFileDescriptor getShortcutIconFd(android.content.pm.ShortcutInfo);
- method public android.os.ParcelFileDescriptor getShortcutIconFd(java.lang.String, java.lang.String, android.os.UserHandle);
method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle);
method public boolean hasShortcutHostPermission();
method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
@@ -9566,10 +9565,10 @@ package android.content.pm {
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
- field public static final int FLAG_GET_DYNAMIC = 1; // 0x1
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
- field public static final int FLAG_GET_MANIFEST = 8; // 0x8
- field public static final int FLAG_GET_PINNED = 2; // 0x2
+ field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
+ field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
+ field public static final int FLAG_MATCH_PINNED = 2; // 0x2
}
public class PackageInfo implements android.os.Parcelable {
@@ -10078,7 +10077,6 @@ package android.content.pm {
method public java.lang.CharSequence getDisabledMessage();
method public int getDisabledMessageResourceId();
method public android.os.PersistableBundle getExtras();
- method public int getIconResourceId();
method public java.lang.String getId();
method public android.content.Intent getIntent();
method public long getLastChangedTimestamp();
@@ -10089,14 +10087,11 @@ package android.content.pm {
method public java.lang.CharSequence getShortLabel();
method public int getShortLabelResourceId();
method public android.os.UserHandle getUserHandle();
- method public boolean hasIconFile();
- method public boolean hasIconResource();
method public boolean hasKeyFieldsOnly();
- method public boolean hasStringResourcesResolved();
+ method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
method public boolean isImmutable();
- method public boolean isManifestShortcut();
method public boolean isPinned();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutInfo> CREATOR;
@@ -10104,14 +10099,15 @@ package android.content.pm {
}
public static class ShortcutInfo.Builder {
- ctor public ShortcutInfo.Builder(android.content.Context);
+ ctor public deprecated ShortcutInfo.Builder(android.content.Context);
+ ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
- method public android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
+ method public deprecated android.content.pm.ShortcutInfo.Builder setId(java.lang.String);
method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setRank(int);
@@ -29437,6 +29433,7 @@ package android.os {
method public android.os.Bundle getUserRestrictions();
method public android.os.Bundle getUserRestrictions(android.os.UserHandle);
method public boolean hasUserRestriction(java.lang.String);
+ method public boolean isDemoUser();
method public boolean isQuietModeEnabled(android.os.UserHandle);
method public boolean isSystemUser();
method public boolean isUserAGoat();
@@ -32551,6 +32548,7 @@ package android.provider {
field public static final java.lang.String DATA_ROAMING = "data_roaming";
field public static final java.lang.String DEBUG_APP = "debug_app";
field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
+ field public static final java.lang.String DEVICE_NAME = "device_name";
field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned";
field public static final java.lang.String HTTP_PROXY = "http_proxy";
field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
@@ -33139,6 +33137,7 @@ package android.provider {
field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
field public static final java.lang.String ACTION_SYNC_VOICEMAIL = "android.provider.action.SYNC_VOICEMAIL";
field public static final java.lang.String AUTHORITY = "com.android.voicemail";
+ field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.provider.extra.PHONE_ACCOUNT_HANDLE";
field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
}
@@ -33147,6 +33146,9 @@ package android.provider {
method public static android.net.Uri buildSourceUri(java.lang.String);
field public static final java.lang.String CONFIGURATION_STATE = "configuration_state";
field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2
+ field public static final int CONFIGURATION_STATE_CONFIGURING = 3; // 0x3
+ field public static final int CONFIGURATION_STATE_DISABLED = 5; // 0x5
+ field public static final int CONFIGURATION_STATE_FAILED = 4; // 0x4
field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1
field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
field public static final android.net.Uri CONTENT_URI;
@@ -36393,6 +36395,7 @@ package android.telecom {
field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8
field public static final java.lang.String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED";
field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED";
+ field public static final java.lang.String EXTRA_ANSWERING_DROPS_FG_CALL = "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS";
field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
@@ -36844,9 +36847,11 @@ package android.telephony {
field public static final java.lang.String ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
field public static final java.lang.String KEY_ADDITIONAL_CALL_SETTING_BOOL = "additional_call_setting_bool";
field public static final java.lang.String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
+ field public static final java.lang.String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call";
field public static final java.lang.String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
field public static final java.lang.String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL = "allow_emergency_video_calls_bool";
field public static final java.lang.String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool";
+ field public static final java.lang.String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool";
field public static final java.lang.String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool";
field public static final java.lang.String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool";
field public static final java.lang.String KEY_APN_EXPAND_BOOL = "apn_expand_bool";
@@ -36878,6 +36883,7 @@ package android.telephony {
field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
field public static final java.lang.String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+ field public static final java.lang.String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL = "drop_video_call_when_answering_audio_call_bool";
field public static final java.lang.String KEY_DTMF_TYPE_ENABLED_BOOL = "dtmf_type_enabled_bool";
field public static final java.lang.String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT = "duration_blocking_disabled_after_emergency_int";
field public static final java.lang.String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
@@ -36935,6 +36941,7 @@ package android.telephony {
field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
field public static final java.lang.String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool";
field public static final java.lang.String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
+ field public static final java.lang.String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool";
field public static final java.lang.String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
field public static final java.lang.String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
field public static final java.lang.String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
@@ -37430,26 +37437,6 @@ package android.telephony {
method public void onSubscriptionsChanged();
}
- public final class TelephonyHistogram implements android.os.Parcelable {
- ctor public TelephonyHistogram(int, int, int);
- ctor public TelephonyHistogram(android.telephony.TelephonyHistogram);
- ctor public TelephonyHistogram(android.os.Parcel);
- method public void addTimeTaken(int);
- method public int describeContents();
- method public int getAverageTime();
- method public int getBucketCount();
- method public int[] getBucketCounters();
- method public int[] getBucketEndPoints();
- method public int getCategory();
- method public int getId();
- method public int getMaxTime();
- method public int getMinTime();
- method public int getSampleCount();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.TelephonyHistogram> CREATOR;
- field public static final int TELEPHONY_CATEGORY_RIL = 1; // 0x1
- }
-
public class TelephonyManager {
method public boolean canChangeDtmfToneLength();
method public android.telephony.TelephonyManager createForSubscriptionId(int);
@@ -37480,7 +37467,6 @@ package android.telephony {
method public java.lang.String getSimSerialNumber();
method public int getSimState();
method public java.lang.String getSubscriberId();
- method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
method public java.lang.String getVoiceMailAlphaTag();
method public java.lang.String getVoiceMailNumber();
method public int getVoiceNetworkType();
@@ -37540,12 +37526,15 @@ package android.telephony {
field public static final int NETWORK_TYPE_EVDO_A = 6; // 0x6
field public static final int NETWORK_TYPE_EVDO_B = 12; // 0xc
field public static final int NETWORK_TYPE_GPRS = 1; // 0x1
+ field public static final int NETWORK_TYPE_GSM = 16; // 0x10
field public static final int NETWORK_TYPE_HSDPA = 8; // 0x8
field public static final int NETWORK_TYPE_HSPA = 10; // 0xa
field public static final int NETWORK_TYPE_HSPAP = 15; // 0xf
field public static final int NETWORK_TYPE_HSUPA = 9; // 0x9
field public static final int NETWORK_TYPE_IDEN = 11; // 0xb
+ field public static final int NETWORK_TYPE_IWLAN = 18; // 0x12
field public static final int NETWORK_TYPE_LTE = 13; // 0xd
+ field public static final int NETWORK_TYPE_TD_SCDMA = 17; // 0x11
field public static final int NETWORK_TYPE_UMTS = 3; // 0x3
field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
field public static final int PHONE_TYPE_CDMA = 2; // 0x2
@@ -41076,8 +41065,11 @@ package android.view {
field public static final android.os.Parcelable.Creator<android.view.Display.Mode> CREATOR;
}
- public final class DragAndDropPermissions {
+ public final class DragAndDropPermissions implements android.os.Parcelable {
+ method public int describeContents();
method public void release();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.DragAndDropPermissions> CREATOR;
}
public class DragEvent implements android.os.Parcelable {
@@ -41560,10 +41552,6 @@ package android.view {
field public static final int KEYCODE_FOCUS = 80; // 0x50
field public static final int KEYCODE_FORWARD = 125; // 0x7d
field public static final int KEYCODE_FORWARD_DEL = 112; // 0x70
- field public static final int KEYCODE_FP_NAV_DOWN = 281; // 0x119
- field public static final int KEYCODE_FP_NAV_LEFT = 282; // 0x11a
- field public static final int KEYCODE_FP_NAV_RIGHT = 283; // 0x11b
- field public static final int KEYCODE_FP_NAV_UP = 280; // 0x118
field public static final int KEYCODE_FUNCTION = 119; // 0x77
field public static final int KEYCODE_G = 35; // 0x23
field public static final int KEYCODE_GRAVE = 68; // 0x44
@@ -41682,6 +41670,10 @@ package android.view {
field public static final int KEYCODE_SWITCH_CHARSET = 95; // 0x5f
field public static final int KEYCODE_SYM = 63; // 0x3f
field public static final int KEYCODE_SYSRQ = 120; // 0x78
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_DOWN = 281; // 0x119
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_LEFT = 282; // 0x11a
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283; // 0x11b
+ field public static final int KEYCODE_SYSTEM_NAVIGATION_UP = 280; // 0x118
field public static final int KEYCODE_T = 48; // 0x30
field public static final int KEYCODE_TAB = 61; // 0x3d
field public static final int KEYCODE_TV = 170; // 0xaa
@@ -44772,6 +44764,7 @@ package android.view.inputmethod {
method public boolean clearMetaKeyStates(int);
method public void closeConnection();
method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+ method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
method public boolean commitText(java.lang.CharSequence, int);
method public boolean deleteSurroundingText(int, int);
@@ -44787,7 +44780,6 @@ package android.view.inputmethod {
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
- method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -44942,6 +44934,7 @@ package android.view.inputmethod {
method public abstract boolean clearMetaKeyStates(int);
method public abstract void closeConnection();
method public abstract boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+ method public abstract boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
method public abstract boolean commitText(java.lang.CharSequence, int);
method public abstract boolean deleteSurroundingText(int, int);
@@ -44954,7 +44947,6 @@ package android.view.inputmethod {
method public abstract java.lang.CharSequence getSelectedText(int);
method public abstract java.lang.CharSequence getTextAfterCursor(int, int);
method public abstract java.lang.CharSequence getTextBeforeCursor(int, int);
- method public abstract boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
method public abstract boolean performContextMenuAction(int);
method public abstract boolean performEditorAction(int);
method public abstract boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -44968,6 +44960,7 @@ package android.view.inputmethod {
field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2
field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1
field public static final int GET_TEXT_WITH_STYLES = 1; // 0x1
+ field public static final int INPUT_CONTENT_GRANT_READ_URI_PERMISSION = 1; // 0x1
}
public class InputConnectionWrapper implements android.view.inputmethod.InputConnection {
@@ -44976,6 +44969,7 @@ package android.view.inputmethod {
method public boolean clearMetaKeyStates(int);
method public void closeConnection();
method public boolean commitCompletion(android.view.inputmethod.CompletionInfo);
+ method public boolean commitContent(android.view.inputmethod.InputContentInfo, int, android.os.Bundle);
method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
method public boolean commitText(java.lang.CharSequence, int);
method public boolean deleteSurroundingText(int, int);
@@ -44988,7 +44982,6 @@ package android.view.inputmethod {
method public java.lang.CharSequence getSelectedText(int);
method public java.lang.CharSequence getTextAfterCursor(int, int);
method public java.lang.CharSequence getTextBeforeCursor(int, int);
- method public boolean insertContent(android.view.inputmethod.InputContentInfo, android.os.Bundle);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(java.lang.String, android.os.Bundle);
@@ -45001,13 +44994,15 @@ package android.view.inputmethod {
method public void setTarget(android.view.inputmethod.InputConnection);
}
- public class InputContentInfo implements android.os.Parcelable {
+ public final class InputContentInfo implements android.os.Parcelable {
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription);
ctor public InputContentInfo(android.net.Uri, android.content.ClipDescription, android.net.Uri);
method public int describeContents();
method public android.net.Uri getContentUri();
method public android.content.ClipDescription getDescription();
method public android.net.Uri getLinkUri();
+ method public void releasePermission();
+ method public void requestPermission();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.inputmethod.InputContentInfo> CREATOR;
}
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 8ccd5d2ebcba..d6c00589e7c2 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -723,10 +723,10 @@ public class Am extends BaseCommand {
System.out.println("Complete");
}
mRepeat--;
- if (mRepeat > 1) {
+ if (mRepeat > 0) {
mAm.unhandledBack();
}
- } while (mRepeat > 1);
+ } while (mRepeat > 0);
}
private void runForceStop() throws Exception {
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 69b5a17300de..5bf80765a7de 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -122,6 +122,11 @@ public final class Bmgr {
return;
}
+ if ("whitelist".equals(op)) {
+ doPrintWhitelist();
+ return;
+ }
+
System.err.println("Unknown command");
showUsage();
}
@@ -604,6 +609,20 @@ public final class Bmgr {
}
}
+ private void doPrintWhitelist() {
+ try {
+ final String[] whitelist = mBmgr.getTransportWhitelist();
+ if (whitelist != null) {
+ for (String transport : whitelist) {
+ System.out.println(transport);
+ }
+ }
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(BMGR_NOT_RUNNING_ERR);
+ }
+ }
+
private String nextArg() {
if (mNextArg >= mArgs.length) {
return null;
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 4470eda0a2fa..32a8088e9c4e 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -254,6 +254,10 @@ public final class Pm {
return runMovePrimaryStorage();
}
+ if ("set-user-restriction".equals(op)) {
+ return runSetUserRestriction();
+ }
+
try {
if (args.length == 1) {
if (args[0].equalsIgnoreCase("-l")) {
@@ -918,6 +922,8 @@ public final class Pm {
flags |= UserInfo.FLAG_EPHEMERAL;
} else if ("--guest".equals(opt)) {
flags |= UserInfo.FLAG_GUEST;
+ } else if ("--demo".equals(opt)) {
+ flags |= UserInfo.FLAG_DEMO;
} else {
System.err.println("Error: unknown option " + opt);
return showUsage();
@@ -1054,6 +1060,38 @@ public final class Pm {
}
}
+ public int runSetUserRestriction() {
+ int userId = UserHandle.USER_SYSTEM;
+ String opt = nextOption();
+ if (opt != null && "--user".equals(opt)) {
+ String arg = nextArg();
+ if (arg == null || !isNumber(arg)) {
+ System.err.println("Error: valid userId not specified");
+ return 1;
+ }
+ userId = Integer.parseInt(arg);
+ }
+
+ String restriction = nextArg();
+ String arg = nextArg();
+ boolean value;
+ if ("1".equals(arg)) {
+ value = true;
+ } else if ("0".equals(arg)) {
+ value = false;
+ } else {
+ System.err.println("Error: valid value not specified");
+ return 1;
+ }
+ try {
+ mUm.setUserRestriction(restriction, value, userId);
+ return 0;
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ return 1;
+ }
+ }
+
static class ClearDataObserver extends IPackageDataObserver.Stub {
boolean finished;
boolean result;
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 7841d29b5700..053ba7d5fa0a 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1064,15 +1064,15 @@ public final class AnimatorSet extends Animator {
/**
* @hide
* TODO: For animatorSet defined in XML, we can use a flag to indicate what the play order
- * if defined (i.e. sequential or together), then we can use the flag instead of calculate
- * dynamically.
+ * if defined (i.e. sequential or together), then we can use the flag instead of calculating
+ * dynamically. Note that when AnimatorSet is empty this method returns true.
* @return whether all the animators in the set are supposed to play together
*/
public boolean shouldPlayTogether() {
updateAnimatorsDuration();
createDependencyGraph();
// All the child nodes are set out to play right after the delay animation
- return mRootNode.mChildNodes.size() == mNodes.size() - 1;
+ return mRootNode.mChildNodes == null || mRootNode.mChildNodes.size() == mNodes.size() - 1;
}
@Override
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ec8b2882682b..06a01fc59807 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -306,7 +306,7 @@ import java.util.List;
* </thead>
*
* <tbody>
- * <tr><th colspan="3" align="left" border="0">{@link android.app.Activity#onCreate onCreate()}</th>
+ * <tr><td colspan="3" align="left" border="0">{@link android.app.Activity#onCreate onCreate()}</td>
* <td>Called when the activity is first created.
* This is where you should do all of your normal static set up:
* create views, bind data to lists, etc. This method also
@@ -318,7 +318,7 @@ import java.util.List;
* </tr>
*
* <tr><td rowspan="5" style="border-left: none; border-right: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
- * <th colspan="2" align="left" border="0">{@link android.app.Activity#onRestart onRestart()}</th>
+ * <td colspan="2" align="left" border="0">{@link android.app.Activity#onRestart onRestart()}</td>
* <td>Called after your activity has been stopped, prior to it being
* started again.
* <p>Always followed by <code>onStart()</code></td>
@@ -326,7 +326,7 @@ import java.util.List;
* <td align="center"><code>onStart()</code></td>
* </tr>
*
- * <tr><th colspan="2" align="left" border="0">{@link android.app.Activity#onStart onStart()}</th>
+ * <tr><td colspan="2" align="left" border="0">{@link android.app.Activity#onStart onStart()}</td>
* <td>Called when the activity is becoming visible to the user.
* <p>Followed by <code>onResume()</code> if the activity comes
* to the foreground, or <code>onStop()</code> if it becomes hidden.</td>
@@ -335,7 +335,7 @@ import java.util.List;
* </tr>
*
* <tr><td rowspan="2" style="border-left: none;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
- * <th align="left" border="0">{@link android.app.Activity#onResume onResume()}</th>
+ * <td align="left" border="0">{@link android.app.Activity#onResume onResume()}</td>
* <td>Called when the activity will start
* interacting with the user. At this point your activity is at
* the top of the activity stack, with user input going to it.
@@ -344,7 +344,7 @@ import java.util.List;
* <td align="center"><code>onPause()</code></td>
* </tr>
*
- * <tr><th align="left" border="0">{@link android.app.Activity#onPause onPause()}</th>
+ * <tr><td align="left" border="0">{@link android.app.Activity#onPause onPause()}</td>
* <td>Called when the system is about to start resuming a previous
* activity. This is typically used to commit unsaved changes to
* persistent data, stop animations and other things that may be consuming
@@ -358,7 +358,7 @@ import java.util.List;
* <code>onStop()</code></td>
* </tr>
*
- * <tr><th colspan="2" align="left" border="0">{@link android.app.Activity#onStop onStop()}</th>
+ * <tr><td colspan="2" align="left" border="0">{@link android.app.Activity#onStop onStop()}</td>
* <td>Called when the activity is no longer visible to the user, because
* another activity has been resumed and is covering this one. This
* may happen either because a new activity is being started, an existing
@@ -372,7 +372,7 @@ import java.util.List;
* <code>onDestroy()</code></td>
* </tr>
*
- * <tr><th colspan="3" align="left" border="0">{@link android.app.Activity#onDestroy onDestroy()}</th>
+ * <tr><td colspan="3" align="left" border="0">{@link android.app.Activity#onDestroy onDestroy()}</td>
* <td>The final call you receive before your
* activity is destroyed. This can happen either because the
* activity is finishing (someone called {@link Activity#finish} on
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 3a70a4cd4b99..33ae553fb57f 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -19,6 +19,7 @@ package android.app;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.IIntentSender;
+import android.content.res.Configuration;
import android.os.IBinder;
import android.service.voice.IVoiceInteractionSession;
@@ -151,4 +152,13 @@ public abstract class ActivityManagerInternal {
* such as Power Save mode.
*/
public abstract void setPendingIntentWhitelistDuration(IIntentSender target, long duration);
+
+ /**
+ * Updates and persists the {@link Configuration} for a given user.
+ *
+ * @param values the configuration to update
+ * @param userId the user to update the configuration for
+ */
+ public abstract void updatePersistentConfigurationForUser(@NonNull Configuration values,
+ int userId);
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 3c7eef5eee64..cee5646a73b3 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1813,12 +1813,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
- case KILL_APPLICATION_WITH_APPID_TRANSACTION: {
+ case KILL_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String pkg = data.readString();
- int appid = data.readInt();
+ int appId = data.readInt();
+ int userId = data.readInt();
String reason = data.readString();
- killApplicationWithAppId(pkg, appid, reason);
+ killApplication(pkg, appId, userId, reason);
reply.writeNoException();
return true;
}
@@ -2370,7 +2371,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
data.enforceInterface(IActivityManager.descriptor);
IUserSwitchObserver observer = IUserSwitchObserver.Stub.asInterface(
data.readStrongBinder());
- registerUserSwitchObserver(observer);
+ String name = data.readString();
+ registerUserSwitchObserver(observer, name);
reply.writeNoException();
return true;
}
@@ -5291,15 +5293,16 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
- public void killApplicationWithAppId(String pkg, int appid, String reason)
+ public void killApplication(String pkg, int appId, int userId, String reason)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeString(pkg);
- data.writeInt(appid);
+ data.writeInt(appId);
+ data.writeInt(userId);
data.writeString(reason);
- mRemote.transact(KILL_APPLICATION_WITH_APPID_TRANSACTION, data, reply, 0);
+ mRemote.transact(KILL_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
@@ -6058,11 +6061,13 @@ class ActivityManagerProxy implements IActivityManager
return result;
}
- public void registerUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException {
+ public void registerUserSwitchObserver(IUserSwitchObserver observer,
+ String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(observer != null ? observer.asBinder() : null);
+ data.writeString(name);
mRemote.transact(REGISTER_USER_SWITCH_OBSERVER_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0728bdfc4016..3f15a755bd79 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -236,6 +236,7 @@ public final class ActivityThread {
boolean mSystemThread = false;
boolean mJitEnabled = false;
boolean mSomeActivitiesChanged = false;
+ boolean mUpdatingSystemConfig = false;
// These can be accessed by multiple threads; mPackages is the lock.
// XXX For now we keep around information about all packages we have
@@ -1574,7 +1575,9 @@ public final class ActivityThread {
case CONFIGURATION_CHANGED:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
+ mUpdatingSystemConfig = true;
handleConfigurationChanged((Configuration)msg.obj, null);
+ mUpdatingSystemConfig = false;
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CLEAN_UP_CONTEXT:
@@ -4629,7 +4632,14 @@ public final class ActivityThread {
// onConfigurationChanged
int diff = activity.mCurrentConfig.diff(newConfig);
if (diff != 0) {
- shouldChangeConfig = true;
+ // Always send the task-level config changes. For system-level configuration, if
+ // this activity doesn't handle any of the config changes, then don't bother
+ // calling onConfigurationChanged as we're going to destroy it.
+ if (!mUpdatingSystemConfig
+ || (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
+ || !reportToActivity) {
+ shouldChangeConfig = true;
+ }
}
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index cf663a32a072..e6ca52072079 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -16,6 +16,8 @@
package android.app;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -30,6 +32,7 @@ import android.content.IntentSender;
import android.content.ReceiverCallNotAllowedException;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -155,10 +158,9 @@ class ContextImpl extends Context {
private final String mBasePackageName;
private final String mOpPackageName;
- private final ResourcesManager mResourcesManager;
- private final Resources mResources;
- private final Display mDisplay; // may be null if default display
- private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
+ private final @NonNull ResourcesManager mResourcesManager;
+ private final @NonNull Resources mResources;
+ private @Nullable Display mDisplay; // may be null if default display
private final int mFlags;
@@ -1897,18 +1899,6 @@ class ContextImpl extends Context {
mUser, mFlags, display, null, Display.INVALID_DISPLAY);
}
- Display getDisplay() {
- if (mDisplay != null) {
- return mDisplay;
- }
- return ResourcesManager.getInstance().getAdjustedDisplay(
- Display.DEFAULT_DISPLAY, mDisplayAdjustments);
- }
-
- private int getDisplayId() {
- return mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
- }
-
@Override
public Context createDeviceProtectedStorageContext() {
final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
@@ -1941,8 +1931,23 @@ class ContextImpl extends Context {
}
@Override
+ public Display getDisplay() {
+ final DisplayAdjustments displayAdjustments = mResources.getDisplayAdjustments();
+ if (mDisplay == null) {
+ return mResourcesManager.getAdjustedDisplay(Display.DEFAULT_DISPLAY,
+ displayAdjustments);
+ }
+
+ if (!mDisplay.getDisplayAdjustments().equals(displayAdjustments)) {
+ mDisplay = mResourcesManager.getAdjustedDisplay(mDisplay.getDisplayId(),
+ displayAdjustments);
+ }
+ return mDisplay;
+ }
+
+ @Override
public DisplayAdjustments getDisplayAdjustments(int displayId) {
- return mDisplayAdjustments;
+ return mResources.getDisplayAdjustments();
}
@Override
@@ -2057,11 +2062,6 @@ class ContextImpl extends Context {
? packageInfo.getCompatibilityInfo()
: CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
}
- mDisplayAdjustments.setCompatibilityInfo(compatInfo);
- mDisplayAdjustments.setConfiguration(overrideConfiguration);
-
- mDisplay = (createDisplayWithId == Display.INVALID_DISPLAY) ? display
- : ResourcesManager.getInstance().getAdjustedDisplay(displayId, mDisplayAdjustments);
Resources resources = packageInfo.getResources(mainThread);
if (resources != null) {
@@ -2101,6 +2101,9 @@ class ContextImpl extends Context {
}
mResources = resources;
+ mDisplay = (createDisplayWithId == Display.INVALID_DISPLAY) ? display
+ : mResourcesManager.getAdjustedDisplay(displayId, mResources.getDisplayAdjustments());
+
if (container != null) {
mBasePackageName = container.mBasePackageName;
mOpPackageName = container.mOpPackageName;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index ac213461f578..3f7ff0bede57 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -398,7 +398,7 @@ public interface IActivityManager extends IInterface {
public void addPackageDependency(String packageName) throws RemoteException;
- public void killApplicationWithAppId(String pkg, int appid, String reason)
+ public void killApplication(String pkg, int appId, int userId, String reason)
throws RemoteException;
public void closeSystemDialogs(String reason) throws RemoteException;
@@ -512,7 +512,8 @@ public interface IActivityManager extends IInterface {
public int getLaunchedFromUid(IBinder activityToken) throws RemoteException;
public String getLaunchedFromPackage(IBinder activityToken) throws RemoteException;
- public void registerUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
+ public void registerUserSwitchObserver(IUserSwitchObserver observer,
+ String name) throws RemoteException;
public void unregisterUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
public void requestBugReport(int bugreportType) throws RemoteException;
@@ -852,7 +853,7 @@ public interface IActivityManager extends IInterface {
int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
int ADD_PACKAGE_DEPENDENCY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
- int KILL_APPLICATION_WITH_APPID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
+ int KILL_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98;
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 0b62ed2b0917..b889c8f9a81b 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1072,6 +1072,7 @@ public final class LoadedApk {
final class Args extends BroadcastReceiver.PendingResult implements Runnable {
private Intent mCurIntent;
private final boolean mOrdered;
+ private boolean mDispatched;
public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
boolean ordered, boolean sticky, int sendingUser) {
@@ -1096,9 +1097,13 @@ public final class LoadedApk {
final IActivityManager mgr = ActivityManagerNative.getDefault();
final Intent intent = mCurIntent;
+ if (intent == null) {
+ Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
+ }
+
mCurIntent = null;
-
- if (receiver == null || mForgotten) {
+ mDispatched = true;
+ if (receiver == null || intent == null || mForgotten) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing null broadcast to " + mReceiver);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index eaea98958e45..4104d72ec5ad 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -39,6 +39,7 @@ import android.media.AudioManager;
import android.media.session.MediaSession;
import android.net.Uri;
import android.os.BadParcelableException;
+import android.os.BaseBundle;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
@@ -53,6 +54,7 @@ import android.text.style.AbsoluteSizeSpan;
import android.text.style.CharacterStyle;
import android.text.style.RelativeSizeSpan;
import android.text.style.TextAppearanceSpan;
+import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.view.Gravity;
@@ -63,6 +65,7 @@ import android.widget.ProgressBar;
import android.widget.RemoteViews;
import com.android.internal.R;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.NotificationColorUtil;
import java.lang.annotation.Retention;
@@ -70,6 +73,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -758,6 +762,15 @@ public class Notification implements Parcelable
public Bundle extras = new Bundle();
/**
+ * All pending intents in the notification as the system needs to be able to access them but
+ * touching the extras bundle in the system process is not safe because the bundle may contain
+ * custom parcelable objects.
+ *
+ * @hide
+ */
+ public ArraySet<PendingIntent> allPendingIntents;
+
+ /**
* {@link #extras} key: this is the title of the notification,
* as supplied to {@link Builder#setContentTitle(CharSequence)}.
*/
@@ -1573,7 +1586,16 @@ public class Notification implements Parcelable
/**
* Unflatten the notification from a parcel.
*/
- public Notification(Parcel parcel)
+ @SuppressWarnings("unchecked")
+ public Notification(Parcel parcel) {
+ // IMPORTANT: Add unmarshaling code in readFromParcel as the pending
+ // intents in extras are always written as the last entry.
+ readFromParcelImpl(parcel);
+ // Must be read last!
+ allPendingIntents = (ArraySet<PendingIntent>) parcel.readArraySet(null);
+ }
+
+ private void readFromParcelImpl(Parcel parcel)
{
int version = parcel.readInt();
@@ -1728,6 +1750,10 @@ public class Notification implements Parcelable
}
}
+ if (!ArrayUtils.isEmpty(allPendingIntents)) {
+ that.allPendingIntents = new ArraySet<>(allPendingIntents);
+ }
+
if (this.actions != null) {
that.actions = new Action[this.actions.length];
for(int i=0; i<this.actions.length; i++) {
@@ -1843,8 +1869,40 @@ public class Notification implements Parcelable
/**
* Flatten this notification into a parcel.
*/
- public void writeToParcel(Parcel parcel, int flags)
- {
+ public void writeToParcel(Parcel parcel, int flags) {
+ // We need to mark all pending intents getting into the notification
+ // system as being put there to later allow the notification ranker
+ // to launch them and by doing so add the app to the battery saver white
+ // list for a short period of time. The problem is that the system
+ // cannot look into the extras as there may be parcelables there that
+ // the platform does not know how to handle. To go around that we have
+ // an explicit list of the pending intents in the extras bundle.
+ final boolean collectPendingIntents = (allPendingIntents == null);
+ if (collectPendingIntents) {
+ PendingIntent.setOnMarshaledListener(
+ (PendingIntent intent, Parcel out, int outFlags) -> {
+ if (parcel == out) {
+ if (allPendingIntents == null) {
+ allPendingIntents = new ArraySet<>();
+ }
+ allPendingIntents.add(intent);
+ }
+ });
+ }
+ try {
+ // IMPORTANT: Add marshaling code in writeToParcelImpl as we
+ // want to intercept all pending events written to the pacel.
+ writeToParcelImpl(parcel, flags);
+ // Must be written last!
+ parcel.writeArraySet(allPendingIntents);
+ } finally {
+ if (collectPendingIntents) {
+ PendingIntent.setOnMarshaledListener(null);
+ }
+ }
+ }
+
+ private void writeToParcelImpl(Parcel parcel, int flags) {
parcel.writeInt(1);
parcel.writeLong(when);
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index cb15392b6a8a..cfa242be02aa 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -242,6 +242,36 @@ public final class PendingIntent implements Parcelable {
}
/**
+ * Listener for observing when pending intents are written to a parcel.
+ *
+ * @hide
+ */
+ public interface OnMarshaledListener {
+ /**
+ * Called when a pending intent is written to a parcel.
+ *
+ * @param intent The pending intent.
+ * @param parcel The parcel to which it was written.
+ * @param flags The parcel flags when it was written.
+ */
+ void onMarshaled(PendingIntent intent, Parcel parcel, int flags);
+ }
+
+ private static final ThreadLocal<OnMarshaledListener> sOnMarshaledListener
+ = new ThreadLocal<>();
+
+ /**
+ * Registers an listener for pending intents being written to a parcel.
+ *
+ * @param listener The listener, null to clear.
+ *
+ * @hide
+ */
+ public static void setOnMarshaledListener(OnMarshaledListener listener) {
+ sOnMarshaledListener.set(listener);
+ }
+
+ /**
* Retrieve a PendingIntent that will start a new activity, like calling
* {@link Context#startActivity(Intent) Context.startActivity(Intent)}.
* Note that the activity will be started outside of the context of an
@@ -1016,6 +1046,11 @@ public final class PendingIntent implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeStrongBinder(mTarget.asBinder());
+ OnMarshaledListener listener = sOnMarshaledListener.get();
+ if (listener != null) {
+ listener.onMarshaled(this, out, flags);
+ }
+
}
public static final Parcelable.Creator<PendingIntent> CREATOR
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
index e110dcbf1d2a..70007f584645 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -310,7 +310,7 @@ public class Presentation extends Dialog {
final WindowManagerImpl outerWindowManager =
(WindowManagerImpl)outerContext.getSystemService(Context.WINDOW_SERVICE);
final WindowManagerImpl displayWindowManager =
- outerWindowManager.createPresentationWindowManager(display);
+ outerWindowManager.createPresentationWindowManager(displayContext);
return new ContextThemeWrapper(displayContext, theme) {
@Override
public Object getSystemService(String name) {
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index f56a6ad855d4..c4673a3b0b4c 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -149,17 +149,17 @@ public class ResourcesManager {
}
DisplayMetrics getDisplayMetrics() {
- return getDisplayMetrics(Display.DEFAULT_DISPLAY);
+ return getDisplayMetrics(Display.DEFAULT_DISPLAY,
+ DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
}
/**
* Protected so that tests can override and returns something a fixed value.
*/
@VisibleForTesting
- protected @NonNull DisplayMetrics getDisplayMetrics(int displayId) {
+ protected @NonNull DisplayMetrics getDisplayMetrics(int displayId, DisplayAdjustments da) {
DisplayMetrics dm = new DisplayMetrics();
- final Display display =
- getAdjustedDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+ final Display display = getAdjustedDisplay(displayId, da);
if (display != null) {
display.getMetrics(dm);
} else {
@@ -304,10 +304,13 @@ public class ResourcesManager {
}
private @NonNull ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key) {
- AssetManager assets = createAssetManager(key);
- DisplayMetrics dm = getDisplayMetrics(key.mDisplayId);
- Configuration config = generateConfig(key, dm);
- ResourcesImpl impl = new ResourcesImpl(assets, dm, config, key.mCompatInfo);
+ final DisplayAdjustments daj = new DisplayAdjustments(key.mOverrideConfiguration);
+ daj.setCompatibilityInfo(key.mCompatInfo);
+
+ final AssetManager assets = createAssetManager(key);
+ final DisplayMetrics dm = getDisplayMetrics(key.mDisplayId, daj);
+ final Configuration config = generateConfig(key, dm);
+ final ResourcesImpl impl = new ResourcesImpl(assets, dm, config, daj);
if (DEBUG) {
Slog.d(TAG, "- creating impl=" + impl + " with key: " + key);
}
@@ -804,7 +807,16 @@ public class ResourcesManager {
}
tmpConfig.setTo(config);
if (!isDefaultDisplay) {
- dm = getDisplayMetrics(displayId);
+ // Get new DisplayMetrics based on the DisplayAdjustments given
+ // to the ResourcesImpl. Udate a copy if the CompatibilityInfo
+ // changed, because the ResourcesImpl object will handle the
+ // update internally.
+ DisplayAdjustments daj = r.getDisplayAdjustments();
+ if (compat != null) {
+ daj = new DisplayAdjustments(daj);
+ daj.setCompatibilityInfo(compat);
+ }
+ dm = getDisplayMetrics(displayId, daj);
applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
}
if (hasOverrideConfiguration) {
diff --git a/services/core/java/com/android/server/am/RetailDemoModeServiceInternal.java b/core/java/android/app/RetailDemoModeServiceInternal.java
index 32de03a31cb9..7ca214aae602 100644
--- a/services/core/java/com/android/server/am/RetailDemoModeServiceInternal.java
+++ b/core/java/android/app/RetailDemoModeServiceInternal.java
@@ -14,8 +14,16 @@
* limitations under the License
*/
-package com.android.server.am;
+package android.app;
+/**
+ * Retail Demo Mode Service interface to be used locally inside system server
+ *
+ * @hide Only for use inside system server
+ */
public interface RetailDemoModeServiceInternal {
+ /**
+ * Used to notify RetailDemoModeService of any user activity.
+ */
public void onUserActivity();
} \ No newline at end of file
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 7cd13ea4ff9d..55744b935f51 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -559,7 +559,7 @@ final class SystemServiceRegistry {
new CachedServiceFetcher<WindowManager>() {
@Override
public WindowManager createService(ContextImpl ctx) {
- return new WindowManagerImpl(ctx.getDisplay());
+ return new WindowManagerImpl(ctx);
}});
registerService(Context.USER_SERVICE, UserManager.class,
diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java
index 84a16cf3e96a..9d40381fcefd 100644
--- a/core/java/android/app/WallpaperInfo.java
+++ b/core/java/android/app/WallpaperInfo.java
@@ -312,7 +312,12 @@ public final class WallpaperInfo implements Parcelable {
}
/**
- * Queries whether any metadata should be shown when previewing the wallpaper.
+ * Queries whether any metadata should be shown when previewing the wallpaper. If this value is
+ * set to true, any component that shows a preview of this live wallpaper should also show
+ * accompanying information like {@link #loadLabel},
+ * {@link #loadDescription}, {@link #loadAuthor} and
+ * {@link #loadContextDescription(PackageManager)}, so the user gets to know further information
+ * about this wallpaper.
*
* @return Whether any metadata should be shown when previewing the wallpaper.
*/
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 63afdd86bd93..325a15f1cb30 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3030,8 +3030,6 @@ public class DevicePolicyManager {
* @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
* {@code false} otherwise. This carries the risk that any failure of the VPN provider
* could break networking for all apps. This has no effect when clearing.
- * @return {@code true} if the package is set as always-on VPN controller; {@code false}
- * otherwise.
* @throws SecurityException if {@code admin} is not a device or a profile owner.
* @throws NameNotFoundException if {@code vpnPackage} is not installed.
* @throws UnsupportedOperationException if {@code vpnPackage} exists but does not support being
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 5d4cc6fe2dc9..a320bbf9d178 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -218,6 +218,14 @@ interface IBackupManager {
String[] listAllTransports();
/**
+ * Retrieve the list of whitelisted transport components. Callers do </i>not</i> need
+ * any special permission.
+ *
+ * @return The names of all whitelisted transport components defined by the system.
+ */
+ String[] getTransportWhitelist();
+
+ /**
* Specify the current backup transport. Callers must hold the
* android.permission.BACKUP permission to use this method.
*
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index c4ca82e59b99..5823abf9d78f 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -28,6 +28,7 @@ import android.os.PersistableBundle;
import android.util.Log;
import java.util.ArrayList;
+import java.util.Objects;
/**
* Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the
@@ -494,6 +495,20 @@ public class JobInfo implements Parcelable {
return mFlags;
}
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof TriggerContentUri)) {
+ return false;
+ }
+ TriggerContentUri t = (TriggerContentUri) o;
+ return Objects.equals(t.mUri, mUri) && t.mFlags == mFlags;
+ }
+
+ @Override
+ public int hashCode() {
+ return (mUri == null ? 0 : mUri.hashCode()) ^ mFlags;
+ }
+
private TriggerContentUri(Parcel in) {
mUri = Uri.CREATOR.createFromParcel(in);
mFlags = in.readInt();
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 720c84a8e2a8..7961a72a12e4 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -305,7 +305,8 @@ public class NetworkStatsManager {
*/
public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes,
UsageCallback callback) {
- registerUsageCallback(networkType, subscriberId, thresholdBytes, null /* handler */);
+ registerUsageCallback(networkType, subscriberId, thresholdBytes, callback,
+ null /* handler */);
}
/**
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index f66b5ff466c3..353c6400ffd7 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -30,8 +30,11 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
@@ -114,7 +117,8 @@ public final class BluetoothA2dp implements BluetoothProfile {
private Context mContext;
private ServiceListener mServiceListener;
- private IBluetoothA2dp mService;
+ private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
+ @GuardedBy("mServiceLock") private IBluetoothA2dp mService;
private BluetoothAdapter mAdapter;
final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -122,25 +126,27 @@ public final class BluetoothA2dp implements BluetoothProfile {
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
- if (VDBG) Log.d(TAG,"Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG,"",re);
- }
+ if (VDBG) Log.d(TAG, "Unbinding service...");
+ try {
+ mServiceLock.writeLock().lock();
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG, "", re);
+ } finally {
+ mServiceLock.writeLock().unlock();
}
} else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (VDBG) Log.d(TAG,"Binding service...");
- doBind();
- }
- } catch (Exception re) {
- Log.e(TAG,"",re);
+ try {
+ mServiceLock.readLock().lock();
+ if (mService == null) {
+ if (VDBG) Log.d(TAG,"Binding service...");
+ doBind();
}
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ } finally {
+ mServiceLock.readLock().unlock();
}
}
}
@@ -189,15 +195,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
}
}
- synchronized (mConnection) {
+ try {
+ mServiceLock.writeLock().lock();
if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG,"",re);
- }
+ mService = null;
+ mContext.unbindService(mConnection);
}
+ } catch (Exception re) {
+ Log.e(TAG, "", re);
+ } finally {
+ mServiceLock.writeLock().unlock();
}
}
@@ -229,17 +236,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- if (mService != null && isEnabled() &&
- isValidDevice(device)) {
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
return mService.connect(device);
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return false;
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return false;
}
/**
@@ -270,17 +280,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- if (mService != null && isEnabled() &&
- isValidDevice(device)) {
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
return mService.disconnect(device);
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return false;
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return false;
}
/**
@@ -288,16 +301,19 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- if (mService != null && isEnabled()) {
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
return mService.getConnectedDevices();
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return new ArrayList<BluetoothDevice>();
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return new ArrayList<BluetoothDevice>();
}
/**
@@ -305,16 +321,19 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- if (mService != null && isEnabled()) {
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
return mService.getDevicesMatchingConnectionStates(states);
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return new ArrayList<BluetoothDevice>();
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<BluetoothDevice>();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return new ArrayList<BluetoothDevice>();
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return new ArrayList<BluetoothDevice>();
}
/**
@@ -322,17 +341,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
- if (mService != null && isEnabled()
- && isValidDevice(device)) {
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
return mService.getConnectionState(device);
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return BluetoothProfile.STATE_DISCONNECTED;
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.STATE_DISCONNECTED;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return BluetoothProfile.STATE_DISCONNECTED;
}
/**
@@ -352,21 +374,24 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- if (mService != null && isEnabled()
- && isValidDevice(device)) {
- if (priority != BluetoothProfile.PRIORITY_OFF &&
- priority != BluetoothProfile.PRIORITY_ON){
- return false;
- }
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
+ if (priority != BluetoothProfile.PRIORITY_OFF &&
+ priority != BluetoothProfile.PRIORITY_ON) {
+ return false;
+ }
return mService.setPriority(device, priority);
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return false;
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return false;
}
/**
@@ -385,17 +410,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
@RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- if (mService != null && isEnabled()
- && isValidDevice(device)) {
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
return mService.getPriority(device);
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return BluetoothProfile.PRIORITY_OFF;
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.PRIORITY_OFF;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.PRIORITY_OFF;
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return BluetoothProfile.PRIORITY_OFF;
}
/**
@@ -406,16 +434,19 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public boolean isAvrcpAbsoluteVolumeSupported() {
if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
- if (mService != null && isEnabled()) {
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
return mService.isAvrcpAbsoluteVolumeSupported();
- } catch (RemoteException e) {
- Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
- return false;
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
+ return false;
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return false;
}
/**
@@ -433,16 +464,17 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public void adjustAvrcpAbsoluteVolume(int direction) {
if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
- if (mService != null && isEnabled()) {
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
mService.adjustAvrcpAbsoluteVolume(direction);
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
- return;
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
}
/**
@@ -453,16 +485,17 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public void setAvrcpAbsoluteVolume(int volume) {
if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
- if (mService != null && isEnabled()) {
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()) {
mService.setAvrcpAbsoluteVolume(volume);
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
- return;
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
}
/**
@@ -473,17 +506,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
* @param device BluetoothDevice device
*/
public boolean isA2dpPlaying(BluetoothDevice device) {
- if (mService != null && isEnabled()
- && isValidDevice(device)) {
- try {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null && isEnabled()
+ && isValidDevice(device)) {
return mService.isA2dpPlaying(device);
- } catch (RemoteException e) {
- Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return false;
}
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+ return false;
+ } finally {
+ mServiceLock.readLock().unlock();
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return false;
}
/**
@@ -534,7 +570,12 @@ public final class BluetoothA2dp implements BluetoothProfile {
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothA2dp.Stub.asInterface(service);
+ try {
+ mServiceLock.writeLock().lock();
+ mService = IBluetoothA2dp.Stub.asInterface(service);
+ } finally {
+ mServiceLock.writeLock().unlock();
+ }
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
@@ -542,7 +583,12 @@ public final class BluetoothA2dp implements BluetoothProfile {
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
+ try {
+ mServiceLock.writeLock().lock();
+ mService = null;
+ } finally {
+ mServiceLock.writeLock().unlock();
+ }
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 9390bcd13de3..47ae68796f65 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -897,28 +897,10 @@ public final class BluetoothAdapter {
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean enable() {
- int state = BluetoothAdapter.STATE_OFF;
if (isEnabled() == true) {
if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
return true;
}
- // Use service interface to get the exact state
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- state = mService.getState();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- } finally {
- mServiceLock.readLock().unlock();
- }
-
- if (state == BluetoothAdapter.STATE_BLE_ON) {
- Log.e(TAG, "BT is in BLE_ON State");
- notifyUserAction(true);
- return true;
- }
try {
return mManagerService.enable();
} catch (RemoteException e) {Log.e(TAG, "", e);}
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index ae12c88ff233..ec01beff9310 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -532,22 +532,19 @@ public final class BluetoothSocket implements Closeable {
if(length <= mMaxTxPacketSize) {
mSocketOS.write(b, offset, length);
} else {
- int tmpOffset = offset;
- int tmpLength = mMaxTxPacketSize;
- int endIndex = offset + length;
- boolean done = false;
if(DBG) Log.w(TAG, "WARNING: Write buffer larger than L2CAP packet size!\n"
+ "Packet will be divided into SDU packets of size "
+ mMaxTxPacketSize);
- do{
+ int tmpOffset = offset;
+ int bytesToWrite = length;
+ while (bytesToWrite > 0) {
+ int tmpLength = (bytesToWrite > mMaxTxPacketSize)
+ ? mMaxTxPacketSize
+ : bytesToWrite;
mSocketOS.write(b, tmpOffset, tmpLength);
- tmpOffset += mMaxTxPacketSize;
- if((tmpOffset + mMaxTxPacketSize) > endIndex) {
- tmpLength = endIndex - tmpOffset;
- done = true;
- }
- } while(!done);
-
+ tmpOffset += tmpLength;
+ bytesToWrite -= tmpLength;
+ }
}
} else {
mSocketOS.write(b, offset, length);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index aeda7a24066d..c8d89204d8d4 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1819,6 +1819,7 @@ public abstract class ContentResolver {
* calling app. That is, the returned permissions have been granted
* <em>to</em> the calling app. Only persistable grants taken with
* {@link #takePersistableUriPermission(Uri, int)} are returned.
+ * <p>Note: Some of the returned URIs may not be usable until after the user is unlocked.
*
* @see #takePersistableUriPermission(Uri, int)
* @see #releasePersistableUriPermission(Uri, int)
@@ -1837,6 +1838,7 @@ public abstract class ContentResolver {
* calling app. That is, the returned permissions have been granted
* <em>from</em> the calling app. Only grants taken with
* {@link #takePersistableUriPermission(Uri, int)} are returned.
+ * <p>Note: Some of the returned URIs may not be usable until after the user is unlocked.
*/
public @NonNull List<UriPermission> getOutgoingPersistedUriPermissions() {
try {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ca798f63d1b2..3f18ea91c99a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3615,7 +3615,8 @@ public abstract class Context {
public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
/**
- * TODO Javadoc
+ * Use with {@link #getSystemService} to retrieve a
+ * {@link android.content.pm.ShortcutManager} for accessing the launcher shortcut service.
*
* @see #getSystemService
* @see android.content.pm.ShortcutManager
@@ -4277,6 +4278,11 @@ public abstract class Context {
public abstract DisplayAdjustments getDisplayAdjustments(int displayId);
/**
+ * @hide
+ */
+ public abstract Display getDisplay();
+
+ /**
* Indicates whether this Context is restricted.
*
* @return {@code true} if this Context is restricted, {@code false} otherwise.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 087ac4781803..60da63e9bc09 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -819,6 +819,14 @@ public class ContextWrapper extends Context {
return mBase.getDisplayAdjustments(displayId);
}
+ /**
+ * @hide
+ */
+ @Override
+ public Display getDisplay() {
+ return mBase.getDisplay();
+ }
+
@Override
public Context createDeviceProtectedStorageContext() {
return mBase.createDeviceProtectedStorageContext();
diff --git a/core/java/android/content/pm/EphemeralResolveInfo.java b/core/java/android/content/pm/EphemeralResolveInfo.java
index 2b9cfa0050fa..fc3b95850d21 100644
--- a/core/java/android/content/pm/EphemeralResolveInfo.java
+++ b/core/java/android/content/pm/EphemeralResolveInfo.java
@@ -27,6 +27,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
/**
* Information about an ephemeral application.
@@ -52,7 +53,7 @@ public final class EphemeralResolveInfo implements Parcelable {
throw new IllegalArgumentException();
}
- mDigest = new EphemeralDigest(uri, -1);
+ mDigest = new EphemeralDigest(uri, 0xFFFFFFFF, -1);
mFilters.addAll(filters);
mPackageName = packageName;
}
@@ -134,7 +135,7 @@ public final class EphemeralResolveInfo implements Parcelable {
/** The first 4 bytes of the domain hashes */
private final int[] mDigestPrefix;
- public EphemeralDigest(@NonNull Uri uri, int maxDigests) {
+ public EphemeralDigest(@NonNull Uri uri, int digestMask, int maxDigests) {
if (uri == null) {
throw new IllegalArgumentException();
}
@@ -142,17 +143,18 @@ public final class EphemeralResolveInfo implements Parcelable {
mDigestPrefix = new int[mDigestBytes.length];
for (int i = 0; i < mDigestBytes.length; i++) {
mDigestPrefix[i] =
- (mDigestBytes[i][0] & 0xFF) << 24
- | (mDigestBytes[i][1] & 0xFF) << 16
- | (mDigestBytes[i][2] & 0xFF) << 8
- | (mDigestBytes[i][3] & 0xFF) << 0;
+ ((mDigestBytes[i][0] & 0xFF) << 24
+ | (mDigestBytes[i][1] & 0xFF) << 16
+ | (mDigestBytes[i][2] & 0xFF) << 8
+ | (mDigestBytes[i][3] & 0xFF) << 0)
+ & digestMask;
}
}
private static byte[][] generateDigest(Uri uri, int maxDigests) {
ArrayList<byte[]> digests = new ArrayList<>();
try {
- final String host = uri.getHost();
+ final String host = uri.getHost().toLowerCase(Locale.ENGLISH);
final MessageDigest digest = MessageDigest.getInstance(SHA_ALGORITHM);
if (maxDigests <= 0) {
final byte[] hostBytes = host.getBytes();
diff --git a/core/java/android/content/pm/IOtaDexopt.aidl b/core/java/android/content/pm/IOtaDexopt.aidl
index 786a77f64110..467bd5f5e82b 100644
--- a/core/java/android/content/pm/IOtaDexopt.aidl
+++ b/core/java/android/content/pm/IOtaDexopt.aidl
@@ -50,6 +50,13 @@ interface IOtaDexopt {
/**
* Optimize the next package. Note: this command is synchronous, that is, only returns after
* the package has been dexopted (or dexopting failed).
+ *
+ * Note: this will be removed after a transition period. Use nextDexoptCommand instead.
*/
void dexoptNextPackage();
+
+ /**
+ * Get the optimization parameters for the next package.
+ */
+ String nextDexoptCommand();
}
diff --git a/core/java/android/content/pm/IShortcutService.aidl b/core/java/android/content/pm/IShortcutService.aidl
index 1c373f91fb53..7ba1b8bb3905 100644
--- a/core/java/android/content/pm/IShortcutService.aidl
+++ b/core/java/android/content/pm/IShortcutService.aidl
@@ -46,7 +46,7 @@ interface IShortcutService {
void enableShortcuts(String packageName, in List shortcutIds, int userId);
- int getMaxDynamicShortcutCount(String packageName, int userId);
+ int getMaxShortcutCountForActivity(String packageName, int userId);
int getRemainingCallCount(String packageName, int userId);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 6cb50fc1576b..d57968f253c2 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -171,8 +171,9 @@ public class LauncherApps {
* as defined in {@link #hasShortcutHostPermission()}, will receive it.
*
* @param packageName The name of the package that has the shortcuts.
- * @param shortcuts all shortcuts from the package (dynamic and/or pinned). Only "key"
- * information will be provided, as defined in {@link ShortcutInfo#hasKeyFieldsOnly()}.
+ * @param shortcuts all shortcuts from the package (dynamic, manifest and/or pinned).
+ * Only "key" information will be provided, as defined in
+ * {@link ShortcutInfo#hasKeyFieldsOnly()}.
* @param user The UserHandle of the profile that generated the change.
*/
public void onShortcutsChanged(@NonNull String packageName,
@@ -187,17 +188,37 @@ public class LauncherApps {
/**
* Include dynamic shortcuts in the result.
*/
- public static final int FLAG_GET_DYNAMIC = 1 << 0;
+ public static final int FLAG_MATCH_DYNAMIC = 1 << 0;
+
+ /** @hide kept for unit tests */
+ @Deprecated
+ public static final int FLAG_GET_DYNAMIC = FLAG_MATCH_DYNAMIC;
/**
* Include pinned shortcuts in the result.
*/
- public static final int FLAG_GET_PINNED = 1 << 1;
+ public static final int FLAG_MATCH_PINNED = 1 << 1;
+
+ /** @hide kept for unit tests */
+ @Deprecated
+ public static final int FLAG_GET_PINNED = FLAG_MATCH_PINNED;
/**
* Include manifest shortcuts in the result.
*/
- public static final int FLAG_GET_MANIFEST = 1 << 3;
+ public static final int FLAG_MATCH_MANIFEST = 1 << 3;
+
+ /** @hide kept for unit tests */
+ @Deprecated
+ public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
+
+ /** @hide */
+ public static final int FLAG_MATCH_ALL_KINDS =
+ FLAG_GET_DYNAMIC | FLAG_GET_PINNED | FLAG_GET_MANIFEST;
+
+ /** @hide kept for unit tests */
+ @Deprecated
+ public static final int FLAG_GET_ALL_KINDS = FLAG_MATCH_ALL_KINDS;
/**
* Requests "key" fields only. See {@link ShortcutInfo#hasKeyFieldsOnly()} for which
@@ -208,9 +229,9 @@ public class LauncherApps {
/** @hide */
@IntDef(flag = true,
value = {
- FLAG_GET_DYNAMIC,
- FLAG_GET_PINNED,
- FLAG_GET_MANIFEST,
+ FLAG_MATCH_DYNAMIC,
+ FLAG_MATCH_PINNED,
+ FLAG_MATCH_MANIFEST,
FLAG_GET_KEY_FIELDS_ONLY,
})
@Retention(RetentionPolicy.SOURCE)
@@ -480,12 +501,13 @@ public class LauncherApps {
* @hide // No longer used. Use getShortcuts() instead. Kept for unit tests.
*/
@Nullable
+ @Deprecated
public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName,
@NonNull List<String> ids, @NonNull UserHandle user) {
final ShortcutQuery q = new ShortcutQuery();
q.setPackage(packageName);
q.setShortcutIds(ids);
- q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+ q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
return getShortcuts(q, user);
}
@@ -514,6 +536,7 @@ public class LauncherApps {
/**
* @hide kept for testing.
*/
+ @Deprecated
public int getShortcutIconResId(@NonNull ShortcutInfo shortcut) {
return shortcut.getIconResourceId();
}
@@ -521,25 +544,20 @@ public class LauncherApps {
/**
* @hide kept for testing.
*/
+ @Deprecated
public int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId,
@NonNull UserHandle user) {
final ShortcutQuery q = new ShortcutQuery();
q.setPackage(packageName);
q.setShortcutIds(Arrays.asList(shortcutId));
- q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+ q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
final List<ShortcutInfo> shortcuts = getShortcuts(q, user);
return shortcuts.size() > 0 ? shortcuts.get(0).getIconResourceId() : 0;
}
/**
- * Return the icon as {@link ParcelFileDescriptor}, when it's stored as a file
- * (i.e. when {@link ShortcutInfo#hasIconFile()} returns {@code true}).
- *
- * <p>Callers must be allowed to access the shortcut information, as defined in {@link
- * #hasShortcutHostPermission()}.
- *
- * @param shortcut The target shortcut.
+ * @hide internal/unit tests only
*/
public ParcelFileDescriptor getShortcutIconFd(
@NonNull ShortcutInfo shortcut) {
@@ -548,15 +566,7 @@ public class LauncherApps {
}
/**
- * Return the icon as {@link ParcelFileDescriptor}, when it's stored as a file
- * (i.e. when {@link ShortcutInfo#hasIconFile()} returns {@code true}).
- *
- * <p>Callers must be allowed to access the shortcut information, as defined in {@link
- * #hasShortcutHostPermission()}.
- *
- * @param packageName The target package name.
- * @param shortcutId The ID of the shortcut to lad rom.
- * @param user The UserHandle of the profile.
+ * @hide internal/unit tests only
*/
public ParcelFileDescriptor getShortcutIconFd(
@NonNull String packageName, @NonNull String shortcutId, @NonNull UserHandle user) {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b06568ca0b2d..fbe16c5db717 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -132,6 +132,9 @@ public abstract class PackageManager {
MATCH_SYSTEM_ONLY,
MATCH_FACTORY_ONLY,
MATCH_DEBUG_TRIAGED_MISSING,
+ GET_DISABLED_COMPONENTS,
+ GET_DISABLED_UNTIL_USED_COMPONENTS,
+ GET_UNINSTALLED_PACKAGES,
})
@Retention(RetentionPolicy.SOURCE)
public @interface PackageInfoFlags {}
@@ -143,6 +146,7 @@ public abstract class PackageManager {
MATCH_UNINSTALLED_PACKAGES,
MATCH_SYSTEM_ONLY,
MATCH_DEBUG_TRIAGED_MISSING,
+ GET_UNINSTALLED_PACKAGES,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApplicationInfoFlags {}
@@ -160,6 +164,9 @@ public abstract class PackageManager {
MATCH_DIRECT_BOOT_UNAWARE,
MATCH_SYSTEM_ONLY,
MATCH_UNINSTALLED_PACKAGES,
+ GET_DISABLED_COMPONENTS,
+ GET_DISABLED_UNTIL_USED_COMPONENTS,
+ GET_UNINSTALLED_PACKAGES,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ComponentInfoFlags {}
@@ -178,6 +185,9 @@ public abstract class PackageManager {
MATCH_DIRECT_BOOT_UNAWARE,
MATCH_SYSTEM_ONLY,
MATCH_UNINSTALLED_PACKAGES,
+ GET_DISABLED_COMPONENTS,
+ GET_DISABLED_UNTIL_USED_COMPONENTS,
+ GET_UNINSTALLED_PACKAGES,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ResolveInfoFlags {}
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 14f7727e61a0..d208fe7c10ca 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -157,7 +157,7 @@ public abstract class PackageManagerInternal {
int deviceOwnerUserId, String deviceOwner, SparseArray<String> profileOwners);
/**
- * Whether a package's data be cleared.
+ * Returns {@code true} if a given package can't be wiped. Otherwise, returns {@code false}.
*/
- public abstract boolean canPackageBeWiped(int userId, String packageName);
+ public abstract boolean isPackageDataProtected(int userId, String packageName);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index f59a7dda5696..82cd448e7776 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1876,7 +1876,7 @@ public class PackageParser {
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestUsesSdk);
- int minVers = 0;
+ int minVers = 1;
String minCode = null;
int targetVers = 0;
String targetCode = null;
@@ -1903,9 +1903,6 @@ public class PackageParser {
} else {
// If it's not a string, it's an integer.
targetVers = val.data;
- if (minVers == 0) {
- minVers = targetVers;
- }
}
}
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 064b9090c444..35370f0998fd 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -39,6 +39,7 @@ import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.List;
import java.util.Set;
// TODO Enhance javadoc
@@ -294,6 +295,7 @@ public final class ShortcutInfo implements Parcelable {
mUserId = source.mUserId;
mId = source.mId;
mPackageName = source.mPackageName;
+ mActivity = source.mActivity;
mFlags = source.mFlags;
mLastChangedTimestamp = source.mLastChangedTimestamp;
@@ -301,7 +303,6 @@ public final class ShortcutInfo implements Parcelable {
mIconResId = source.mIconResId;
if ((cloneFlags & CLONE_REMOVE_NON_KEY_INFO) == 0) {
- mActivity = source.mActivity;
if ((cloneFlags & CLONE_REMOVE_ICON) == 0) {
mIcon = source.mIcon;
@@ -694,24 +695,43 @@ public final class ShortcutInfo implements Parcelable {
private PersistableBundle mExtras;
- /** Constructor. */
+ /**
+ * Old style constructor. STOPSHIP hide it before launch.
+ */
+ @Deprecated
public Builder(Context context) {
mContext = context;
}
/**
- * Sets the ID of the shortcut. This is a mandatory field.
+ * Used with the old style constructor, kept for unit tests. STOPSHIP hide it before launch.
*/
@NonNull
+ @Deprecated
public Builder setId(@NonNull String id) {
- mId = Preconditions.checkStringNotEmpty(id, "id");
+ mId = Preconditions.checkStringNotEmpty(id, "id cannot be empty");
return this;
}
/**
- * Optionally sets the target activity. If it's not set, and if the caller application
- * has multiple launcher icons, this shortcut will be shown on all those icons.
- * If it's set, this shortcut will be only shown on this activity.
+ * Constructor.
+ *
+ * @param context Client context.
+ * @param id ID of the shortcut.
+ */
+ public Builder(Context context, String id) {
+ mContext = context;
+ mId = Preconditions.checkStringNotEmpty(id, "id cannot be empty");
+ }
+
+ /**
+ * Sets the target activity. A shortcut will be shown with this activity on the launcher.
+ *
+ * <p>Only "main" activities -- i.e. ones with an intent filter for
+ * {@link Intent#ACTION_MAIN} and {@link Intent#CATEGORY_LAUNCHER} can be target activities.
+ *
+ * <p>By default, the first main activity defined in the application manifest will be
+ * the target.
*
* <p>The package name of the target activity must match the package name of the shortcut
* publisher.
@@ -721,23 +741,23 @@ public final class ShortcutInfo implements Parcelable {
*/
@NonNull
public Builder setActivity(@NonNull ComponentName activity) {
- mActivity = Preconditions.checkNotNull(activity, "activity");
+ mActivity = Preconditions.checkNotNull(activity, "activity cannot be null");
return this;
}
/**
- * Optionally sets an icon.
+ * Sets an icon.
*
* <ul>
* <li>Tints set by {@link Icon#setTint} or {@link Icon#setTintList} are not supported.
* <li>Bitmaps and resources are supported, but "content:" URIs are not supported.
* </ul>
*
- * <p>For performance reasons, icons will <b>NOT</b> be available on instances
- * returned by {@link ShortcutManager} or {@link LauncherApps}. Launcher applications
- * can use {@link ShortcutInfo#getIconResourceId()} if {@link #hasIconResource()} is true.
- * Otherwise, if {@link #hasIconFile()} is true, use
- * {@link LauncherApps#getShortcutIconFd} to load the image.
+ * <p>For performance and security reasons, icons will <b>NOT</b> be available on instances
+ * returned by {@link ShortcutManager} or {@link LauncherApps}. Default launcher application
+ * can use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}
+ * or {@link LauncherApps#getShortcutBadgedIconDrawable(ShortcutInfo, int)} to fetch
+ * shortcut icons.
*/
@NonNull
public Builder setIcon(Icon icon) {
@@ -749,6 +769,7 @@ public final class ShortcutInfo implements Parcelable {
* @hide We don't support resource strings for dynamic shortcuts for now. (But unit tests
* use it.)
*/
+ @Deprecated
public Builder setShortLabelResId(int shortLabelResId) {
Preconditions.checkState(mTitle == null, "shortLabel already set");
mTitleResId = shortLabelResId;
@@ -756,7 +777,10 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Sets the short title of a shortcut. This is a mandatory field.
+ * Sets the short title of a shortcut.
+ *
+ * <p>This is a mandatory field, unless it's passed to
+ * {@link ShortcutManager#updateShortcuts(List)}.
*
* <p>This field is intended for a concise description of a shortcut displayed under
* an icon. The recommend max length is 10 characters.
@@ -764,7 +788,7 @@ public final class ShortcutInfo implements Parcelable {
@NonNull
public Builder setShortLabel(@NonNull CharSequence shortLabel) {
Preconditions.checkState(mTitleResId == 0, "shortLabelResId already set");
- mTitle = Preconditions.checkStringNotEmpty(shortLabel, "shortLabel");
+ mTitle = Preconditions.checkStringNotEmpty(shortLabel, "shortLabel cannot be empty");
return this;
}
@@ -772,6 +796,7 @@ public final class ShortcutInfo implements Parcelable {
* @hide We don't support resource strings for dynamic shortcuts for now. (But unit tests
* use it.)
*/
+ @Deprecated
public Builder setLongLabelResId(int longLabelResId) {
Preconditions.checkState(mText == null, "longLabel already set");
mTextResId = longLabelResId;
@@ -779,7 +804,7 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Sets the text of a shortcut. This is an optional field.
+ * Sets the text of a shortcut.
*
* <p>This field is intended to be more descriptive than the shortcut title. The launcher
* shows this instead of the short title, when it has enough space.
@@ -788,26 +813,30 @@ public final class ShortcutInfo implements Parcelable {
@NonNull
public Builder setLongLabel(@NonNull CharSequence longLabel) {
Preconditions.checkState(mTextResId == 0, "longLabelResId already set");
- mText = Preconditions.checkStringNotEmpty(longLabel, "longLabel");
+ mText = Preconditions.checkStringNotEmpty(longLabel, "longLabel cannot be empty");
return this;
}
/** @hide -- old signature, the internal code still uses it. */
+ @Deprecated
public Builder setTitle(@NonNull CharSequence value) {
return setShortLabel(value);
}
/** @hide -- old signature, the internal code still uses it. */
+ @Deprecated
public Builder setTitleResId(int value) {
return setShortLabelResId(value);
}
/** @hide -- old signature, the internal code still uses it. */
+ @Deprecated
public Builder setText(@NonNull CharSequence value) {
return setLongLabel(value);
}
/** @hide -- old signature, the internal code still uses it. */
+ @Deprecated
public Builder setTextResId(int value) {
return setLongLabelResId(value);
}
@@ -816,6 +845,7 @@ public final class ShortcutInfo implements Parcelable {
* @hide We don't support resource strings for dynamic shortcuts for now. (But unit tests
* use it.)
*/
+ @Deprecated
public Builder setDisabledMessageResId(int disabledMessageResId) {
Preconditions.checkState(mDisabledMessage == null, "disabledMessage already set");
mDisabledMessageResId = disabledMessageResId;
@@ -827,7 +857,8 @@ public final class ShortcutInfo implements Parcelable {
Preconditions.checkState(
mDisabledMessageResId == 0, "disabledMessageResId already set");
mDisabledMessage =
- Preconditions.checkStringNotEmpty(disabledMessage, "disabledMessage");
+ Preconditions.checkStringNotEmpty(disabledMessage,
+ "disabledMessage cannot be empty");
return this;
}
@@ -849,8 +880,8 @@ public final class ShortcutInfo implements Parcelable {
*/
@NonNull
public Builder setIntent(@NonNull Intent intent) {
- mIntent = Preconditions.checkNotNull(intent, "intent");
- Preconditions.checkNotNull(mIntent.getAction(), "Intent action must be set");
+ mIntent = Preconditions.checkNotNull(intent, "intent cannot be null");
+ Preconditions.checkNotNull(mIntent.getAction(), "intent's action must be set");
return this;
}
@@ -867,7 +898,9 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Optional values that applications can set. Applications can store any meta-data of
+ * Extras that application can set to any purposes.
+ *
+ * <p>Applications can store any meta-data of
* shortcuts in this, and retrieve later from {@link ShortcutInfo#getExtras()}.
*/
@NonNull
@@ -915,6 +948,11 @@ public final class ShortcutInfo implements Parcelable {
return mActivity;
}
+ /** @hide */
+ public void setActivity(ComponentName activity) {
+ mActivity = activity;
+ }
+
/**
* Icon.
*
@@ -931,22 +969,26 @@ public final class ShortcutInfo implements Parcelable {
/** @hide -- old signature, the internal code still uses it. */
@Nullable
+ @Deprecated
public CharSequence getTitle() {
return mTitle;
}
/** @hide -- old signature, the internal code still uses it. */
+ @Deprecated
public int getTitleResId() {
return mTitleResId;
}
/** @hide -- old signature, the internal code still uses it. */
@Nullable
+ @Deprecated
public CharSequence getText() {
return mText;
}
/** @hide -- old signature, the internal code still uses it. */
+ @Deprecated
public int getTextResId() {
return mTextResId;
}
@@ -1094,7 +1136,7 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Optional values that application can set.
+ * Extras that application can set to any purposes.
*/
@Nullable
public PersistableBundle getExtras() {
@@ -1168,10 +1210,16 @@ public final class ShortcutInfo implements Parcelable {
* <p>NOTE this is whether a shortcut is published from the <b>current version's</b>
* AndroidManifest.xml.
*/
- public boolean isManifestShortcut() {
+ public boolean isDeclaredInManifest() {
return hasFlags(FLAG_MANIFEST);
}
+ /** @hide kept for unit tests */
+ @Deprecated
+ public boolean isManifestShortcut() {
+ return isDeclaredInManifest();
+ }
+
/**
* @return true if pinned but neither dynamic nor manifest.
* @hide
@@ -1191,7 +1239,7 @@ public final class ShortcutInfo implements Parcelable {
*
* <p>All manifest shortcuts are immutable. When a manifest shortcut is pinned and then
* disabled because the app is upgraded and its AndroidManifest.xml no longer publishes it,
- * {@link #isManifestShortcut} returns {@code false}, but it is still immutable.
+ * {@link #isDeclaredInManifest()} returns {@code false}, but it is still immutable.
*
* <p>All shortcuts originally published via the {@link ShortcutManager} APIs
* are all mutable.
@@ -1221,7 +1269,7 @@ public final class ShortcutInfo implements Parcelable {
/**
* Return whether a shortcut's icon is a resource in the owning package.
*
- * @see LauncherApps#getShortcutIconResId(ShortcutInfo)
+ * @hide internal/unit tests only
*/
public boolean hasIconResource() {
return hasFlags(FLAG_HAS_ICON_RES);
@@ -1240,7 +1288,7 @@ public final class ShortcutInfo implements Parcelable {
/**
* Return whether a shortcut's icon is stored as a file.
*
- * @see LauncherApps#getShortcutIconFd(ShortcutInfo)
+ * @hide internal/unit tests only
*/
public boolean hasIconFile() {
return hasFlags(FLAG_HAS_ICON_FILE);
@@ -1252,18 +1300,21 @@ public final class ShortcutInfo implements Parcelable {
* <ul>
* <li>{@link #getId()}
* <li>{@link #getPackage()}
+ * <li>{@link #getActivity()}
* <li>{@link #getLastChangedTimestamp()}
* <li>{@link #isDynamic()}
* <li>{@link #isPinned()}
- * <li>{@link #hasIconResource()}
- * <li>{@link #hasIconFile()}
+ * <li>{@link #isDeclaredInManifest()}
+ * <li>{@link #isImmutable()}
+ * <li>{@link #isEnabled()}
+ * <li>{@link #getUserHandle()}
* </ul>
*/
public boolean hasKeyFieldsOnly() {
return hasFlags(FLAG_KEY_FIELDS_ONLY);
}
- /** TODO Javadoc */
+ /** @hide */
public boolean hasStringResourcesResolved() {
return hasFlags(FLAG_STRINGS_RESOLVED);
}
@@ -1294,6 +1345,7 @@ public final class ShortcutInfo implements Parcelable {
/**
* Get the resource ID for the icon, valid only when {@link #hasIconResource()} } is true.
+ * @hide internal / tests only.
*/
public int getIconResourceId() {
return mIconResId;
@@ -1403,6 +1455,14 @@ public final class ShortcutInfo implements Parcelable {
mId = source.readString();
mPackageName = source.readString();
mActivity = source.readParcelable(cl);
+ mFlags = source.readInt();
+ mIconResId = source.readInt();
+ mLastChangedTimestamp = source.readLong();
+
+ if (source.readInt() == 0) {
+ return; // key information only.
+ }
+
mIcon = source.readParcelable(cl);
mTitle = source.readCharSequence();
mTitleResId = source.readInt();
@@ -1414,9 +1474,6 @@ public final class ShortcutInfo implements Parcelable {
mIntentPersistableExtras = source.readParcelable(cl);
mRank = source.readInt();
mExtras = source.readParcelable(cl);
- mLastChangedTimestamp = source.readLong();
- mFlags = source.readInt();
- mIconResId = source.readInt();
mBitmapPath = source.readString();
mIconResName = source.readString();
@@ -1441,6 +1498,16 @@ public final class ShortcutInfo implements Parcelable {
dest.writeString(mId);
dest.writeString(mPackageName);
dest.writeParcelable(mActivity, flags);
+ dest.writeInt(mFlags);
+ dest.writeInt(mIconResId);
+ dest.writeLong(mLastChangedTimestamp);
+
+ if (hasKeyFieldsOnly()) {
+ dest.writeInt(0);
+ return;
+ }
+ dest.writeInt(1);
+
dest.writeParcelable(mIcon, flags);
dest.writeCharSequence(mTitle);
dest.writeInt(mTitleResId);
@@ -1453,9 +1520,6 @@ public final class ShortcutInfo implements Parcelable {
dest.writeParcelable(mIntentPersistableExtras, flags);
dest.writeInt(mRank);
dest.writeParcelable(mExtras, flags);
- dest.writeLong(mLastChangedTimestamp);
- dest.writeInt(mFlags);
- dest.writeInt(mIconResId);
dest.writeString(mBitmapPath);
dest.writeString(mIconResName);
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 36ab804a0b02..3ccdef1f37a0 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -296,12 +296,13 @@ public class ShortcutManager {
}
/**
- * Return the max number of dynamic shortcuts + manifest shortcuts that each launcehr icon
+ * Return the max number of dynamic shortcuts + manifest shortcuts that each launcher icon
* can have at a time.
*/
public int getMaxShortcutCountForActivity() {
try {
- return mService.getMaxDynamicShortcutCount(mContext.getPackageName(), injectMyUserId());
+ return mService.getMaxShortcutCountForActivity(
+ mContext.getPackageName(), injectMyUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 6f43d99ecb95..b2d518c56ca0 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1543,27 +1543,41 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* @hide
*/
public static String localesToResourceQualifier(LocaleList locs) {
- StringBuilder sb = new StringBuilder();
+ final StringBuilder sb = new StringBuilder();
for (int i = 0; i < locs.size(); i++) {
- Locale loc = locs.get(i);
- boolean l = (loc.getLanguage().length() != 0);
- boolean c = (loc.getCountry().length() != 0);
- boolean s = (loc.getScript().length() != 0);
- boolean v = (loc.getVariant().length() != 0);
- // TODO: take script and extensions into account
- if (l) {
- if (sb.length() != 0) {
- sb.append(",");
- }
+ final Locale loc = locs.get(i);
+ final int l = loc.getLanguage().length();
+ if (l == 0) {
+ continue;
+ }
+ final int s = loc.getScript().length();
+ final int c = loc.getCountry().length();
+ final int v = loc.getVariant().length();
+ // We ignore locale extensions, since they are not supported by AAPT
+
+ if (sb.length() != 0) {
+ sb.append(",");
+ }
+ if (l == 2 && s == 0 && (c == 0 || c == 2) && v == 0) {
+ // Traditional locale format: xx or xx-rYY
sb.append(loc.getLanguage());
- if (c) {
+ if (c == 2) {
sb.append("-r").append(loc.getCountry());
- if (s) {
- sb.append("-s").append(loc.getScript());
- if (v) {
- sb.append("-v").append(loc.getVariant());
- }
- }
+ }
+ } else {
+ sb.append("b+");
+ sb.append(loc.getLanguage());
+ if (s != 0) {
+ sb.append("+");
+ sb.append(loc.getScript());
+ }
+ if (c != 0) {
+ sb.append("+");
+ sb.append(loc.getCountry());
+ }
+ if (v != 0) {
+ sb.append("+");
+ sb.append(loc.getVariant());
}
}
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 54a59680fe4d..8d3940c99e0d 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -51,6 +51,7 @@ import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pools.SynchronizedPool;
import android.util.TypedValue;
+import android.view.DisplayAdjustments;
import android.view.ViewDebug;
import android.view.ViewHierarchyEncoder;
@@ -208,8 +209,7 @@ public class Resources {
*/
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
this(null);
- mResourcesImpl = new ResourcesImpl(assets, metrics, config,
- CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
+ mResourcesImpl = new ResourcesImpl(assets, metrics, config, new DisplayAdjustments());
}
/**
@@ -237,7 +237,7 @@ public class Resources {
config.setToDefaults();
mResourcesImpl = new ResourcesImpl(AssetManager.getSystem(), metrics, config,
- CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
+ new DisplayAdjustments());
}
/**
@@ -1800,6 +1800,11 @@ public class Resources {
return mResourcesImpl.getDisplayMetrics();
}
+ /** @hide */
+ public DisplayAdjustments getDisplayAdjustments() {
+ return mResourcesImpl.getDisplayAdjustments();
+ }
+
/**
* Return the current configuration that is in effect for this resource
* object. The returned object should be treated as read-only.
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 000751e88639..aa8039025df6 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -44,6 +44,8 @@ import android.util.LongSparseArray;
import android.util.Slog;
import android.util.TypedValue;
import android.util.Xml;
+import android.view.Display;
+import android.view.DisplayAdjustments;
import java.io.InputStream;
import java.util.Arrays;
@@ -111,12 +113,12 @@ public class ResourcesImpl {
final AssetManager mAssets;
- final DisplayMetrics mMetrics = new DisplayMetrics();
+ private final DisplayMetrics mMetrics = new DisplayMetrics();
+ private final DisplayAdjustments mDisplayAdjustments;
private PluralRules mPluralRule;
private final Configuration mConfiguration = new Configuration();
- private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
static {
sPreloadedDrawables = new LongSparseArray[2];
@@ -132,16 +134,22 @@ public class ResourcesImpl {
* selecting/computing resource values.
* @param config Desired device configuration to consider when
* selecting/computing resource values (optional).
- * @param compatInfo this resource's compatibility info. Must not be null.
+ * @param displayAdjustments this resource's Display override and compatibility info.
+ * Must not be null.
*/
- public ResourcesImpl(AssetManager assets, DisplayMetrics metrics, Configuration config,
- CompatibilityInfo compatInfo) {
+ public ResourcesImpl(@NonNull AssetManager assets, @Nullable DisplayMetrics metrics,
+ @Nullable Configuration config, @NonNull DisplayAdjustments displayAdjustments) {
mAssets = assets;
mMetrics.setToDefaults();
- updateConfiguration(config, metrics, compatInfo);
+ mDisplayAdjustments = displayAdjustments;
+ updateConfiguration(config, metrics, displayAdjustments.getCompatibilityInfo());
mAssets.ensureStringBlocks();
}
+ public DisplayAdjustments getDisplayAdjustments() {
+ return mDisplayAdjustments;
+ }
+
public AssetManager getAssets() {
return mAssets;
}
@@ -161,7 +169,7 @@ public class ResourcesImpl {
}
CompatibilityInfo getCompatibilityInfo() {
- return mCompatibilityInfo;
+ return mDisplayAdjustments.getCompatibilityInfo();
}
private PluralRules getPluralRule() {
@@ -316,12 +324,13 @@ public class ResourcesImpl {
synchronized (mAccessLock) {
if (false) {
Slog.i(TAG, "**** Updating config of " + this + ": old config is "
- + mConfiguration + " old compat is " + mCompatibilityInfo);
+ + mConfiguration + " old compat is "
+ + mDisplayAdjustments.getCompatibilityInfo());
Slog.i(TAG, "**** Updating config of " + this + ": new config is "
+ config + " new compat is " + compat);
}
if (compat != null) {
- mCompatibilityInfo = compat;
+ mDisplayAdjustments.setCompatibilityInfo(compat);
}
if (metrics != null) {
mMetrics.setTo(metrics);
@@ -335,7 +344,7 @@ public class ResourcesImpl {
// it would be cleaner and more maintainable to just be
// consistently dealing with a compatible display everywhere in
// the framework.
- mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
+ mDisplayAdjustments.getCompatibilityInfo().applyToDisplayMetrics(mMetrics);
final @Config int configChanges = calcConfigChanges(config);
@@ -409,7 +418,8 @@ public class ResourcesImpl {
if (DEBUG_CONFIG) {
Slog.i(TAG, "**** Updating config of " + this + ": final config is "
- + mConfiguration + " final compat is " + mCompatibilityInfo);
+ + mConfiguration + " final compat is "
+ + mDisplayAdjustments.getCompatibilityInfo());
}
mDrawableCache.onConfigurationChange(configChanges);
@@ -449,7 +459,7 @@ public class ResourcesImpl {
density = mMetrics.noncompatDensityDpi;
}
- mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
+ mDisplayAdjustments.getCompatibilityInfo().applyToConfiguration(density, mTmpConfig);
if (mTmpConfig.getLocales().isEmpty()) {
mTmpConfig.setLocales(LocaleList.getDefault());
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 0f07419f4855..c9ae69c93b8c 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -20,8 +20,6 @@ package android.hardware;
import android.annotation.SystemApi;
import android.os.Build;
-import java.util.UUID;
-
/**
* Class representing a sensor. Use {@link SensorManager#getSensorList} to get
* the list of available Sensors.
@@ -806,7 +804,7 @@ public final class Sensor {
private String mRequiredPermission;
private int mMaxDelay;
private int mFlags;
- private UUID mUuid;
+ private int mId;
Sensor() {
}
@@ -895,34 +893,28 @@ public final class Sensor {
}
/**
- * @return The UUID of the sensor. If the sensor does not support UUID, the returned value will
- * be an all zero UUID; if the sensor's combination of type and name is guaranteed to be unique
- * in system, the return value will be an all "F" UUID.
+ * Do not use.
+ *
+ * This method throws an UnsupportedOperationException.
+ *
+ * Use getId() if you want a unique ID.
+ *
+ * @see getId
*
* @hide
*/
@SystemApi
- public UUID getUuid() {
- return mUuid;
+ public java.util.UUID getUuid() {
+ throw new UnsupportedOperationException();
}
/**
- * @return The unique id of sensor. Return value of 0 means this sensor does not support UUID;
- * return value of -1 means this sensor can be uniquely identified in system by combination of
- * its type and name.
+ * @return The sensor id that will be unique for the same app unless the device is factory
+ * reset. Return value of 0 means this sensor does not support this function; return value of -1
+ * means this sensor can be uniquely identified in system by combination of its type and name.
*/
public int getId() {
- if (mUuid.equals(ALL_0_UUID)) {
- return 0;
- } else if (mUuid.equals(ALL_F_UUID)) {
- return -1;
- } else {
- int id = Math.abs(mUuid.hashCode()) + 1;
- if (id <= 0) { // catch corner case when hash is Integer.MIN_VALUE and Integer.MAX_VALUE
- id = 1;
- }
- return id;
- }
+ return mId;
}
/**
@@ -1038,10 +1030,6 @@ public final class Sensor {
+ ", power=" + mPower + ", minDelay=" + mMinDelay + "}";
}
- //special UUID hash constant
- private final static UUID ALL_0_UUID = new UUID(0,0);
- private final static UUID ALL_F_UUID = new UUID(~0L, ~0L);
-
/**
* Sets the Type associated with the sensor.
* NOTE: to be used only by native bindings in SensorManager.
@@ -1141,24 +1129,17 @@ public final class Sensor {
}
/**
- * Sets the UUID associated with the sensor.
+ * Sets the ID associated with the sensor.
+ *
+ * The method name is misleading; while this ID is based on the UUID,
+ * we do not pass in the actual UUID.
*
* NOTE: to be used only by native bindings in SensorManager.
*
- * @see #getUuid
- * @see UUID
+ * @see #getId
*/
private void setUuid(long msb, long lsb) {
- // reuse static object if possible
- if (msb == lsb) {
- if (msb == 0L) {
- mUuid = ALL_0_UUID;
- return;
- } else if (msb == ~0L) {
- mUuid = ALL_F_UUID;
- return;
- }
- }
- mUuid = new UUID(msb, lsb);
+ // TODO(b/29547335): Rename this method to setId.
+ mId = (int)msb;
}
}
diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java
index 10fc8e6e366a..01a540484f1a 100644
--- a/core/java/android/hardware/input/InputManagerInternal.java
+++ b/core/java/android/hardware/input/InputManagerInternal.java
@@ -59,4 +59,9 @@ public abstract class InputManagerInternal {
* @param deviceId The id of input device.
*/
public abstract void toggleCapsLock(int deviceId);
+
+ /**
+ * Set whether the input stack should deliver pulse gesture events when the device is asleep.
+ */
+ public abstract void setPulseGestureEnabled(boolean enabled);
}
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index 3531926d347c..29177b6b47cf 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -16,11 +16,14 @@
package android.inputmethodservice;
+import android.annotation.NonNull;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodSession;
@@ -208,7 +211,7 @@ public abstract class AbstractInputMethodService extends Service
*
* @param event The motion event being received.
* @return True if the event was handled in this function, false otherwise.
- * @see View#onTrackballEvent
+ * @see android.view.View#onTrackballEvent(MotionEvent)
*/
public boolean onTrackballEvent(MotionEvent event) {
return false;
@@ -219,9 +222,30 @@ public abstract class AbstractInputMethodService extends Service
*
* @param event The motion event being received.
* @return True if the event was handled in this function, false otherwise.
- * @see View#onGenericMotionEvent
+ * @see android.view.View#onGenericMotionEvent(MotionEvent)
*/
public boolean onGenericMotionEvent(MotionEvent event) {
return false;
}
+
+ /**
+ * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
+ * permission to the content.
+ *
+ * <p>Default implementation does nothing.</p>
+ *
+ * @param inputContentInfo Content to be temporarily exposed from the input method to the
+ * application.
+ * This cannot be {@code null}.
+ * @param inputConnection {@link InputConnection} with which
+ * {@link InputConnection#commitContent(InputContentInfo, int, android.os.Bundle)} will be
+ * called.
+ * @return {@code false} if we cannot allow a temporary access permission.
+ * @hide
+ */
+ public void exposeContent(@NonNull InputContentInfo inputContentInfo,
+ @NonNull InputConnection inputConnection) {
+ return;
+ }
+
}
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index cc71a9c24bfb..167d5a09a2dc 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -168,7 +168,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
int missingMethods = msg.arg1;
IInputContext inputContext = (IInputContext)args.arg1;
InputConnection ic = inputContext != null
- ? new InputConnectionWrapper(inputContext, missingMethods) : null;
+ ? new InputConnectionWrapper(mTarget, inputContext, missingMethods) : null;
EditorInfo info = (EditorInfo)args.arg2;
info.makeCompatible(mTargetSdkVersion);
inputMethod.startInput(ic, info);
@@ -180,7 +180,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
int missingMethods = msg.arg1;
IInputContext inputContext = (IInputContext)args.arg1;
InputConnection ic = inputContext != null
- ? new InputConnectionWrapper(inputContext, missingMethods) : null;
+ ? new InputConnectionWrapper(mTarget, inputContext, missingMethods) : null;
EditorInfo info = (EditorInfo)args.arg2;
info.makeCompatible(mTargetSdkVersion);
inputMethod.restartInput(ic, info);
@@ -251,7 +251,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
public void bindInput(InputBinding binding) {
// This IInputContext is guaranteed to implement all the methods.
final int missingMethodFlags = 0;
- InputConnection ic = new InputConnectionWrapper(
+ InputConnection ic = new InputConnectionWrapper(mTarget,
IInputContext.Stub.asInterface(binding.getConnectionToken()), missingMethodFlags);
InputBinding nu = new InputBinding(ic, binding);
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_INPUT_CONTEXT, nu));
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 4799773d9ed6..fede77d9bb1d 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -23,6 +23,7 @@ import android.annotation.CallSuper;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.MainThread;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.Dialog;
import android.content.Context;
@@ -65,6 +66,7 @@ import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputBinding;
import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
@@ -2598,6 +2600,29 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
+ * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
+ * permission to the content.
+ *
+ * @param inputContentInfo Content to be temporarily exposed from the input method to the
+ * application.
+ * This cannot be {@code null}.
+ * @param inputConnection {@link InputConnection} with which
+ * {@link InputConnection#commitContent(InputContentInfo, Bundle)} will be called.
+ * @hide
+ */
+ @Override
+ public final void exposeContent(@NonNull InputContentInfo inputContentInfo,
+ @NonNull InputConnection inputConnection) {
+ if (inputConnection == null) {
+ return;
+ }
+ if (getCurrentInputConnection() != inputConnection) {
+ return;
+ }
+ mImm.exposeContent(mToken, inputContentInfo, getCurrentInputEditorInfo());
+ }
+
+ /**
* Performs a dump of the InputMethodService's internal state. Override
* to add your own information to the dump.
*/
diff --git a/core/java/android/net/ConnectivityMetricsLogger.java b/core/java/android/net/ConnectivityMetricsLogger.java
index 73734958f512..029c5bdccd41 100644
--- a/core/java/android/net/ConnectivityMetricsLogger.java
+++ b/core/java/android/net/ConnectivityMetricsLogger.java
@@ -23,6 +23,8 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
/** {@hide} */
@SystemApi
public class ConnectivityMetricsLogger {
@@ -49,8 +51,14 @@ public class ConnectivityMetricsLogger {
private int mNumSkippedEvents;
public ConnectivityMetricsLogger() {
- mService = IConnectivityMetricsLogger.Stub.asInterface(ServiceManager.getService(
- CONNECTIVITY_METRICS_LOGGER_SERVICE));
+ this(IConnectivityMetricsLogger.Stub.asInterface(
+ ServiceManager.getService(CONNECTIVITY_METRICS_LOGGER_SERVICE)));
+ }
+
+ /** {@hide} */
+ @VisibleForTesting
+ public ConnectivityMetricsLogger(IConnectivityMetricsLogger service) {
+ mService = service;
}
/**
@@ -153,11 +161,10 @@ public class ConnectivityMetricsLogger {
public boolean unregister(PendingIntent newEventsIntent) {
try {
mService.unregister(newEventsIntent);
+ return true;
} catch (RemoteException e) {
Log.e(TAG, "IConnectivityMetricsLogger.unregister", e);
return false;
}
-
- return true;
}
}
diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java
index f8b59925cb91..b881fbb1dacc 100644
--- a/core/java/android/net/metrics/DefaultNetworkEvent.java
+++ b/core/java/android/net/metrics/DefaultNetworkEvent.java
@@ -25,7 +25,7 @@ import android.os.Parcelable;
* {@hide}
*/
@SystemApi
-public final class DefaultNetworkEvent extends IpConnectivityEvent implements Parcelable {
+public final class DefaultNetworkEvent implements Parcelable {
// The ID of the network that has become the new default or NETID_UNSET if none.
public final int netId;
// The list of transport types of the new default network, for example TRANSPORT_WIFI, as
@@ -37,7 +37,8 @@ public final class DefaultNetworkEvent extends IpConnectivityEvent implements Pa
public final boolean prevIPv4;
public final boolean prevIPv6;
- private DefaultNetworkEvent(int netId, int[] transportTypes,
+ /** {@hide} */
+ public DefaultNetworkEvent(int netId, int[] transportTypes,
int prevNetId, boolean prevIPv4, boolean prevIPv6) {
this.netId = netId;
this.transportTypes = transportTypes;
@@ -105,6 +106,5 @@ public final class DefaultNetworkEvent extends IpConnectivityEvent implements Pa
public static void logEvent(
int netId, int[] transports, int prevNetId, boolean hadIPv4, boolean hadIPv6) {
- logEvent(new DefaultNetworkEvent(netId, transports, prevNetId, hadIPv4, hadIPv6));
}
-};
+}
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index ec560bf64ccc..3fe68b40e9f4 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -24,11 +24,12 @@ import android.os.Parcelable;
* {@hide}
*/
@SystemApi
-public final class DhcpClientEvent extends IpConnectivityEvent implements Parcelable {
+public final class DhcpClientEvent implements Parcelable {
public final String ifName;
public final String msg;
- private DhcpClientEvent(String ifName, String msg) {
+ /** {@hide} */
+ public DhcpClientEvent(String ifName, String msg) {
this.ifName = ifName;
this.msg = msg;
}
@@ -64,6 +65,5 @@ public final class DhcpClientEvent extends IpConnectivityEvent implements Parcel
};
public static void logStateEvent(String ifName, String state) {
- logEvent(new DhcpClientEvent(ifName, state));
}
-};
+}
diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java
index 84795b89bb6b..4206886c6bd0 100644
--- a/core/java/android/net/metrics/DhcpErrorEvent.java
+++ b/core/java/android/net/metrics/DhcpErrorEvent.java
@@ -27,7 +27,7 @@ import com.android.internal.util.MessageUtils;
* {@hide} Event class used to record error events when parsing DHCP response packets.
*/
@SystemApi
-public final class DhcpErrorEvent extends IpConnectivityEvent implements Parcelable {
+public final class DhcpErrorEvent implements Parcelable {
public static final int L2_ERROR = 1;
public static final int L3_ERROR = 2;
public static final int L4_ERROR = 3;
@@ -61,7 +61,8 @@ public final class DhcpErrorEvent extends IpConnectivityEvent implements Parcela
// byte 3: optional code
public final int errorCode;
- private DhcpErrorEvent(String ifName, int errorCode) {
+ /** {@hide} */
+ public DhcpErrorEvent(String ifName, int errorCode) {
this.ifName = ifName;
this.errorCode = errorCode;
}
@@ -92,11 +93,9 @@ public final class DhcpErrorEvent extends IpConnectivityEvent implements Parcela
};
public static void logParseError(String ifName, int errorCode) {
- logEvent(new DhcpErrorEvent(ifName, errorCode));
}
public static void logReceiveError(String ifName) {
- logEvent(new DhcpErrorEvent(ifName, RECEIVE_ERROR));
}
public static int errorCodeWithOption(int errorCode, int option) {
diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java
index b94dda079cd8..9eb8bdb579d0 100644
--- a/core/java/android/net/metrics/DnsEvent.java
+++ b/core/java/android/net/metrics/DnsEvent.java
@@ -24,7 +24,7 @@ import android.os.Parcelable;
* {@hide}
*/
@SystemApi
-final public class DnsEvent extends IpConnectivityEvent implements Parcelable {
+final public class DnsEvent implements Parcelable {
public final int netId;
// The event type is currently only 1 or 2, so we store it as a byte.
@@ -37,7 +37,8 @@ final public class DnsEvent extends IpConnectivityEvent implements Parcelable {
// queries.
public final int[] latenciesMs;
- private DnsEvent(int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) {
+ /** {@hide} */
+ public DnsEvent(int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) {
this.netId = netId;
this.eventTypes = eventTypes;
this.returnCodes = returnCodes;
@@ -82,6 +83,5 @@ final public class DnsEvent extends IpConnectivityEvent implements Parcelable {
public static void logEvent(
int netId, byte[] eventTypes, byte[] returnCodes, int[] latenciesMs) {
- logEvent(new DnsEvent(netId, eventTypes, returnCodes, latenciesMs));
}
}
diff --git a/core/java/android/net/metrics/IpConnectivityEvent.java b/core/java/android/net/metrics/IpConnectivityEvent.java
deleted file mode 100644
index d3771dcb60af..000000000000
--- a/core/java/android/net/metrics/IpConnectivityEvent.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.metrics;
-
-import android.os.Parcelable;
-
-/** {@hide} */
-public abstract class IpConnectivityEvent {
- private static final IpConnectivityLog sMetricsLog = new IpConnectivityLog();
-
- static <T extends IpConnectivityEvent & Parcelable> void logEvent(T event) {
- sMetricsLog.log(System.currentTimeMillis(), event);
- }
-}
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index 233ff74a145b..a7c1d40e90de 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -18,28 +18,40 @@ package android.net.metrics;
import android.net.ConnectivityMetricsEvent;
import android.net.ConnectivityMetricsLogger;
+import android.net.IConnectivityMetricsLogger;
import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Specialization of the ConnectivityMetricsLogger class for recording IP connectivity events.
* {@hide}
*/
-class IpConnectivityLog extends ConnectivityMetricsLogger {
+public class IpConnectivityLog extends ConnectivityMetricsLogger {
private static String TAG = "IpConnectivityMetricsLogger";
private static final boolean DBG = false;
+ public IpConnectivityLog() {
+ // mService initialized in super constructor.
+ }
+
+ @VisibleForTesting
+ public IpConnectivityLog(IConnectivityMetricsLogger service) {
+ super(service);
+ }
+
/**
* Log an IpConnectivity event. Contrary to logEvent(), this method does not
* keep track of skipped events and is thread-safe for callers.
*
* @param timestamp is the epoch timestamp of the event in ms.
- * @param data is a Parcelable IpConnectivityEvent instance representing the event.
+ * @param data is a Parcelable instance representing the event.
*
* @return true if the event was successfully logged.
*/
- public <T extends IpConnectivityEvent & Parcelable> boolean log(long timestamp, T data) {
+ public boolean log(long timestamp, Parcelable data) {
if (mService == null) {
if (DBG) {
Log.d(TAG, CONNECTIVITY_METRICS_LOGGER_SERVICE + " service not ready");
@@ -67,4 +79,8 @@ class IpConnectivityLog extends ConnectivityMetricsLogger {
return false;
}
}
+
+ public void log(Parcelable event) {
+ log(System.currentTimeMillis(), event);
+ }
}
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index 0940bd06c3d3..a39061748ac3 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -27,7 +27,7 @@ import com.android.internal.util.MessageUtils;
* {@hide}
*/
@SystemApi
-public final class IpManagerEvent extends IpConnectivityEvent implements Parcelable {
+public final class IpManagerEvent implements Parcelable {
public static final int PROVISIONING_OK = 1;
public static final int PROVISIONING_FAIL = 2;
@@ -37,7 +37,8 @@ public final class IpManagerEvent extends IpConnectivityEvent implements Parcela
public final int eventType;
public final long durationMs;
- private IpManagerEvent(String ifName, int eventType, long duration) {
+ /** {@hide} */
+ public IpManagerEvent(String ifName, int eventType, long duration) {
this.ifName = ifName;
this.eventType = eventType;
this.durationMs = duration;
@@ -71,7 +72,6 @@ public final class IpManagerEvent extends IpConnectivityEvent implements Parcela
};
public static void logEvent(int eventType, String ifName, long durationMs) {
- logEvent(new IpManagerEvent(ifName, eventType, durationMs));
}
@Override
@@ -84,4 +84,4 @@ public final class IpManagerEvent extends IpConnectivityEvent implements Parcela
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{IpManagerEvent.class}, new String[]{"PROVISIONING_", "COMPLETE_"});
}
-};
+}
diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java
index d40389c03986..7d0229191563 100644
--- a/core/java/android/net/metrics/IpReachabilityEvent.java
+++ b/core/java/android/net/metrics/IpReachabilityEvent.java
@@ -27,7 +27,7 @@ import com.android.internal.util.MessageUtils;
* {@hide}
*/
@SystemApi
-public final class IpReachabilityEvent extends IpConnectivityEvent implements Parcelable {
+public final class IpReachabilityEvent implements Parcelable {
public static final int PROBE = 1 << 8;
public static final int NUD_FAILED = 2 << 8;
@@ -41,7 +41,8 @@ public final class IpReachabilityEvent extends IpConnectivityEvent implements Pa
// byte 3: kernel errno from RTNetlink or IpReachabilityMonitor
public final int eventType;
- private IpReachabilityEvent(String ifName, int eventType) {
+ /** {@hide} */
+ public IpReachabilityEvent(String ifName, int eventType) {
this.ifName = ifName;
this.eventType = eventType;
}
@@ -72,15 +73,12 @@ public final class IpReachabilityEvent extends IpConnectivityEvent implements Pa
};
public static void logProbeEvent(String ifName, int nlErrorCode) {
- logEvent(new IpReachabilityEvent(ifName, PROBE | (nlErrorCode & 0xFF)));
}
public static void logNudFailed(String ifName) {
- logEvent(new IpReachabilityEvent(ifName, NUD_FAILED));
}
public static void logProvisioningLost(String ifName) {
- logEvent(new IpReachabilityEvent(ifName, PROVISIONING_LOST));
}
@Override
@@ -94,4 +92,4 @@ public final class IpReachabilityEvent extends IpConnectivityEvent implements Pa
MessageUtils.findMessageNames(new Class[]{IpReachabilityEvent.class},
new String[]{"PROBE", "PROVISIONING_", "NUD_"});
}
-};
+}
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index 08c9c758bbc8..cdfe386d430c 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -27,7 +27,7 @@ import com.android.internal.util.MessageUtils;
* {@hide}
*/
@SystemApi
-public final class NetworkEvent extends IpConnectivityEvent implements Parcelable {
+public final class NetworkEvent implements Parcelable {
public static final int NETWORK_CONNECTED = 1;
public static final int NETWORK_VALIDATED = 2;
@@ -41,12 +41,18 @@ public final class NetworkEvent extends IpConnectivityEvent implements Parcelabl
public final int eventType;
public final long durationMs;
- private NetworkEvent(int netId, int eventType, long durationMs) {
+ /** {@hide} */
+ public NetworkEvent(int netId, int eventType, long durationMs) {
this.netId = netId;
this.eventType = eventType;
this.durationMs = durationMs;
}
+ /** {@hide} */
+ public NetworkEvent(int netId, int eventType) {
+ this(netId, eventType, 0);
+ }
+
private NetworkEvent(Parcel in) {
netId = in.readInt();
eventType = in.readInt();
@@ -75,15 +81,12 @@ public final class NetworkEvent extends IpConnectivityEvent implements Parcelabl
};
public static void logEvent(int netId, int eventType) {
- logEvent(new NetworkEvent(netId, eventType, 0));
}
public static void logValidated(int netId, long durationMs) {
- logEvent(new NetworkEvent(netId, NETWORK_VALIDATED, durationMs));
}
public static void logCaptivePortalFound(int netId, long durationMs) {
- logEvent(new NetworkEvent(netId, NETWORK_CAPTIVE_PORTAL_FOUND, durationMs));
}
@Override
@@ -96,4 +99,4 @@ public final class NetworkEvent extends IpConnectivityEvent implements Parcelabl
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{NetworkEvent.class}, new String[]{"NETWORK_"});
}
-};
+}
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 751c35f8a144..d5ad0f6c25a9 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -27,7 +27,7 @@ import com.android.internal.util.MessageUtils;
* {@hide}
*/
@SystemApi
-public final class ValidationProbeEvent extends IpConnectivityEvent implements Parcelable {
+public final class ValidationProbeEvent implements Parcelable {
public static final int PROBE_DNS = 0;
public static final int PROBE_HTTP = 1;
@@ -42,7 +42,8 @@ public final class ValidationProbeEvent extends IpConnectivityEvent implements P
public final int probeType;
public final int returnCode;
- private ValidationProbeEvent(int netId, long durationMs, int probeType, int returnCode) {
+ /** @hide */
+ public ValidationProbeEvent(int netId, long durationMs, int probeType, int returnCode) {
this.netId = netId;
this.durationMs = durationMs;
this.probeType = probeType;
@@ -84,7 +85,6 @@ public final class ValidationProbeEvent extends IpConnectivityEvent implements P
}
public static void logEvent(int netId, long durationMs, int probeType, int returnCode) {
- logEvent(new ValidationProbeEvent(netId, durationMs, probeType, returnCode));
}
@Override
@@ -97,4 +97,4 @@ public final class ValidationProbeEvent extends IpConnectivityEvent implements P
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{ValidationProbeEvent.class}, new String[]{"PROBE_"});
}
-};
+}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index f4bf3eab169e..4acb729b6a76 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2385,6 +2385,13 @@ public abstract class BatteryStats implements Parcelable {
public abstract LongCounter getDischargeCoulombCounter();
/**
+ * Returns the estimated real battery capacity, which may be less than the capacity
+ * declared by the PowerProfile.
+ * @return The estimated battery capacity in mAh.
+ */
+ public abstract int getEstimatedBatteryCapacity();
+
+ /**
* Return the array of discharge step durations.
*/
public abstract LevelStepTracker getDischargeLevelStepTracker();
@@ -2836,7 +2843,8 @@ public abstract class BatteryStats implements Parcelable {
whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
totalRealtime / 1000, totalUptime / 1000,
getStartClockTime(),
- whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000);
+ whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000,
+ getEstimatedBatteryCapacity());
// Calculate wakelock times across all uids.
@@ -3348,6 +3356,16 @@ public abstract class BatteryStats implements Parcelable {
final SparseArray<? extends Uid> uidStats = getUidStats();
final int NU = uidStats.size();
+ final int estimatedBatteryCapacity = getEstimatedBatteryCapacity();
+ if (estimatedBatteryCapacity > 0) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Estimated battery capacity: ");
+ sb.append(BatteryStatsHelper.makemAh(estimatedBatteryCapacity));
+ sb.append(" mAh");
+ pw.println(sb.toString());
+ }
+
sb.setLength(0);
sb.append(prefix);
sb.append(" Time on battery: ");
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index b27cb32bd4eb..eeb641d33c20 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -81,4 +81,5 @@ interface IUserManager {
void clearSeedAccountData();
boolean someUserHasSeedAccount(in String accountName, in String accountType);
boolean isManagedProfile(int userId);
+ boolean isDemoUser(int userId);
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 26312475297c..74dcc0787b3b 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -17,8 +17,10 @@
package android.os;
import android.annotation.IntegerRes;
+import android.annotation.Nullable;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.Size;
import android.util.SizeF;
@@ -734,6 +736,21 @@ public final class Parcel {
}
/**
+ * Write an array set to the parcel.
+ *
+ * @param val The array set to write.
+ *
+ * @hide
+ */
+ public void writeArraySet(@Nullable ArraySet<? extends Object> val) {
+ final int size = (val != null) ? val.size() : -1;
+ writeInt(size);
+ for (int i = 0; i < size; i++) {
+ writeValue(val.valueAt(i));
+ }
+ }
+
+ /**
* Flatten a Bundle into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
@@ -2735,6 +2752,26 @@ public final class Parcel {
readArrayMapInternal(outVal, N, loader);
}
+ /**
+ * Reads an array set.
+ *
+ * @param loader The class loader to use.
+ *
+ * @hide
+ */
+ public @Nullable ArraySet<? extends Object> readArraySet(ClassLoader loader) {
+ final int size = readInt();
+ if (size < 0) {
+ return null;
+ }
+ ArraySet<Object> result = new ArraySet<>(size);
+ for (int i = 0; i < size; i++) {
+ Object value = readValue(loader);
+ result.append(value);
+ }
+ return result;
+ }
+
private void readListInternal(List outVal, int N,
ClassLoader loader) {
while (N > 0) {
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 4506f51fe38a..f664e70cf7be 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1184,6 +1184,8 @@ public class Process {
/** @hide */
public static final int PROC_QUOTES = 0x400;
/** @hide */
+ public static final int PROC_CHAR = 0x800;
+ /** @hide */
public static final int PROC_OUT_STRING = 0x1000;
/** @hide */
public static final int PROC_OUT_LONG = 0x2000;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d74220676ca2..a44a9eed701b 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -859,15 +859,17 @@ public class UserManager {
}
/**
- * Checks if the calling app is running in a demo user.
- * <p>
- * Caller must hold the MANAGE_USERS permission.
+ * Checks if the calling app is running in a demo user. When running in a demo user,
+ * apps can be more helpful to the user, or explain their features in more detail.
+ *
* @return whether the caller is a demo user.
- * @hide
*/
public boolean isDemoUser() {
- UserInfo user = getUserInfo(UserHandle.myUserId());
- return user != null && user.isDemo();
+ try {
+ return mService.isDemoUser(UserHandle.myUserId());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
}
/**
diff --git a/core/java/android/print/PrintServiceRecommendationsLoader.java b/core/java/android/print/PrintServiceRecommendationsLoader.java
index bb5d065c6430..c6a4d5103a47 100644
--- a/core/java/android/print/PrintServiceRecommendationsLoader.java
+++ b/core/java/android/print/PrintServiceRecommendationsLoader.java
@@ -36,7 +36,7 @@ public class PrintServiceRecommendationsLoader extends Loader<List<Recommendatio
private final @NonNull PrintManager mPrintManager;
/** Handler to sequentialize the delivery of the results to the main thread */
- private final Handler mHandler;
+ private final @NonNull Handler mHandler;
/** Listens for updates to the data from the platform */
private PrintManager.PrintServiceRecommendationsChangeListener mListener;
@@ -90,9 +90,7 @@ public class PrintServiceRecommendationsLoader extends Loader<List<Recommendatio
mListener = null;
}
- if (mHandler != null) {
- mHandler.removeMessages(0);
- }
+ mHandler.removeMessages(0);
}
@Override
diff --git a/core/java/android/print/PrintServicesLoader.java b/core/java/android/print/PrintServicesLoader.java
index 60d7d666c2c9..4c9a69ab5e97 100644
--- a/core/java/android/print/PrintServicesLoader.java
+++ b/core/java/android/print/PrintServicesLoader.java
@@ -39,7 +39,7 @@ public class PrintServicesLoader extends Loader<List<PrintServiceInfo>> {
private final @NonNull PrintManager mPrintManager;
/** Handler to sequentialize the delivery of the results to the main thread */
- private Handler mHandler;
+ private final @NonNull Handler mHandler;
/** Listens for updates to the data from the platform */
private PrintManager.PrintServicesChangeListener mListener;
@@ -54,6 +54,7 @@ public class PrintServicesLoader extends Loader<List<PrintServiceInfo>> {
public PrintServicesLoader(@NonNull PrintManager printManager, @NonNull Context context,
int selectionFlags) {
super(Preconditions.checkNotNull(context));
+ mHandler = new MyHandler();
mPrintManager = Preconditions.checkNotNull(printManager);
mSelectionFlags = Preconditions.checkFlagsArgument(selectionFlags,
PrintManager.ALL_SERVICES);
@@ -75,7 +76,6 @@ public class PrintServicesLoader extends Loader<List<PrintServiceInfo>> {
@Override
protected void onStartLoading() {
- mHandler = new MyHandler();
mListener = new PrintManager.PrintServicesChangeListener() {
@Override public void onPrintServicesChanged() {
queueNewResult();
@@ -95,10 +95,7 @@ public class PrintServicesLoader extends Loader<List<PrintServiceInfo>> {
mListener = null;
}
- if (mHandler != null) {
- mHandler.removeMessages(0);
- mHandler = null;
- }
+ mHandler.removeMessages(0);
}
@Override
@@ -119,8 +116,6 @@ public class PrintServicesLoader extends Loader<List<PrintServiceInfo>> {
@Override
public void handleMessage(Message msg) {
- super.handleMessage(msg);
-
if (isStarted()) {
deliverResult((List<PrintServiceInfo>) msg.obj);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 88cf138eb123..e51df0f1da94 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1322,13 +1322,20 @@ public final class Settings {
/**
* @hide Key with the location in the {@link android.util.MemoryIntArray} where
- * to look up the generation id of the backing table.
+ * to look up the generation id of the backing table. The value is an integer.
*
* @see #CALL_METHOD_TRACK_GENERATION_KEY
*/
public static final String CALL_METHOD_GENERATION_INDEX_KEY = "_generation_index";
/**
+ * @hide Key with the settings table generation. The value is an integer.
+ *
+ * @see #CALL_METHOD_TRACK_GENERATION_KEY
+ */
+ public static final String CALL_METHOD_GENERATION_KEY = "_generation";
+
+ /**
* @hide - User handle argument extra to the fast-path call()-based requests
*/
public static final String CALL_METHOD_USER_KEY = "_user";
@@ -1478,11 +1485,11 @@ public final class Settings {
private int mCurrentGeneration;
public GenerationTracker(@NonNull MemoryIntArray array, int index,
- Runnable errorHandler) {
+ int generation, Runnable errorHandler) {
mArray = array;
mIndex = index;
mErrorHandler = errorHandler;
- mCurrentGeneration = readCurrentGeneration();
+ mCurrentGeneration = generation;
}
public boolean isGenerationChanged() {
@@ -1638,6 +1645,8 @@ public final class Settings {
final int index = b.getInt(
CALL_METHOD_GENERATION_INDEX_KEY, -1);
if (array != null && index >= 0) {
+ final int generation = b.getInt(
+ CALL_METHOD_GENERATION_KEY, 0);
if (DEBUG) {
Log.i(TAG, "Received generation tracker for type:"
+ mUri.getPath() + " in package:"
@@ -1645,7 +1654,7 @@ public final class Settings {
+ userHandle + " with index:" + index);
}
mGenerationTracker = new GenerationTracker(array, index,
- () -> {
+ generation, () -> {
synchronized (this) {
Log.e(TAG, "Error accessing generation"
+ " tracker - removing");
@@ -8498,8 +8507,6 @@ public final class Settings {
/**
* The name of the device
- *
- * @hide
*/
public static final String DEVICE_NAME = "device_name";
@@ -9065,6 +9072,12 @@ public final class Settings {
*/
public static final String SYSTEM_NAVIGATION_KEYS_ENABLED =
"system_navigation_keys_enabled";
+
+ /**
+ * Whether cell is enabled/disabled
+ * @hide
+ */
+ public static final String CELL_ON = "cell_on";
}
/**
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index ab9e4971570a..27b0a8baf62b 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -153,6 +153,13 @@ public class VoicemailContract {
public static final String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
/**
+ * Extra included in {@link #ACTION_SYNC_VOICEMAIL} broadcast intents to indicate which {@link
+ * PhoneAccountHandle} to sync.
+ */
+ public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
+ "android.provider.extra.PHONE_ACCOUNT_HANDLE";
+
+ /**
* Name of the source package field, which must be same across all voicemail related tables.
* This is an internal field.
* @hide
@@ -454,6 +461,9 @@ public class VoicemailContract {
* {@link #CONFIGURATION_STATE_OK},
* {@link #CONFIGURATION_STATE_NOT_CONFIGURED},
* {@link #CONFIGURATION_STATE_CAN_BE_CONFIGURED}
+ * {@link #CONFIGURATION_STATE_CONFIGURING}
+ * {@link #CONFIGURATION_STATE_FAILED}
+ * {@link #CONFIGURATION_STATE_DISABLED}
* <P>Type: INTEGER</P>
*/
public static final String CONFIGURATION_STATE = "configuration_state";
@@ -473,6 +483,21 @@ public class VoicemailContract {
*/
public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2;
/**
+ * Value of {@link #CONFIGURATION_STATE} to indicate that visual voicemail still is being
+ * configured.
+ */
+ public static final int CONFIGURATION_STATE_CONFIGURING = 3;
+ /**
+ * Value of {@link #CONFIGURATION_STATE} to indicate that visual voicemail has failed to
+ * be configured.
+ */
+ public static final int CONFIGURATION_STATE_FAILED = 4;
+ /**
+ * Value of {@link #CONFIGURATION_STATE} to indicate that visual voicemail is disabled by
+ * the user.
+ */
+ public static final int CONFIGURATION_STATE_DISABLED = 5;
+ /**
* The data channel state of the voicemail source. This the channel through which the source
* pulls voicemail data from a remote server.
*
diff --git a/core/java/android/security/NetworkSecurityPolicy.java b/core/java/android/security/NetworkSecurityPolicy.java
index 331063e2bfac..1b1c30048ee7 100644
--- a/core/java/android/security/NetworkSecurityPolicy.java
+++ b/core/java/android/security/NetworkSecurityPolicy.java
@@ -17,7 +17,10 @@
package android.security;
import android.annotation.TestApi;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.security.net.config.ApplicationConfig;
+import android.security.net.config.ManifestConfigSource;
/**
* Network security policy.
@@ -98,4 +101,16 @@ public class NetworkSecurityPolicy {
public void handleTrustStorageUpdate() {
ApplicationConfig.getDefaultInstance().handleTrustStorageUpdate();
}
+
+ /**
+ * Returns an {@link ApplicationConfig} based on the configuration for {@code packageName}.
+ *
+ * @hide
+ */
+ public static ApplicationConfig getApplicationConfigForPackage(Context context,
+ String packageName) throws PackageManager.NameNotFoundException {
+ Context appContext = context.createPackageContext(packageName, 0);
+ ManifestConfigSource source = new ManifestConfigSource(appContext);
+ return new ApplicationConfig(source);
+ }
}
diff --git a/core/java/android/service/quicksettings/IQSService.aidl b/core/java/android/service/quicksettings/IQSService.aidl
index 747f18531d3b..bf963570b040 100644
--- a/core/java/android/service/quicksettings/IQSService.aidl
+++ b/core/java/android/service/quicksettings/IQSService.aidl
@@ -23,6 +23,7 @@ import android.service.quicksettings.Tile;
* @hide
*/
interface IQSService {
+ Tile getTile(in ComponentName component);
void updateQsTile(in Tile tile);
void updateStatusIcon(in Tile tile, in Icon icon,
String contentDescription);
diff --git a/core/java/android/service/quicksettings/IQSTileService.aidl b/core/java/android/service/quicksettings/IQSTileService.aidl
index bfde8702338a..b6c830cf9840 100644
--- a/core/java/android/service/quicksettings/IQSTileService.aidl
+++ b/core/java/android/service/quicksettings/IQSTileService.aidl
@@ -15,15 +15,10 @@
*/
package android.service.quicksettings;
-import android.service.quicksettings.Tile;
-import android.service.quicksettings.IQSService;
-
/**
* @hide
*/
oneway interface IQSTileService {
- void setQSService(in IQSService service);
- void setQSTile(in Tile tile);
void onTileAdded();
void onTileRemoved();
void onStartListening();
diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java
index 4e9a0751f2e3..50411ab7d15e 100644
--- a/core/java/android/service/quicksettings/TileService.java
+++ b/core/java/android/service/quicksettings/TileService.java
@@ -118,6 +118,11 @@ public class TileService extends Service {
/**
* @hide
*/
+ public static final String EXTRA_SERVICE = "service";
+
+ /**
+ * @hide
+ */
public static final String EXTRA_COMPONENT = "android.service.quicksettings.extra.COMPONENT";
private final H mHandler = new H(Looper.getMainLooper());
@@ -305,18 +310,19 @@ public class TileService extends Service {
@Override
public IBinder onBind(Intent intent) {
+ mService = IQSService.Stub.asInterface(intent.getIBinderExtra(EXTRA_SERVICE));
+ try {
+ ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT);
+ mTile = mService.getTile(component);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Unable to reach IQSService", e);
+ }
+ if (mTile != null) {
+ mTile.setService(mService);
+ mHandler.sendEmptyMessage(H.MSG_START_SUCCESS);
+ }
return new IQSTileService.Stub() {
@Override
- public void setQSService(IQSService service) throws RemoteException {
- mHandler.obtainMessage(H.MSG_SET_SERVICE, service).sendToTarget();
- }
-
- @Override
- public void setQSTile(Tile tile) throws RemoteException {
- mHandler.obtainMessage(H.MSG_SET_TILE, tile).sendToTarget();
- }
-
- @Override
public void onTileRemoved() throws RemoteException {
mHandler.sendEmptyMessage(H.MSG_TILE_REMOVED);
}
@@ -349,14 +355,13 @@ public class TileService extends Service {
}
private class H extends Handler {
- private static final int MSG_SET_TILE = 1;
- private static final int MSG_START_LISTENING = 2;
- private static final int MSG_STOP_LISTENING = 3;
- private static final int MSG_TILE_ADDED = 4;
- private static final int MSG_TILE_REMOVED = 5;
- private static final int MSG_TILE_CLICKED = 6;
- private static final int MSG_SET_SERVICE = 7;
- private static final int MSG_UNLOCK_COMPLETE = 8;
+ private static final int MSG_START_LISTENING = 1;
+ private static final int MSG_STOP_LISTENING = 2;
+ private static final int MSG_TILE_ADDED = 3;
+ private static final int MSG_TILE_REMOVED = 4;
+ private static final int MSG_TILE_CLICKED = 5;
+ private static final int MSG_UNLOCK_COMPLETE = 6;
+ private static final int MSG_START_SUCCESS = 7;
public H(Looper looper) {
super(looper);
@@ -365,18 +370,6 @@ public class TileService extends Service {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_SET_SERVICE:
- mService = (IQSService) msg.obj;
- if (mTile != null) {
- mTile.setService(mService);
- }
- break;
- case MSG_SET_TILE:
- mTile = (Tile) msg.obj;
- if (mService != null && mTile != null) {
- mTile.setService(mService);
- }
- break;
case MSG_TILE_ADDED:
TileService.this.onTileAdded();
break;
@@ -408,6 +401,12 @@ public class TileService extends Service {
mUnlockRunnable.run();
}
break;
+ case MSG_START_SUCCESS:
+ try {
+ mService.onStartSuccessful(mTile);
+ } catch (RemoteException e) {
+ }
+ break;
}
}
}
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index 9e9314fba4c4..d39e91fd98b2 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -390,6 +390,32 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
}
/**
+ * Special fast path for appending items to the end of the array without validation.
+ * The array must already be large enough to contain the item.
+ * @hide
+ */
+ public void append(E value) {
+ final int index = mSize;
+ final int hash = value == null ? 0
+ : (mIdentityHashCode ? System.identityHashCode(value) : value.hashCode());
+ if (index >= mHashes.length) {
+ throw new IllegalStateException("Array is full");
+ }
+ if (index > 0 && mHashes[index - 1] > hash) {
+ RuntimeException e = new RuntimeException("here");
+ e.fillInStackTrace();
+ Log.w(TAG, "New hash " + hash
+ + " is before end of array hash " + mHashes[index - 1]
+ + " at index " + index, e);
+ add(value);
+ return;
+ }
+ mSize = index + 1;
+ mHashes[index] = hash;
+ mArray[index] = value;
+ }
+
+ /**
* Perform a {@link #add(Object)} of all values in <var>array</var>
* @param array The array whose contents are to be retrieved.
*/
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index a865307b12bb..d3db74d1ea24 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -232,6 +232,19 @@ public final class Choreographer {
return sThreadInstance.get();
}
+ /** Destroys the calling thread's choreographer
+ * @hide
+ */
+ public static void releaseInstance() {
+ Choreographer old = sThreadInstance.get();
+ sThreadInstance.remove();
+ old.dispose();
+ }
+
+ private void dispose() {
+ mDisplayEventReceiver.dispose();
+ }
+
/**
* The amount of time, in milliseconds, between each frame of the animation.
* <p>
diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java
index 272740fb6c01..dd86062f2d1d 100644
--- a/core/java/android/view/DisplayAdjustments.java
+++ b/core/java/android/view/DisplayAdjustments.java
@@ -23,8 +23,6 @@ import java.util.Objects;
/** @hide */
public class DisplayAdjustments {
- public static final boolean DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN = false;
-
public static final DisplayAdjustments DEFAULT_DISPLAY_ADJUSTMENTS = new DisplayAdjustments();
private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
@@ -64,7 +62,7 @@ public class DisplayAdjustments {
throw new IllegalArgumentException(
"setConfiguration: Cannot modify DEFAULT_DISPLAY_ADJUSTMENTS");
}
- mConfiguration = configuration;
+ mConfiguration = configuration != null ? configuration : Configuration.EMPTY;
}
public Configuration getConfiguration() {
@@ -74,10 +72,8 @@ public class DisplayAdjustments {
@Override
public int hashCode() {
int hash = 17;
- hash = hash * 31 + mCompatInfo.hashCode();
- if (DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN) {
- hash = hash * 31 + (mConfiguration == null ? 0 : mConfiguration.hashCode());
- }
+ hash = hash * 31 + Objects.hashCode(mCompatInfo);
+ hash = hash * 31 + Objects.hashCode(mConfiguration);
return hash;
}
diff --git a/core/java/android/view/DragAndDropPermissions.java b/core/java/android/view/DragAndDropPermissions.java
index a3dbdb16197d..71afaaa5b458 100644
--- a/core/java/android/view/DragAndDropPermissions.java
+++ b/core/java/android/view/DragAndDropPermissions.java
@@ -16,12 +16,14 @@
package android.view;
+import android.app.Activity;
import android.app.ActivityManagerNative;
import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
-import com.android.internal.view.IDragAndDropPermissions;
-import dalvik.system.CloseGuard;
+import com.android.internal.view.IDragAndDropPermissions;
/**
* {@link DragAndDropPermissions} controls the access permissions for the content URIs associated
@@ -33,20 +35,27 @@ import dalvik.system.CloseGuard;
* Which permissions are granted is defined by the set of flags passed to {@link
* View#startDragAndDrop(android.content.ClipData, View.DragShadowBuilder, Object, int)
* View.startDragAndDrop} by the app that started the drag operation.
+ * </p>
* <p>
* The life cycle of the permissions is bound to the activity used to call {@link
* android.app.Activity#requestDragAndDropPermissions(DragEvent) requestDragAndDropPermissions}. The
* permissions are revoked when this activity is destroyed, or when {@link #release()} is called,
* whichever occurs first.
+ * </p>
+ * <p>
+ * If you anticipate that your application will receive a large number of drops (e.g. document
+ * editor), you should try to call {@link #release()} on the obtained permissions as soon as they
+ * are no longer required. Permissions can be added to your activity's
+ * {@link Activity#onSaveInstanceState} bundle and later retrieved in order to manually release
+ * the permissions once they are no longer needed.
+ * </p>
*/
-public final class DragAndDropPermissions {
+public final class DragAndDropPermissions implements Parcelable {
private final IDragAndDropPermissions mDragAndDropPermissions;
private IBinder mPermissionOwnerToken;
- private final CloseGuard mCloseGuard = CloseGuard.get();
-
/**
* Create a new {@link DragAndDropPermissions} object to control the access permissions for
* content URIs associated with {@link DragEvent}.
@@ -79,7 +88,6 @@ public final class DragAndDropPermissions {
} catch (RemoteException e) {
return false;
}
- mCloseGuard.open("release");
return true;
}
@@ -96,7 +104,6 @@ public final class DragAndDropPermissions {
} catch (RemoteException e) {
return false;
}
- mCloseGuard.open("release");
return true;
}
@@ -109,18 +116,34 @@ public final class DragAndDropPermissions {
mPermissionOwnerToken = null;
} catch (RemoteException e) {
}
- mCloseGuard.close();
}
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mCloseGuard != null) {
- mCloseGuard.warnIfOpen();
- }
- release();
- } finally {
- super.finalize();
+ public static final Parcelable.Creator<DragAndDropPermissions> CREATOR =
+ new Parcelable.Creator<DragAndDropPermissions> () {
+ @Override
+ public DragAndDropPermissions createFromParcel(Parcel source) {
+ return new DragAndDropPermissions(source);
+ }
+
+ @Override
+ public DragAndDropPermissions[] newArray(int size) {
+ return new DragAndDropPermissions[size];
}
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel destination, int flags) {
+ destination.writeStrongInterface(mDragAndDropPermissions);
+ destination.writeStrongBinder(mPermissionOwnerToken);
+ }
+
+ private DragAndDropPermissions(Parcel in) {
+ mDragAndDropPermissions = IDragAndDropPermissions.Stub.asInterface(in.readStrongBinder());
+ mPermissionOwnerToken = in.readStrongBinder();
}
}
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 599c9c72237e..990d55374a64 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -796,16 +796,16 @@ public class KeyEvent extends InputEvent implements Parcelable {
public static final int KEYCODE_COPY = 278;
/** Key code constant: Paste key. */
public static final int KEYCODE_PASTE = 279;
- /** Key code constant: fingerprint navigation up */
- public static final int KEYCODE_FP_NAV_UP = 280;
- /** Key code constant: fingerprint navigation down */
- public static final int KEYCODE_FP_NAV_DOWN = 281;
- /** Key code constant: fingerprint navigation left*/
- public static final int KEYCODE_FP_NAV_LEFT = 282;
- /** Key code constant: fingerprint navigation right */
- public static final int KEYCODE_FP_NAV_RIGHT = 283;
+ /** Key code constant: Consumed by the system for navigation up */
+ public static final int KEYCODE_SYSTEM_NAVIGATION_UP = 280;
+ /** Key code constant: Consumed by the system for navigation down */
+ public static final int KEYCODE_SYSTEM_NAVIGATION_DOWN = 281;
+ /** Key code constant: Consumed by the system for navigation left*/
+ public static final int KEYCODE_SYSTEM_NAVIGATION_LEFT = 282;
+ /** Key code constant: Consumed by the system for navigation right */
+ public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283;
- private static final int LAST_KEYCODE = KEYCODE_FP_NAV_RIGHT;
+ private static final int LAST_KEYCODE = KEYCODE_SYSTEM_NAVIGATION_RIGHT;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
@@ -1852,10 +1852,10 @@ public class KeyEvent extends InputEvent implements Parcelable {
case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:
case KeyEvent.KEYCODE_BRIGHTNESS_UP:
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
- case KeyEvent.KEYCODE_FP_NAV_UP:
- case KeyEvent.KEYCODE_FP_NAV_DOWN:
- case KeyEvent.KEYCODE_FP_NAV_LEFT:
- case KeyEvent.KEYCODE_FP_NAV_RIGHT:
+ case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
+ case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
+ case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
+ case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT:
return true;
}
@@ -2941,11 +2941,13 @@ public class KeyEvent extends InputEvent implements Parcelable {
public static final Parcelable.Creator<KeyEvent> CREATOR
= new Parcelable.Creator<KeyEvent>() {
+ @Override
public KeyEvent createFromParcel(Parcel in) {
in.readInt(); // skip token, we already know this is a KeyEvent
return KeyEvent.createFromParcelBody(in);
}
+ @Override
public KeyEvent[] newArray(int size) {
return new KeyEvent[size];
}
@@ -2969,6 +2971,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
mEventTime = in.readLong();
}
+ @Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(PARCEL_TOKEN_KEY_EVENT);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 7da849a832e4..286e0979d12b 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -58,6 +58,7 @@ public class Surface implements Parcelable {
private static native long nativeGetNextFrameNumber(long nativeObject);
private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
+ private static native void nativeSetBuffersTransform(long nativeObject, long transform);
public static final Parcelable.Creator<Surface> CREATOR =
new Parcelable.Creator<Surface>() {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 415e70ca03fd..f1abca8e2a0d 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -51,7 +51,7 @@ public class SurfaceControl {
private static native void nativeSetLayer(long nativeObject, int zorder);
private static native void nativeSetPosition(long nativeObject, float x, float y);
- private static native void nativeSetPositionAppliesWithResize(long nativeObject);
+ private static native void nativeSetGeometryAppliesWithResize(long nativeObject);
private static native void nativeSetSize(long nativeObject, int w, int h);
private static native void nativeSetTransparentRegionHint(long nativeObject, Region region);
private static native void nativeSetAlpha(long nativeObject, float alpha);
@@ -89,6 +89,8 @@ public class SurfaceControl {
private static native void nativeSetOverrideScalingMode(long nativeObject,
int scalingMode);
private static native IBinder nativeGetHandle(long nativeObject);
+ private static native boolean nativeGetTransformToDisplayInverse(long nativeObject);
+
private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
@@ -393,6 +395,10 @@ public class SurfaceControl {
return nativeGetHandle(mNativeObject);
}
+ public boolean getTransformToDisplayInverse() {
+ return nativeGetTransformToDisplayInverse(mNativeObject);
+ }
+
/** flag the transaction as an animation */
public static void setAnimationTransaction() {
nativeSetAnimationTransaction();
@@ -409,13 +415,15 @@ public class SurfaceControl {
}
/**
- * If the size changes in this transaction, position updates specified
+ * If the buffer size changes in this transaction, position and crop updates specified
* in this transaction will not complete until a buffer of the new size
- * arrives.
+ * arrives. As transform matrix and size are already frozen in this fashion,
+ * this enables totally freezing the surface until the resize has completed
+ * (at which point the geometry influencing aspects of this transaction will then occur)
*/
- public void setPositionAppliesWithResize() {
+ public void setGeometryAppliesWithResize() {
checkNotReleased();
- nativeSetPositionAppliesWithResize(mNativeObject);
+ nativeSetGeometryAppliesWithResize(mNativeObject);
}
public void setSize(int w, int h) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 17834fb601c4..48189106f2c4 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -124,6 +124,7 @@ public class SurfaceView extends View {
int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
boolean mIsCreating = false;
+ private volatile boolean mRtHandlingPositionUpdates = false;
final Handler mHandler = new Handler() {
@Override
@@ -498,7 +499,7 @@ public class SurfaceView extends View {
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
;
- if (!creating && !force && !mUpdateWindowNeeded && !sizeChanged) {
+ if (!creating && !force && !sizeChanged) {
mLayout.privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY;
} else {
@@ -649,7 +650,9 @@ public class SurfaceView extends View {
TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
" w=" + mLayout.width + " h=" + mLayout.height +
", frame=" + mSurfaceFrame);
- } else if (!isHardwareAccelerated()) {
+ } else {
+ // Calculate the window position in case RT loses the window
+ // and we need to fallback to a UI-thread driven position update
getLocationInWindow(mLocation);
final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
|| mWindowSpaceTop != mLocation[1];
@@ -670,15 +673,17 @@ public class SurfaceView extends View {
mTranslator.translateRectInAppWindowToScreen(mWinFrame);
}
- try {
- Log.d(TAG, String.format("%d updateWindowPosition UI, " +
- "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
- mWinFrame.left, mWinFrame.top,
- mWinFrame.right, mWinFrame.bottom));
- mSession.repositionChild(mWindow, mWinFrame.left, mWinFrame.top,
- mWinFrame.right, mWinFrame.bottom, -1, mWinFrame);
- } catch (RemoteException ex) {
- Log.e(TAG, "Exception from relayout", ex);
+ if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) {
+ try {
+ if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition UI, " +
+ "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
+ mWinFrame.left, mWinFrame.top,
+ mWinFrame.right, mWinFrame.bottom));
+ mSession.repositionChild(mWindow, mWinFrame.left, mWinFrame.top,
+ mWinFrame.right, mWinFrame.bottom, -1, mWinFrame);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Exception from relayout", ex);
+ }
}
}
}
@@ -698,6 +703,15 @@ public class SurfaceView extends View {
// Guess we got detached, that sucks
return;
}
+ // TODO: This is teensy bit racey in that a brand new SurfaceView moving on
+ // its 2nd frame if RenderThread is running slowly could potentially see
+ // this as false, enter the branch, get pre-empted, then this comes along
+ // and reports a new position, then the UI thread resumes and reports
+ // its position. This could therefore be de-sync'd in that interval, but
+ // the synchronization would violate the rule that RT must never block
+ // on the UI thread which would open up potential deadlocks. The risk of
+ // a single-frame desync is therefore preferable for now.
+ mRtHandlingPositionUpdates = true;
if (mRTLastReportedPosition.left == left
&& mRTLastReportedPosition.top == top
&& mRTLastReportedPosition.right == right
@@ -731,13 +745,32 @@ public class SurfaceView extends View {
Log.d(TAG, String.format("%d windowPositionLostRT RT, frameNr = %d",
System.identityHashCode(this), frameNumber));
}
- // TODO: This is a bit of a hack as we don't have an API to report to WM
- // to hide a window with a frameNumber, so just shift the window very far into
- // negative space which will do effectively the same thing.
- // Use the last reported size to avoid influencing the size of the bufferqueue
- int x = -1000 - mRTLastReportedPosition.width();
- int y = -1000 - mRTLastReportedPosition.height();
- updateWindowPositionRT(frameNumber, x, y, -1000, -1000);
+ IWindowSession session = mSession;
+ MyWindow window = mWindow;
+ if (session == null || window == null) {
+ // We got detached prior to receiving this, abort
+ return;
+ }
+ if (mRtHandlingPositionUpdates) {
+ mRtHandlingPositionUpdates = false;
+ // This callback will happen while the UI thread is blocked, so we can
+ // safely access other member variables at this time.
+ // So do what the UI thread would have done if RT wasn't handling position
+ // updates.
+ if (!mWinFrame.isEmpty() && !mWinFrame.equals(mRTLastReportedPosition)) {
+ try {
+ if (DEBUG) Log.d(TAG, String.format("%d updateWindowPosition, " +
+ "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
+ mWinFrame.left, mWinFrame.top,
+ mWinFrame.right, mWinFrame.bottom));
+ session.repositionChild(window, mWinFrame.left, mWinFrame.top,
+ mWinFrame.right, mWinFrame.bottom, frameNumber, mWinFrame);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Exception from relayout", ex);
+ }
+ }
+ mRTLastReportedPosition.setEmpty();
+ }
}
private SurfaceHolder.Callback[] getSurfaceCallbacks() {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 5f6ee09bf2ac..d4ac30076eaa 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20527,8 +20527,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to the target Views. For example, it can contain flags that differentiate between a
* a copy operation and a move operation.
* </p>
- * @param flags Flags that control the drag and drop operation. No flags are currently defined,
- * so the parameter should be set to 0.
+ * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
+ * flags, or any combination of the following:
+ * <ul>
+ * <li>{@link #DRAG_FLAG_GLOBAL}</li>
+ * <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
+ * <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
+ * <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
+ * <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
+ * <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
+ * <li>{@link #DRAG_FLAG_OPAQUE}</li>
+ * </ul>
* @return {@code true} if the method completes successfully, or
* {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
* do a drag, and so no drag operation is in progress.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 65f0caa0ef24..c42752287a42 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -26,7 +26,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import android.Manifest;
import android.animation.LayoutTransition;
+import android.annotation.NonNull;
import android.app.ActivityManagerNative;
+import android.app.ResourcesManager;
import android.content.ClipDescription;
import android.content.ComponentCallbacks;
import android.content.Context;
@@ -164,7 +166,7 @@ public final class ViewRootImpl implements ViewParent,
final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList<>();
final Context mContext;
final IWindowSession mWindowSession;
- final Display mDisplay;
+ @NonNull Display mDisplay;
final DisplayManager mDisplayManager;
final String mBasePackageName;
@@ -308,8 +310,6 @@ public final class ViewRootImpl implements ViewParent,
boolean mAdded;
boolean mAddedTouchMode;
- final DisplayAdjustments mDisplayAdjustments;
-
// These are accessed by multiple threads.
final Rect mWinFrame; // frame given by window manager.
@@ -413,9 +413,6 @@ public final class ViewRootImpl implements ViewParent,
mWindowSession = WindowManagerGlobal.getWindowSession();
mDisplay = display;
mBasePackageName = context.getBasePackageName();
-
- mDisplayAdjustments = display.getDisplayAdjustments();
-
mThread = Thread.currentThread();
mLocation = new WindowLeaked(null);
mLocation.fillInStackTrace();
@@ -589,7 +586,8 @@ public final class ViewRootImpl implements ViewParent,
attrs.setSurfaceInsets(view, false /*manual*/, true /*preservePrevious*/);
}
- CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
+ CompatibilityInfo compatibilityInfo =
+ mDisplay.getDisplayAdjustments().getCompatibilityInfo();
mTranslator = compatibilityInfo.getTranslator();
// If the application owns the surface, don't enable hardware acceleration
@@ -1476,7 +1474,8 @@ public final class ViewRootImpl implements ViewParent,
surfaceChanged = true;
params = lp;
}
- CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
+ CompatibilityInfo compatibilityInfo =
+ mDisplay.getDisplayAdjustments().getCompatibilityInfo();
if (compatibilityInfo.supportsScreen() == mLastInCompatMode) {
params = lp;
mFullRedrawNeeded = true;
@@ -1732,7 +1731,7 @@ public final class ViewRootImpl implements ViewParent,
}
boolean hwInitialized = false;
- boolean contentInsetsChanged = false;
+ boolean framesChanged = false;
boolean hadSurface = mSurface.isValid();
try {
@@ -1772,7 +1771,7 @@ public final class ViewRootImpl implements ViewParent,
final boolean overscanInsetsChanged = !mPendingOverscanInsets.equals(
mAttachInfo.mOverscanInsets);
- contentInsetsChanged = !mPendingContentInsets.equals(
+ boolean contentInsetsChanged = !mPendingContentInsets.equals(
mAttachInfo.mContentInsets);
final boolean visibleInsetsChanged = !mPendingVisibleInsets.equals(
mAttachInfo.mVisibleInsets);
@@ -1822,6 +1821,19 @@ public final class ViewRootImpl implements ViewParent,
+ mAttachInfo.mVisibleInsets);
}
+ // If any of the insets changed, do a forceLayout on the view so that the
+ // measure cache is cleared. We might have a pending MSG_RESIZED_REPORT
+ // that is supposed to take care of it, but since pending insets are
+ // already modified here, it won't detect the frame change after this.
+ framesChanged = overscanInsetsChanged
+ || contentInsetsChanged
+ || stableInsetsChanged
+ || visibleInsetsChanged
+ || outsetsChanged;
+ if (mAdded && mView != null && framesChanged) {
+ forceLayout(mView);
+ }
+
if (!hadSurface) {
if (mSurface.isValid()) {
// If we are creating a new surface, then we need to
@@ -2005,7 +2017,7 @@ public final class ViewRootImpl implements ViewParent,
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
(relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
- || mHeight != host.getMeasuredHeight() || contentInsetsChanged ||
+ || mHeight != host.getMeasuredHeight() || framesChanged ||
updatedConfiguration) {
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
@@ -2014,7 +2026,7 @@ public final class ViewRootImpl implements ViewParent,
+ mWidth + " measuredWidth=" + host.getMeasuredWidth()
+ " mHeight=" + mHeight
+ " measuredHeight=" + host.getMeasuredHeight()
- + " coveredInsetsChanged=" + contentInsetsChanged);
+ + " framesChanged=" + framesChanged);
// Ask host how big it wants to be
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
@@ -3301,7 +3313,7 @@ public final class ViewRootImpl implements ViewParent,
+ mWindowAttributes.getTitle()
+ ": " + config);
- CompatibilityInfo ci = mDisplayAdjustments.getCompatibilityInfo();
+ CompatibilityInfo ci = mDisplay.getDisplayAdjustments().getCompatibilityInfo();
if (!ci.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
config = new Configuration(config);
ci.applyToConfiguration(mNoncompatDensity, config);
@@ -3316,8 +3328,13 @@ public final class ViewRootImpl implements ViewParent,
// At this point the resources have been updated to
// have the most recent config, whatever that is. Use
// the one in them which may be newer.
- config = mView.getResources().getConfiguration();
+ final Resources localResources = mView.getResources();
+ config = localResources.getConfiguration();
if (force || mLastConfiguration.diff(config) != 0) {
+ // Update the display with new DisplayAdjustments.
+ mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(
+ mDisplay.getDisplayId(), localResources.getDisplayAdjustments());
+
final int lastLayoutDirection = mLastConfiguration.getLayoutDirection();
final int currentLayoutDirection = config.getLayoutDirection();
mLastConfiguration.setTo(config);
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index f8c7d68bd394..dd4e09685362 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -55,26 +55,26 @@ import java.util.List;
*/
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
- private final Display mDisplay;
+ private final Context mContext;
private final Window mParentWindow;
private IBinder mDefaultToken;
- public WindowManagerImpl(Display display) {
- this(display, null);
+ public WindowManagerImpl(Context context) {
+ this(context, null);
}
- private WindowManagerImpl(Display display, Window parentWindow) {
- mDisplay = display;
+ private WindowManagerImpl(Context context, Window parentWindow) {
+ mContext = context;
mParentWindow = parentWindow;
}
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
- return new WindowManagerImpl(mDisplay, parentWindow);
+ return new WindowManagerImpl(mContext, parentWindow);
}
- public WindowManagerImpl createPresentationWindowManager(Display display) {
- return new WindowManagerImpl(display, mParentWindow);
+ public WindowManagerImpl createPresentationWindowManager(Context displayContext) {
+ return new WindowManagerImpl(displayContext, mParentWindow);
}
/**
@@ -90,7 +90,7 @@ public final class WindowManagerImpl implements WindowManager {
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
- mGlobal.addView(view, params, mDisplay, mParentWindow);
+ mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
@Override
@@ -144,6 +144,6 @@ public final class WindowManagerImpl implements WindowManager {
@Override
public Display getDefaultDisplay() {
- return mDisplay;
+ return mContext.getDisplay();
}
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index e6f5b8386d49..a8afaf20a1c5 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1410,4 +1410,6 @@ public interface WindowManagerPolicy {
* Called when the configuration has changed, and it's safe to load new values from resources.
*/
public void onConfigurationChanged();
+
+ public boolean shouldRotateSeamlessly(int oldRotation, int newRotation);
}
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 7c3fc8b5808b..38962a36dd70 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -855,5 +855,7 @@ public class BaseInputConnection implements InputConnection {
/**
* The default implementation does nothing.
*/
- public boolean insertContent(InputContentInfo inputContentInfo, Bundle opts) { return false; }
+ public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
+ return false;
+ }
}
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 7ed0d27f65ec..80380897fd39 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -368,10 +368,10 @@ public class EditorInfo implements InputType, Parcelable {
/**
* List of acceptable MIME types for
- * {@link InputConnection#insertContent(InputContentInfo, Bundle)}.
+ * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)}.
*
* <p>{@code null} or an empty array means that
- * {@link InputConnection#insertContent(InputContentInfo, Bundle)} is not supported in this
+ * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)} is not supported in this
* editor.</p>
*/
@Nullable
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 05e05699df94..07910b60df3f 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -840,7 +840,25 @@ public interface InputConnection {
public void closeConnection();
/**
- * Called by the input method to insert a content such as PNG image to the editor.
+ * When this flag is used, the editor will be able to request read access to the content URI
+ * contained in the {@link InputContentInfo} object.
+ *
+ * <p>Make sure that the content provider owning the Uri sets the
+ * {@link android.R.styleable#AndroidManifestProvider_grantUriPermissions
+ * grantUriPermissions} attribute in its manifest or included the
+ * {@link android.R.styleable#AndroidManifestGrantUriPermission
+ * &lt;grant-uri-permissions&gt;} tag. Otherwise {@link InputContentInfo#requestPermission()}
+ * can fail.</p>
+ *
+ * <p>Although calling this API is allowed only for the IME that is currently selected, the
+ * client is able to request a temporary read-only access even after the current IME is switched
+ * to any other IME as long as the client keeps {@link InputContentInfo} object.</p>
+ **/
+ public static int INPUT_CONTENT_GRANT_READ_URI_PERMISSION =
+ android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION; // 0x00000001
+
+ /**
+ * Called by the input method to commit a content such as PNG image to the editor.
*
* <p>In order to avoid variety of compatibility issues, this focuses on a simple use case,
* where we expect editors and IMEs work cooperatively as follows:</p>
@@ -862,9 +880,11 @@ public interface InputConnection {
* </ul>
*
* @param inputContentInfo Content to be inserted.
+ * @param flags {@code 0} or {@link #INPUT_CONTENT_GRANT_READ_URI_PERMISSION}.
* @param opts optional bundle data. This can be {@code null}.
* @return {@code true} if this request is accepted by the application, no matter if the request
* is already handled or still being handled in background.
*/
- public boolean insertContent(@NonNull InputContentInfo inputContentInfo, @Nullable Bundle opts);
+ public boolean commitContent(@NonNull InputContentInfo inputContentInfo, int flags,
+ @Nullable Bundle opts);
}
diff --git a/core/java/android/view/inputmethod/InputConnectionInspector.java b/core/java/android/view/inputmethod/InputConnectionInspector.java
index fb24fcd8c77a..2b292bbca849 100644
--- a/core/java/android/view/inputmethod/InputConnectionInspector.java
+++ b/core/java/android/view/inputmethod/InputConnectionInspector.java
@@ -43,7 +43,7 @@ public final class InputConnectionInspector {
MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS,
MissingMethodFlags.GET_HANDLER,
MissingMethodFlags.CLOSE_CONNECTION,
- MissingMethodFlags.INSERT_CONTENT,
+ MissingMethodFlags.COMMIT_CONTENT,
})
public @interface MissingMethodFlags {
/**
@@ -82,10 +82,10 @@ public final class InputConnectionInspector {
*/
int CLOSE_CONNECTION = 1 << 6;
/**
- * {@link InputConnection#insertContent(InputContentInfo, Bundle)} is available in
+ * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)} is available in
* {@link android.os.Build.VERSION_CODES#N} MR-1 and later.
*/
- int INSERT_CONTENT = 1 << 7;
+ int COMMIT_CONTENT = 1 << 7;
}
private static final Map<Class, Integer> sMissingMethodsMap = Collections.synchronizedMap(
@@ -135,8 +135,8 @@ public final class InputConnectionInspector {
if (!hasCloseConnection(clazz)) {
flags |= MissingMethodFlags.CLOSE_CONNECTION;
}
- if (!hasInsertContent(clazz)) {
- flags |= MissingMethodFlags.INSERT_CONTENT;
+ if (!hasCommitContent(clazz)) {
+ flags |= MissingMethodFlags.COMMIT_CONTENT;
}
sMissingMethodsMap.put(clazz, flags);
return flags;
@@ -206,10 +206,10 @@ public final class InputConnectionInspector {
}
}
- private static boolean hasInsertContent(@NonNull final Class clazz) {
+ private static boolean hasCommitContent(@NonNull final Class clazz) {
try {
- final Method method = clazz.getMethod("insertContent", InputContentInfo.class,
- Bundle.class);
+ final Method method = clazz.getMethod("commitContent", InputContentInfo.class,
+ int.class, Bundle.class);
return !Modifier.isAbstract(method.getModifiers());
} catch (NoSuchMethodException e) {
return false;
@@ -263,11 +263,11 @@ public final class InputConnectionInspector {
}
sb.append("closeConnection()");
}
- if ((flags & MissingMethodFlags.INSERT_CONTENT) != 0) {
+ if ((flags & MissingMethodFlags.COMMIT_CONTENT) != 0) {
if (!isEmpty) {
sb.append(",");
}
- sb.append("InsertContent(InputContentInfo, Bundle)");
+ sb.append("commitContent(InputContentInfo, Bundle)");
}
return sb.toString();
}
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index 431836a44f84..317730ca092c 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -274,7 +274,7 @@ public class InputConnectionWrapper implements InputConnection {
* {@inheritDoc}
* @throws NullPointerException if the target is {@code null}.
*/
- public boolean insertContent(InputContentInfo inputContentInfo, Bundle opts) {
- return mTarget.insertContent(inputContentInfo, opts);
+ public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
+ return mTarget.commitContent(inputContentInfo, flags, opts);
}
}
diff --git a/core/java/android/view/inputmethod/InputContentInfo.java b/core/java/android/view/inputmethod/InputContentInfo.java
index e2ecfae7f764..9579bbf32835 100644
--- a/core/java/android/view/inputmethod/InputContentInfo.java
+++ b/core/java/android/view/inputmethod/InputContentInfo.java
@@ -22,13 +22,16 @@ import android.content.ClipDescription;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.RemoteException;
+
+import com.android.internal.inputmethod.IInputContentUriToken;
import java.security.InvalidParameterException;
/**
* A container object with which input methods can send content files to the target application.
*/
-public class InputContentInfo implements Parcelable {
+public final class InputContentInfo implements Parcelable {
@NonNull
private final Uri mContentUri;
@@ -36,6 +39,8 @@ public class InputContentInfo implements Parcelable {
private final ClipDescription mDescription;
@Nullable
private final Uri mLinkUri;
+ @NonNull
+ private IInputContentUriToken mUriToken;
/**
* Constructs {@link InputContentInfo} object only with mandatory data.
@@ -110,7 +115,7 @@ public class InputContentInfo implements Parcelable {
return false;
}
final String contentUriScheme = contentUri.getScheme();
- if (contentUriScheme == null || !contentUriScheme.equalsIgnoreCase("content")) {
+ if (!"content".equals(contentUriScheme)) {
if (throwException) {
throw new InvalidParameterException("contentUri must have content scheme");
}
@@ -137,8 +142,9 @@ public class InputContentInfo implements Parcelable {
public Uri getContentUri() { return mContentUri; }
/**
- * @return {@link ClipDescription} object that contains the metadata of {@code contentUri} such
- * as MIME type(s). {@link ClipDescription#getLabel()} can be used for accessibility purpose.
+ * @return {@link ClipDescription} object that contains the metadata of {@code #getContentUri()}
+ * such as MIME type(s). {@link ClipDescription#getLabel()} can be used for accessibility
+ * purpose.
*/
@NonNull
public ClipDescription getDescription() { return mDescription; }
@@ -149,6 +155,47 @@ public class InputContentInfo implements Parcelable {
@Nullable
public Uri getLinkUri() { return mLinkUri; }
+ void setUriToken(IInputContentUriToken token) {
+ if (mUriToken != null) {
+ throw new IllegalStateException("URI token is already set");
+ }
+ mUriToken = token;
+ }
+
+ /**
+ * Requests a temporary read-only access permission for content URI associated with this object.
+ *
+ * <p>Does nothing if the temporary permission is already granted.</p>
+ */
+ public void requestPermission() {
+ if (mUriToken == null) {
+ return;
+ }
+ try {
+ mUriToken.take();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Releases a temporary read-only access permission for content URI associated with this object.
+ *
+ * <p>Does nothing if the temporary permission is not granted.</p>
+ */
+ public void releasePermission() {
+ if (mUriToken == null) {
+ return;
+ }
+ try {
+ mUriToken.release();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ } finally {
+ mUriToken = null;
+ }
+ }
+
/**
* Used to package this object into a {@link Parcel}.
*
@@ -160,12 +207,23 @@ public class InputContentInfo implements Parcelable {
Uri.writeToParcel(dest, mContentUri);
mDescription.writeToParcel(dest, flags);
Uri.writeToParcel(dest, mLinkUri);
+ if (mUriToken != null) {
+ dest.writeInt(1);
+ dest.writeStrongBinder(mUriToken.asBinder());
+ } else {
+ dest.writeInt(0);
+ }
}
private InputContentInfo(@NonNull Parcel source) {
mContentUri = Uri.CREATOR.createFromParcel(source);
mDescription = ClipDescription.CREATOR.createFromParcel(source);
mLinkUri = Uri.CREATOR.createFromParcel(source);
+ if (source.readInt() == 1) {
+ mUriToken = IInputContentUriToken.Stub.asInterface(source.readStrongBinder());
+ } else {
+ mUriToken = null;
+ }
}
/**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 4013b30fce06..c0c8e64aacc8 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -16,6 +16,7 @@
package android.view.inputmethod;
+import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.os.SomeArgs;
import com.android.internal.view.IInputConnectionWrapper;
import com.android.internal.view.IInputContext;
@@ -30,6 +31,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.content.Context;
import android.graphics.Rect;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -56,6 +58,7 @@ import android.view.ViewRootImpl;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -2288,6 +2291,40 @@ public final class InputMethodManager {
}
}
+ /**
+ * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
+ * permission to the content.
+ *
+ * <p>See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo, EditorInfo)}
+ * for details.</p>
+ *
+ * @param token Supplies the identifying token given to an input method when it was started,
+ * which allows it to perform this operation on itself.
+ * @param inputContentInfo Content to be temporarily exposed from the input method to the
+ * application.
+ * This cannot be {@code null}.
+ * @param editorInfo The editor that receives {@link InputContentInfo}.
+ * @hide
+ */
+ public void exposeContent(@NonNull IBinder token, @NonNull InputContentInfo inputContentInfo,
+ @NonNull EditorInfo editorInfo) {
+ final IInputContentUriToken uriToken;
+ final Uri contentUri = inputContentInfo.getContentUri();
+ try {
+ uriToken = mService.createInputContentUriToken(token, contentUri,
+ editorInfo.packageName);
+ if (uriToken == null) {
+ return;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
+ + " packageName=" + editorInfo.packageName, e);
+ return;
+ }
+ inputContentInfo.setUriToken(uriToken);
+ return;
+ }
+
void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
final Printer p = new PrintWriterPrinter(fout);
p.println("Input method client state for " + this + ":");
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 2d1e0bd30590..15eb8de5614c 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -141,17 +141,38 @@ public final class WebViewFactory {
*/
public static int loadWebViewNativeLibraryFromPackage(String packageName,
ClassLoader clazzLoader) {
- int ret = waitForProviderAndSetPackageInfo();
- if (ret != LIBLOAD_SUCCESS && ret != LIBLOAD_FAILED_WAITING_FOR_RELRO) {
- return ret;
+ WebViewProviderResponse response = null;
+ try {
+ response = getUpdateService().waitForAndGetProvider();
+ } catch (RemoteException e) {
+ Log.e(LOGTAG, "error waiting for relro creation", e);
+ return LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN;
}
- if (!sPackageInfo.packageName.equals(packageName))
+
+
+ if (response.status != LIBLOAD_SUCCESS
+ && response.status != LIBLOAD_FAILED_WAITING_FOR_RELRO) {
+ return response.status;
+ }
+ if (!response.packageInfo.packageName.equals(packageName)) {
+ return LIBLOAD_WRONG_PACKAGE_NAME;
+ }
+
+ PackageManager packageManager = AppGlobals.getInitialApplication().getPackageManager();
+ PackageInfo packageInfo;
+ try {
+ packageInfo = packageManager.getPackageInfo(packageName,
+ PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(LOGTAG, "Couldn't find package " + packageName);
return LIBLOAD_WRONG_PACKAGE_NAME;
+ }
+ sPackageInfo = packageInfo;
int loadNativeRet = loadNativeLibrary(clazzLoader);
// If we failed waiting for relro we want to return that fact even if we successfully load
// the relro file.
- if (loadNativeRet == LIBLOAD_SUCCESS) return ret;
+ if (loadNativeRet == LIBLOAD_SUCCESS) return response.status;
return loadNativeRet;
}
@@ -288,7 +309,7 @@ public final class WebViewFactory {
Context webViewContext = initialApplication.createApplicationContext(
newPackageInfo.applicationInfo,
Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
- sPackageInfo = response.packageInfo;
+ sPackageInfo = newPackageInfo;
return webViewContext;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
@@ -599,22 +620,6 @@ public final class WebViewFactory {
}
}
- private static int waitForProviderAndSetPackageInfo() {
- WebViewProviderResponse response = null;
- try {
- response =
- getUpdateService().waitForAndGetProvider();
- if (response.status == LIBLOAD_SUCCESS
- || response.status == LIBLOAD_FAILED_WAITING_FOR_RELRO) {
- sPackageInfo = response.packageInfo;
- }
- } catch (RemoteException e) {
- Log.e(LOGTAG, "error waiting for relro creation", e);
- return LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN;
- }
- return response.status;
- }
-
// Assumes that we have waited for relro creation and set sPackageInfo
private static int loadNativeLibrary(ClassLoader clazzLoader) {
if (!sAddressSpaceReserved) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index fb532e2dd17f..7d7b8804cf12 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -19,7 +19,6 @@ package android.widget;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.NonNull;
-import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
@@ -5986,8 +5985,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
@Override
- public boolean insertContent(InputContentInfo inputContentInfo, Bundle opts) {
- return getTarget().insertContent(inputContentInfo, opts);
+ public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
+ return getTarget().commitContent(inputContentInfo, flags, opts);
}
}
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 3f6e625245f3..6477f079cb7f 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1001,9 +1001,13 @@ public class PopupWindow {
}
/**
- * Returns the popup's height MeasureSpec.
+ * Returns the popup's requested height. May be a layout constant such as
+ * {@link LayoutParams#WRAP_CONTENT} or {@link LayoutParams#MATCH_PARENT}.
+ * <p>
+ * The actual size of the popup may depend on other factors such as
+ * clipping and window layout.
*
- * @return the height MeasureSpec of the popup
+ * @return the popup height in pixels or a layout constant
* @see #setHeight(int)
*/
public int getHeight() {
@@ -1011,12 +1015,16 @@ public class PopupWindow {
}
/**
- * Sets the popup's height MeasureSpec.
+ * Sets the popup's requested height. May be a layout constant such as
+ * {@link LayoutParams#WRAP_CONTENT} or {@link LayoutParams#MATCH_PARENT}.
+ * <p>
+ * The actual size of the popup may depend on other factors such as
+ * clipping and window layout.
* <p>
* If the popup is showing, calling this method will take effect the next
* time the popup is shown.
*
- * @param height the height MeasureSpec of the popup
+ * @param height the popup height in pixels or a layout constant
* @see #getHeight()
* @see #isShowing()
*/
@@ -1025,9 +1033,13 @@ public class PopupWindow {
}
/**
- * Returns the popup's width MeasureSpec.
+ * Returns the popup's requested width. May be a layout constant such as
+ * {@link LayoutParams#WRAP_CONTENT} or {@link LayoutParams#MATCH_PARENT}.
+ * <p>
+ * The actual size of the popup may depend on other factors such as
+ * clipping and window layout.
*
- * @return the width MeasureSpec of the popup
+ * @return the popup width in pixels or a layout constant
* @see #setWidth(int)
*/
public int getWidth() {
@@ -1035,12 +1047,16 @@ public class PopupWindow {
}
/**
- * Sets the popup's width MeasureSpec.
+ * Sets the popup's requested width. May be a layout constant such as
+ * {@link LayoutParams#WRAP_CONTENT} or {@link LayoutParams#MATCH_PARENT}.
+ * <p>
+ * The actual size of the popup may depend on other factors such as
+ * clipping and window layout.
* <p>
* If the popup is showing, calling this method will take effect the next
* time the popup is shown.
*
- * @param width the width MeasureSpec of the popup
+ * @param width the popup width in pixels or a layout constant
* @see #getWidth()
* @see #isShowing()
*/
@@ -1377,6 +1393,14 @@ public class PopupWindow {
}
}
+ private int computeGravity() {
+ int gravity = Gravity.START | Gravity.TOP;
+ if (mClipToScreen || mClippingEnabled) {
+ gravity |= Gravity.DISPLAY_CLIP_VERTICAL | Gravity.DISPLAY_CLIP_HORIZONTAL;
+ }
+ return gravity;
+ }
+
/**
* <p>Generate the layout parameters for the popup window.</p>
*
@@ -1391,7 +1415,7 @@ public class PopupWindow {
// screen. The view is then positioned to the appropriate location by
// setting the x and y offsets to match the anchor's bottom-left
// corner.
- p.gravity = Gravity.START | Gravity.TOP;
+ p.gravity = computeGravity();
p.flags = computeFlags(p.flags);
p.type = mWindowLayoutType;
p.token = token;
@@ -1517,13 +1541,9 @@ public class PopupWindow {
anchor.getWindowVisibleDisplayFrame(displayFrame);
if (width == MATCH_PARENT) {
width = displayFrame.right - displayFrame.left;
- } else if (width == WRAP_CONTENT) {
- width = mContentView.getMeasuredWidth();
}
if (height == MATCH_PARENT) {
height = displayFrame.bottom - displayFrame.top;
- } else if (height == WRAP_CONTENT) {
- height = mContentView.getMeasuredHeight();
}
// Let the window manager know to align the top to y.
@@ -1946,6 +1966,12 @@ public class PopupWindow {
update = true;
}
+ final int newGravity = computeGravity();
+ if (newGravity != p.gravity) {
+ p.gravity = newGravity;
+ update = true;
+ }
+
if (update) {
setLayoutDirectionFromAnchor();
mWindowManager.updateViewLayout(mDecorView, p);
@@ -1958,8 +1984,8 @@ public class PopupWindow {
* Calling this function also updates the window with the current popup
* state as described for {@link #update()}.
*
- * @param width the new width, must be >= 0 or -1 to ignore
- * @param height the new height, must be >= 0 or -1 to ignore
+ * @param width the new width in pixels, must be >= 0 or -1 to ignore
+ * @param height the new height in pixels, must be >= 0 or -1 to ignore
*/
public void update(int width, int height) {
final WindowManager.LayoutParams p =
@@ -1976,8 +2002,8 @@ public class PopupWindow {
*
* @param x the new x location
* @param y the new y location
- * @param width the new width, must be >= 0 or -1 to ignore
- * @param height the new height, must be >= 0 or -1 to ignore
+ * @param width the new width in pixels, must be >= 0 or -1 to ignore
+ * @param height the new height in pixels, must be >= 0 or -1 to ignore
*/
public void update(int x, int y, int width, int height) {
update(x, y, width, height, false);
@@ -1992,8 +2018,8 @@ public class PopupWindow {
*
* @param x the new x location
* @param y the new y location
- * @param width the new width, must be >= 0 or -1 to ignore
- * @param height the new height, must be >= 0 or -1 to ignore
+ * @param width the new width in pixels, must be >= 0 or -1 to ignore
+ * @param height the new height in pixels, must be >= 0 or -1 to ignore
* @param force {@code true} to reposition the window even if the specified
* position already seems to correspond to the LayoutParams,
* {@code false} to only reposition if needed
@@ -2052,6 +2078,12 @@ public class PopupWindow {
update = true;
}
+ final int newGravity = computeGravity();
+ if (newGravity != p.gravity) {
+ p.gravity = newGravity;
+ update = true;
+ }
+
int newAccessibilityIdOfAnchor =
(mAnchor != null) ? mAnchor.get().getAccessibilityViewId() : -1;
if (newAccessibilityIdOfAnchor != p.accessibilityIdOfAnchor) {
@@ -2072,8 +2104,8 @@ public class PopupWindow {
* state as described for {@link #update()}.
*
* @param anchor the popup's anchor view
- * @param width the new width, must be >= 0 or -1 to ignore
- * @param height the new height, must be >= 0 or -1 to ignore
+ * @param width the new width in pixels, must be >= 0 or -1 to ignore
+ * @param height the new height in pixels, must be >= 0 or -1 to ignore
*/
public void update(View anchor, int width, int height) {
update(anchor, false, 0, 0, width, height);
@@ -2092,8 +2124,8 @@ public class PopupWindow {
* @param anchor the popup's anchor view
* @param xoff x offset from the view's left edge
* @param yoff y offset from the view's bottom edge
- * @param width the new width, must be >= 0 or -1 to ignore
- * @param height the new height, must be >= 0 or -1 to ignore
+ * @param width the new width in pixels, must be >= 0 or -1 to ignore
+ * @param height the new height in pixels, must be >= 0 or -1 to ignore
*/
public void update(View anchor, int xoff, int yoff, int width, int height) {
update(anchor, true, xoff, yoff, width, height);
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 9cdb73ae51ce..0988c928cb26 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -161,7 +161,7 @@ public class Toolbar extends ViewGroup {
private int mTitleMarginTop;
private int mTitleMarginBottom;
- private final RtlSpacingHelper mContentInsets = new RtlSpacingHelper();
+ private RtlSpacingHelper mContentInsets;
private int mContentInsetStartWithNavigation;
private int mContentInsetEndWithActions;
@@ -270,6 +270,7 @@ public class Toolbar extends ViewGroup {
final int contentInsetRight =
a.getDimensionPixelSize(R.styleable.Toolbar_contentInsetRight, 0);
+ ensureContentInsets();
mContentInsets.setAbsolute(contentInsetLeft, contentInsetRight);
if (contentInsetStart != RtlSpacingHelper.UNDEFINED ||
@@ -463,13 +464,13 @@ public class Toolbar extends ViewGroup {
*/
public void setTitleMarginBottom(int margin) {
mTitleMarginBottom = margin;
-
requestLayout();
}
@Override
public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
super.onRtlPropertiesChanged(layoutDirection);
+ ensureContentInsets();
mContentInsets.setDirection(layoutDirection == LAYOUT_DIRECTION_RTL);
}
@@ -1092,6 +1093,7 @@ public class Toolbar extends ViewGroup {
* @attr ref android.R.styleable#Toolbar_contentInsetStart
*/
public void setContentInsetsRelative(int contentInsetStart, int contentInsetEnd) {
+ ensureContentInsets();
mContentInsets.setRelative(contentInsetStart, contentInsetEnd);
}
@@ -1112,7 +1114,7 @@ public class Toolbar extends ViewGroup {
* @attr ref android.R.styleable#Toolbar_contentInsetStart
*/
public int getContentInsetStart() {
- return mContentInsets.getStart();
+ return mContentInsets != null ? mContentInsets.getStart() : 0;
}
/**
@@ -1132,7 +1134,7 @@ public class Toolbar extends ViewGroup {
* @attr ref android.R.styleable#Toolbar_contentInsetEnd
*/
public int getContentInsetEnd() {
- return mContentInsets.getEnd();
+ return mContentInsets != null ? mContentInsets.getEnd() : 0;
}
/**
@@ -1154,6 +1156,7 @@ public class Toolbar extends ViewGroup {
* @attr ref android.R.styleable#Toolbar_contentInsetRight
*/
public void setContentInsetsAbsolute(int contentInsetLeft, int contentInsetRight) {
+ ensureContentInsets();
mContentInsets.setAbsolute(contentInsetLeft, contentInsetRight);
}
@@ -1174,7 +1177,7 @@ public class Toolbar extends ViewGroup {
* @attr ref android.R.styleable#Toolbar_contentInsetLeft
*/
public int getContentInsetLeft() {
- return mContentInsets.getLeft();
+ return mContentInsets != null ? mContentInsets.getLeft() : 0;
}
/**
@@ -1194,7 +1197,7 @@ public class Toolbar extends ViewGroup {
* @attr ref android.R.styleable#Toolbar_contentInsetRight
*/
public int getContentInsetRight() {
- return mContentInsets.getRight();
+ return mContentInsets != null ? mContentInsets.getRight() : 0;
}
/**
@@ -2128,6 +2131,12 @@ public class Toolbar extends ViewGroup {
}
}
+ private void ensureContentInsets() {
+ if (mContentInsets == null) {
+ mContentInsets = new RtlSpacingHelper();
+ }
+ }
+
/**
* Accessor to enable LayoutLib to get ActionMenuPresenter directly.
*/
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index e3fce5197dca..e782c3c9fa40 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -307,6 +307,9 @@ public class LocaleStore {
localizedLocales.add(li.getLangScriptKey());
}
+ // Serbian in Latin script is only partially localized in N.
+ localizedLocales.remove("sr-Latn");
+
for (LocaleInfo li : sLocaleCache.values()) {
li.setTranslated(localizedLocales.contains(li.getLangScriptKey()));
}
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index ef2fd0d7401d..36ab394f4a79 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -53,7 +53,8 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
public class PlatLogoActivity extends Activity {
- public static final boolean REVEAL_THE_NAME = true;
+ public static final boolean REVEAL_THE_NAME = false;
+ public static final boolean FINISH = false;
FrameLayout mLayout;
int mTapCount;
@@ -112,7 +113,6 @@ public class PlatLogoActivity extends Activity {
ObjectAnimator.ofInt(overlay, "alpha", 0, 255)
.setDuration(500)
.start();
- return true;
}
final ContentResolver cr = getContentResolver();
@@ -139,7 +139,7 @@ public class PlatLogoActivity extends Activity {
} catch (ActivityNotFoundException ex) {
Log.e("PlatLogoActivity", "No more eggs.");
}
- finish();
+ if (FINISH) finish();
}
});
return true;
diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
index d24cefeecf07..0a539f19c48a 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -37,6 +37,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.Window;
import android.widget.TextView;
import com.android.internal.R;
@@ -59,6 +60,9 @@ public class UnlaunchableAppActivity extends Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ // As this activity has nothing to show, we should hide the title bar also
+ // TODO: Use AlertActivity so we don't need to hide title bar and create a dialog
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
Intent intent = getIntent();
mReason = intent.getIntExtra(EXTRA_UNLAUNCHABLE_REASON, -1);
mUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
diff --git a/core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl b/core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl
new file mode 100644
index 000000000000..8abc8074b5ac
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl
@@ -0,0 +1,27 @@
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package com.android.internal.inputmethod;
+
+import android.os.IBinder;
+
+/**
+ * {@hide}
+ */
+interface IInputContentUriToken {
+ void take();
+ void release();
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 07d38d71b347..a1df8c186982 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -108,7 +108,7 @@ public class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 146 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 147 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -547,6 +547,8 @@ public class BatteryStatsImpl extends BatteryStats {
private int mLoadedNumConnectivityChange;
private int mUnpluggedNumConnectivityChange;
+ private int mEstimatedBatteryCapacity = -1;
+
private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
private PowerProfile mPowerProfile;
@@ -578,6 +580,11 @@ public class BatteryStatsImpl extends BatteryStats {
return mDischargeCounter;
}
+ @Override
+ public int getEstimatedBatteryCapacity() {
+ return mEstimatedBatteryCapacity;
+ }
+
public BatteryStatsImpl() {
this(new SystemClocks());
}
@@ -7625,6 +7632,11 @@ public class BatteryStatsImpl extends BatteryStats {
numSpeedSteps);
firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
}
+
+ if (mEstimatedBatteryCapacity == -1) {
+ // Initialize the estimated battery capacity to a known preset one.
+ mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
+ }
}
}
@@ -8174,6 +8186,12 @@ public class BatteryStatsImpl extends BatteryStats {
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i].reset(false);
}
+
+ if (mPowerProfile != null) {
+ mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
+ } else {
+ mEstimatedBatteryCapacity = -1;
+ }
mInteractiveTimer.reset(false);
mPowerSaveModeEnabledTimer.reset(false);
mLastIdleTimeStart = elapsedRealtimeMillis;
@@ -9158,7 +9176,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime, final boolean onBattery,
- final int oldStatus, final int level) {
+ final int oldStatus, final int level, final int chargeUAh) {
boolean doWrite = false;
Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
m.arg1 = onBattery ? 1 : 0;
@@ -9212,6 +9230,10 @@ public class BatteryStatsImpl extends BatteryStats {
}
doWrite = true;
resetAllStatsLocked();
+ if (chargeUAh > 0) {
+ // Only use the reported coulomb charge value if it is supported and reported.
+ mEstimatedBatteryCapacity = (int) ((level / 100.0) * (chargeUAh / 1000));
+ }
mDischargeStartLevel = level;
reset = true;
mDischargeStepTracker.init();
@@ -9379,7 +9401,7 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargeScreenOffCounter.addCountLocked(chargeDiff);
}
mHistoryCur.batteryChargeUAh = chargeUAh;
- setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
+ setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh);
} else {
boolean changed = false;
if (mHistoryCur.batteryLevel != level) {
@@ -10093,6 +10115,7 @@ public class BatteryStatsImpl extends BatteryStats {
mDischargePlugLevel = in.readInt();
mDischargeCurrentLevel = in.readInt();
mCurrentBatteryLevel = in.readInt();
+ mEstimatedBatteryCapacity = in.readInt();
mLowDischargeAmountSinceCharge = in.readInt();
mHighDischargeAmountSinceCharge = in.readInt();
mDischargeAmountScreenOnSinceCharge = in.readInt();
@@ -10445,6 +10468,7 @@ public class BatteryStatsImpl extends BatteryStats {
out.writeInt(mDischargePlugLevel);
out.writeInt(mDischargeCurrentLevel);
out.writeInt(mCurrentBatteryLevel);
+ out.writeInt(mEstimatedBatteryCapacity);
out.writeInt(getLowDischargeAmountSinceCharge());
out.writeInt(getHighDischargeAmountSinceCharge());
out.writeInt(getDischargeAmountScreenOnSinceCharge());
@@ -10809,6 +10833,7 @@ public class BatteryStatsImpl extends BatteryStats {
mRealtime = in.readLong();
mRealtimeStart = in.readLong();
mOnBattery = in.readInt() != 0;
+ mEstimatedBatteryCapacity = in.readInt();
mOnBatteryInternal = false; // we are no longer really running.
mOnBatteryTimeBase.readFromParcel(in);
mOnBatteryScreenOffTimeBase.readFromParcel(in);
@@ -10992,6 +11017,7 @@ public class BatteryStatsImpl extends BatteryStats {
out.writeLong(mRealtime);
out.writeLong(mRealtimeStart);
out.writeInt(mOnBattery ? 1 : 0);
+ out.writeInt(mEstimatedBatteryCapacity);
mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 9c960c04d491..73a3a0be32e1 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -753,7 +753,7 @@ public class ZygoteInit {
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
- } catch (RuntimeException ex) {
+ } catch (Throwable ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index 8addffb0ef41..0ab3a41f1469 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -217,6 +217,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
synchronized (this) {
// Make sure no more messages are being sent.
mChoreographer = null;
+ Choreographer.releaseInstance();
}
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 7706ff7f173f..20f10b33343b 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -112,4 +112,5 @@ oneway interface IStatusBar
void addQsTile(in ComponentName tile);
void remQsTile(in ComponentName tile);
void clickQsTile(in ComponentName tile);
+ void handleSystemNavigationKey(in int key);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 3d054225d234..698e387175fb 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -66,4 +66,5 @@ interface IStatusBarService
void addTile(in ComponentName tile);
void remTile(in ComponentName tile);
void clickTile(in ComponentName tile);
+ void handleSystemNavigationKey(in int key);
}
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 39fd36b9058c..a5a3dba7ac12 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -29,8 +29,8 @@ import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
-import java.util.Iterator;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Vector;
/**
@@ -1642,7 +1642,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessage(int what) {
+ public void sendMessage(int what) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
@@ -1655,7 +1655,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessage(int what, Object obj) {
+ public void sendMessage(int what, Object obj) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
@@ -1668,7 +1668,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessage(int what, int arg1) {
+ public void sendMessage(int what, int arg1) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
@@ -1681,7 +1681,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessage(int what, int arg1, int arg2) {
+ public void sendMessage(int what, int arg1, int arg2) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
@@ -1694,7 +1694,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessage(int what, int arg1, int arg2, Object obj) {
+ public void sendMessage(int what, int arg1, int arg2, Object obj) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
@@ -1707,7 +1707,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessage(Message msg) {
+ public void sendMessage(Message msg) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
@@ -1720,7 +1720,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessageDelayed(int what, long delayMillis) {
+ public void sendMessageDelayed(int what, long delayMillis) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
@@ -1733,7 +1733,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessageDelayed(int what, Object obj, long delayMillis) {
+ public void sendMessageDelayed(int what, Object obj, long delayMillis) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
@@ -1746,7 +1746,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessageDelayed(int what, int arg1, long delayMillis) {
+ public void sendMessageDelayed(int what, int arg1, long delayMillis) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
@@ -1759,7 +1759,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessageDelayed(int what, int arg1, int arg2, long delayMillis) {
+ public void sendMessageDelayed(int what, int arg1, int arg2, long delayMillis) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
@@ -1772,7 +1772,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessageDelayed(int what, int arg1, int arg2, Object obj,
+ public void sendMessageDelayed(int what, int arg1, int arg2, Object obj,
long delayMillis) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
@@ -1786,7 +1786,7 @@ public class StateMachine {
*
* Message is ignored if state machine has quit.
*/
- public final void sendMessageDelayed(Message msg, long delayMillis) {
+ public void sendMessageDelayed(Message msg, long delayMillis) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index fc189a3e909e..62e34a6780fc 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -62,7 +62,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
private static final int DO_CLEAR_META_KEY_STATES = 130;
private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
private static final int DO_CLOSE_CONNECTION = 150;
- private static final int DO_INSERT_CONTENT = 160;
+ private static final int DO_COMMIT_CONTENT = 160;
@GuardedBy("mLock")
@Nullable
@@ -243,9 +243,10 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
dispatchMessage(obtainMessage(DO_CLOSE_CONNECTION));
}
- public void insertContent(InputContentInfo inputContentInfo, Bundle opts,
+ public void commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts,
int seq, IInputContextCallback callback) {
- dispatchMessage(obtainMessageOOSC(DO_INSERT_CONTENT, inputContentInfo, opts, seq, callback));
+ dispatchMessage(obtainMessageIOOSC(DO_COMMIT_CONTENT, flags, inputContentInfo, opts, seq,
+ callback));
}
void dispatchMessage(Message msg) {
@@ -559,26 +560,28 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
}
return;
}
- case DO_INSERT_CONTENT: {
+ case DO_COMMIT_CONTENT: {
+ final int flags = msg.arg1;
SomeArgs args = (SomeArgs) msg.obj;
try {
InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
- Log.w(TAG, "insertContent on inactive InputConnection");
- args.callback.setInsertContentResult(false, args.seq);
+ Log.w(TAG, "commitContent on inactive InputConnection");
+ args.callback.setCommitContentResult(false, args.seq);
return;
}
final InputContentInfo inputContentInfo = (InputContentInfo) args.arg1;
if (inputContentInfo == null || !inputContentInfo.validate()) {
- Log.w(TAG, "insertContent with invalid inputContentInfo="
+ Log.w(TAG, "commitContent with invalid inputContentInfo="
+ inputContentInfo);
- args.callback.setInsertContentResult(false, args.seq);
+ args.callback.setCommitContentResult(false, args.seq);
return;
}
- args.callback.setInsertContentResult(
- ic.insertContent(inputContentInfo, (Bundle) args.arg2), args.seq);
+ args.callback.setCommitContentResult(
+ ic.commitContent(inputContentInfo, flags, (Bundle) args.arg2),
+ args.seq);
} catch (RemoteException e) {
- Log.w(TAG, "Got RemoteException calling insertContent", e);
+ Log.w(TAG, "Got RemoteException calling commitContent", e);
}
return;
}
@@ -612,14 +615,14 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
return mH.obtainMessage(what, arg1, arg2, args);
}
- Message obtainMessageOOSC(int what, Object arg1, Object arg2, int seq,
+ Message obtainMessageIOOSC(int what, int arg1, Object objArg1, Object objArg2, int seq,
IInputContextCallback callback) {
SomeArgs args = new SomeArgs();
- args.arg1 = arg1;
- args.arg2 = arg2;
+ args.arg1 = objArg1;
+ args.arg2 = objArg2;
args.callback = callback;
args.seq = seq;
- return mH.obtainMessage(what, 0, 0, args);
+ return mH.obtainMessage(what, arg1, 0, args);
}
Message obtainMessageIOSC(int what, int arg1, Object arg2, int seq,
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index bd473557a1b6..728c55786c49 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -78,6 +78,6 @@ import com.android.internal.view.IInputContextCallback;
void requestUpdateCursorAnchorInfo(int cursorUpdateMode, int seq,
IInputContextCallback callback);
- void insertContent(in InputContentInfo inputContentInfo, in Bundle opts, int sec,
+ void commitContent(in InputContentInfo inputContentInfo, int flags, in Bundle opts, int sec,
IInputContextCallback callback);
}
diff --git a/core/java/com/android/internal/view/IInputContextCallback.aidl b/core/java/com/android/internal/view/IInputContextCallback.aidl
index 933cdc0d8745..0f40a83d7ee4 100644
--- a/core/java/com/android/internal/view/IInputContextCallback.aidl
+++ b/core/java/com/android/internal/view/IInputContextCallback.aidl
@@ -28,5 +28,5 @@ oneway interface IInputContextCallback {
void setExtractedText(in ExtractedText extractedText, int seq);
void setSelectedText(CharSequence selectedText, int seq);
void setRequestUpdateCursorAnchorInfoResult(boolean result, int seq);
- void setInsertContentResult(boolean result, int seq);
+ void setCommitContentResult(boolean result, int seq);
}
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index cb7c3bfecc89..9e4b43b6c007 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -16,11 +16,13 @@
package com.android.internal.view;
+import android.net.Uri;
import android.os.ResultReceiver;
import android.text.style.SuggestionSpan;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.EditorInfo;
+import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.view.InputBindResult;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -81,5 +83,8 @@ interface IInputMethodManager {
int getInputMethodWindowVisibleHeight();
void clearLastInputMethodWindowForTransition(in IBinder token);
+ IInputContentUriToken createInputContentUriToken(in IBinder token, in Uri contentUri,
+ in String packageName);
+
oneway void notifyUserAction(int sequenceNumber);
}
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 6d4d45c7041f..9a09dcccd1a7 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -16,7 +16,8 @@
package com.android.internal.view;
-import android.content.ClipData;
+import android.annotation.NonNull;
+import android.inputmethodservice.AbstractInputMethodService;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
@@ -32,9 +33,14 @@ import android.view.inputmethod.InputConnectionInspector;
import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
import android.view.inputmethod.InputContentInfo;
+import java.lang.ref.WeakReference;
+
public class InputConnectionWrapper implements InputConnection {
private static final int MAX_WAIT_TIME_MILLIS = 2000;
private final IInputContext mIInputContext;
+ @NonNull
+ private final WeakReference<AbstractInputMethodService> mInputMethodService;
+
@MissingMethodFlags
private final int mMissingMethods;
@@ -48,7 +54,7 @@ public class InputConnectionWrapper implements InputConnection {
public ExtractedText mExtractedText;
public int mCursorCapsMode;
public boolean mRequestUpdateCursorAnchorInfoResult;
- public boolean mInsertContentResult;
+ public boolean mCommitContentResult;
// A 'pool' of one InputContextCallback. Each ICW request will attempt to gain
// exclusive access to this object.
@@ -175,15 +181,15 @@ public class InputConnectionWrapper implements InputConnection {
}
}
- public void setInsertContentResult(boolean result, int seq) {
+ public void setCommitContentResult(boolean result, int seq) {
synchronized (this) {
if (seq == mSeq) {
- mInsertContentResult = result;
+ mCommitContentResult = result;
mHaveValue = true;
notifyAll();
} else {
Log.i(TAG, "Got out-of-sequence callback " + seq + " (expected " + mSeq
- + ") in setInsertContentResult, ignoring.");
+ + ") in setCommitContentResult, ignoring.");
}
}
}
@@ -211,8 +217,10 @@ public class InputConnectionWrapper implements InputConnection {
}
}
- public InputConnectionWrapper(IInputContext inputContext,
- @MissingMethodFlags final int missingMethods) {
+ public InputConnectionWrapper(
+ @NonNull WeakReference<AbstractInputMethodService> inputMethodService,
+ IInputContext inputContext, @MissingMethodFlags final int missingMethods) {
+ mInputMethodService = inputMethodService;
mIInputContext = inputContext;
mMissingMethods = missingMethods;
}
@@ -507,19 +515,28 @@ public class InputConnectionWrapper implements InputConnection {
// Nothing should happen when called from input method.
}
- public boolean insertContent(InputContentInfo inputContentInfo, Bundle opts) {
+ public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
boolean result = false;
- if (isMethodMissing(MissingMethodFlags.INSERT_CONTENT)) {
+ if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) {
// This method is not implemented.
return false;
}
try {
+ if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
+ final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+ if (inputMethodService == null) {
+ // This basically should not happen, because it's the the caller of this method.
+ return false;
+ }
+ inputMethodService.exposeContent(inputContentInfo, this);
+ }
+
InputContextCallback callback = InputContextCallback.getInstance();
- mIInputContext.insertContent(inputContentInfo, opts, callback.mSeq, callback);
+ mIInputContext.commitContent(inputContentInfo, flags, opts, callback.mSeq, callback);
synchronized (callback) {
callback.waitForResultLocked();
if (callback.mHaveValue) {
- result = callback.mInsertContentResult;
+ result = callback.mCommitContentResult;
}
}
callback.dispose();
diff --git a/core/jni/android_app_ApplicationLoaders.cpp b/core/jni/android_app_ApplicationLoaders.cpp
index 24ee9591fc2f..3e7c039e2129 100644
--- a/core/jni/android_app_ApplicationLoaders.cpp
+++ b/core/jni/android_app_ApplicationLoaders.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "ApplicationLoaders"
+
#include <nativehelper/ScopedUtfChars.h>
#include <nativeloader/native_loader.h>
#include <vulkan/vulkan_loader_data.h>
@@ -22,10 +24,17 @@
static void setupVulkanLayerPath_native(JNIEnv* env, jobject clazz,
jobject classLoader, jstring librarySearchPath) {
+ android_namespace_t* ns = android::FindNamespaceByClassLoader(env, classLoader);
ScopedUtfChars layerPathChars(env, librarySearchPath);
+
vulkan::LoaderData& loader_data = vulkan::LoaderData::GetInstance();
- loader_data.layer_path = layerPathChars.c_str();
- loader_data.app_namespace = android::FindNamespaceByClassLoader(env, classLoader);
+ if (loader_data.layer_path.empty()) {
+ loader_data.layer_path = layerPathChars.c_str();
+ loader_data.app_namespace = ns;
+ } else {
+ ALOGD("ignored Vulkan layer search path %s for namespace %p",
+ layerPathChars.c_str(), ns);
+ }
}
static const JNINativeMethod g_methods[] = {
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index f4237d20f47a..50f23bfe4003 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -30,7 +30,6 @@
#include <utils/Looper.h>
#include <utils/Vector.h>
-#include <endian.h> // htobe64
#include <map>
namespace {
@@ -200,19 +199,9 @@ translateNativeSensorToJavaSensor(JNIEnv *env, jobject sensor, const Sensor& nat
env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
}
- // java.util.UUID constructor UUID(long a, long b) assumes the two long inputs a and b
- // correspond to first half and second half of the 16-byte stream in big-endian,
- // respectively, if the byte stream is serialized according to RFC 4122 (Sec. 4.1.2).
- //
- // For Java UUID 12345678-90AB-CDEF-1122-334455667788, the byte stream will be
- // (uint8_t) {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, ....} according RFC 4122.
- //
- // According to Java UUID constructor document, the long parameter a should be always
- // 0x12345678980ABCDEF regardless of host machine endianess. Thus, htobe64 is used to
- // convert int64_t read directly, which will be in host-endian, to the big-endian required
- // by Java constructor.
- const int64_t (&uuid)[2] = nativeSensor.getUuid().i64;
- env->CallVoidMethod(sensor, sensorOffsets.setUuid, htobe64(uuid[0]), htobe64(uuid[1]));
+ // TODO(b/29547335): Rename "setUuid" method to "setId".
+ int64_t id = nativeSensor.getId();
+ env->CallVoidMethod(sensor, sensorOffsets.setUuid, id, 0);
}
return sensor;
}
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index f7a5e8a07fc0..3d952b0f713f 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -832,6 +832,7 @@ enum {
PROC_COMBINE = 0x100,
PROC_PARENS = 0x200,
PROC_QUOTES = 0x400,
+ PROC_CHAR = 0x800,
PROC_OUT_STRING = 0x1000,
PROC_OUT_LONG = 0x2000,
PROC_OUT_FLOAT = 0x4000,
@@ -933,8 +934,13 @@ jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz,
floatsData[di] = strtof(buffer+start, &end);
}
if ((mode&PROC_OUT_LONG) != 0 && di < NL) {
- char* end;
- longsData[di] = strtoll(buffer+start, &end, 10);
+ if ((mode&PROC_CHAR) != 0) {
+ // Caller wants single first character returned as one long.
+ longsData[di] = buffer[start];
+ } else {
+ char* end;
+ longsData[di] = strtoll(buffer+start, &end, 10);
+ }
}
if ((mode&PROC_OUT_STRING) != 0 && di < NS) {
jstring str = env->NewStringUTF(buffer+start);
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index f9936aedaa5a..a0d5904157eb 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -81,14 +81,12 @@ NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
NativeDisplayEventReceiver::~NativeDisplayEventReceiver() {
JNIEnv* env = AndroidRuntime::getJNIEnv();
env->DeleteGlobalRef(mReceiverWeakGlobal);
+ ALOGV("receiver %p ~ dtor display event receiver.", this);
}
void NativeDisplayEventReceiver::dispose() {
ALOGV("receiver %p ~ Disposing display event receiver.", this);
-
- if (!mReceiver.initCheck()) {
- mMessageQueue->getLooper()->removeFd(mReceiver.getFd());
- }
+ DisplayEventDispatcher::dispose();
}
void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
@@ -143,7 +141,7 @@ static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
}
static void nativeDispose(JNIEnv* env, jclass clazz, jlong receiverPtr) {
- sp<NativeDisplayEventReceiver> receiver =
+ NativeDisplayEventReceiver* receiver =
reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
receiver->dispose();
receiver->decStrong(gDisplayEventReceiverClassInfo.clazz); // drop reference held by the object
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 4fc546c98e97..b0028e1b6f5b 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -573,8 +573,9 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
bounds.roundOut();
}
+ incStrong(0);
auto functor = std::bind(
- std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePosition), this,
+ std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePositionAsync), this,
(jlong) info.canvasContext.getFrameNumber(),
(jint) bounds.left, (jint) bounds.top,
(jint) bounds.right, (jint) bounds.bottom);
@@ -585,15 +586,18 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return;
- if (info) {
- auto functor = std::bind(
- std::mem_fn(&SurfaceViewPositionUpdater::doNotifyPositionLost), this,
- (jlong) info->canvasContext.getFrameNumber());
-
- info->canvasContext.enqueueFrameWork(std::move(functor));
- } else {
- doNotifyPositionLost(0);
+ ATRACE_NAME("SurfaceView position lost");
+ JNIEnv* env = jnienv();
+ jobject localref = env->NewLocalRef(mWeakRef);
+ if (CC_UNLIKELY(!localref)) {
+ jnienv()->DeleteWeakGlobalRef(mWeakRef);
+ mWeakRef = nullptr;
+ return;
}
+
+ env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod,
+ info ? info->canvasContext.getFrameNumber() : 0);
+ env->DeleteLocalRef(localref);
}
private:
@@ -605,36 +609,23 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
return env;
}
- void doUpdatePosition(jlong frameNumber, jint left, jint top,
+ void doUpdatePositionAsync(jlong frameNumber, jint left, jint top,
jint right, jint bottom) {
ATRACE_NAME("Update SurfaceView position");
JNIEnv* env = jnienv();
jobject localref = env->NewLocalRef(mWeakRef);
if (CC_UNLIKELY(!localref)) {
- jnienv()->DeleteWeakGlobalRef(mWeakRef);
- mWeakRef = nullptr;
- return;
- }
-
- env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
- frameNumber, left, top, right, bottom);
- env->DeleteLocalRef(localref);
- }
-
- void doNotifyPositionLost(jlong frameNumber) {
- ATRACE_NAME("SurfaceView position lost");
-
- JNIEnv* env = jnienv();
- jobject localref = env->NewLocalRef(mWeakRef);
- if (CC_UNLIKELY(!localref)) {
- jnienv()->DeleteWeakGlobalRef(mWeakRef);
+ env->DeleteWeakGlobalRef(mWeakRef);
mWeakRef = nullptr;
- return;
+ } else {
+ env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
+ frameNumber, left, top, right, bottom);
+ env->DeleteLocalRef(localref);
}
- env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod, frameNumber);
- env->DeleteLocalRef(localref);
+ // We need to release ourselves here
+ decStrong(0);
}
JavaVM* mVm;
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index ff75677536c4..fa1313bfd79d 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -248,10 +248,10 @@ static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong nativeObject, jfl
}
}
-static void nativeSetPositionAppliesWithResize(JNIEnv* env, jclass clazz,
+static void nativeSetGeometryAppliesWithResize(JNIEnv* env, jclass clazz,
jlong nativeObject) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
- status_t err = ctrl->setPositionAppliesWithResize();
+ status_t err = ctrl->setGeometryAppliesWithResize();
if (err < 0 && err != NO_INIT) {
doThrowIAE(env);
}
@@ -626,6 +626,16 @@ static jobject nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
return javaObjectForIBinder(env, ctrl->getHandle());
}
+static jboolean nativeGetTransformToDisplayInverse(JNIEnv* env, jclass clazz, jlong nativeObject) {
+ bool out = false;
+ auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ status_t status = ctrl->getTransformToDisplayInverse(&out);
+ if (status != NO_ERROR) {
+ return false;
+ }
+ return out;
+}
+
static jobject nativeGetHdrCapabilities(JNIEnv* env, jclass clazz, jobject tokenObject) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
if (token == NULL) return NULL;
@@ -667,8 +677,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetLayer },
{"nativeSetPosition", "(JFF)V",
(void*)nativeSetPosition },
- {"nativeSetPositionAppliesWithResize", "(J)V",
- (void*)nativeSetPositionAppliesWithResize },
+ {"nativeSetGeometryAppliesWithResize", "(J)V",
+ (void*)nativeSetGeometryAppliesWithResize },
{"nativeSetSize", "(JII)V",
(void*)nativeSetSize },
{"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V",
@@ -722,7 +732,9 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
{"nativeSetOverrideScalingMode", "(JI)V",
(void*)nativeSetOverrideScalingMode },
{"nativeGetHandle", "(J)Landroid/os/IBinder;",
- (void*)nativeGetHandle }
+ (void*)nativeGetHandle },
+ {"nativeGetTransformToDisplayInverse", "(J)Z",
+ (void*)nativeGetTransformToDisplayInverse },
};
int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 212bf579cfa7..61a0bda17855 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -255,7 +255,6 @@ public:
void runVectorDrawableAnimators(AnimationContext* context) {
for (auto it = mVectorDrawableAnimators.begin(); it != mVectorDrawableAnimators.end();) {
- (*it)->pushStaging(*context);
if ((*it)->animate(*context)) {
it = mVectorDrawableAnimators.erase(it);
} else {
@@ -264,6 +263,12 @@ public:
}
}
+ void pushStagingVectorDrawableAnimators(AnimationContext* context) {
+ for (auto& anim : mVectorDrawableAnimators) {
+ anim->pushStaging(*context);
+ }
+ }
+
void destroy() {
for (auto& renderNode : mPendingAnimatingRenderNodes) {
renderNode->animators().endAllStagingAnimators();
@@ -328,6 +333,9 @@ public:
// already ran in each RenderNode. Note that these animators don't damage the RenderNodes.
// The damaging is done in prepareTree as needed after checking whether a VD has been
// modified.
+ if (mode == TreeInfo::MODE_FULL) {
+ mRootNode->pushStagingVectorDrawableAnimators(this);
+ }
mRootNode->runVectorDrawableAnimators(this);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3783dc8fa179..3c71dd9312a5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -193,6 +193,7 @@
<protected-broadcast android:name="android.btopp.intent.action.OPEN" />
<protected-broadcast android:name="android.btopp.intent.action.OPEN_INBOUND" />
<protected-broadcast android:name="android.btopp.intent.action.TRANSFER_COMPLETE" />
+ <protected-broadcast android:name="com.android.bluetooth.gatt.REFRESH_BATCHED_SCAN" />
<protected-broadcast android:name="com.android.bluetooth.pbap.authchall" />
<protected-broadcast android:name="com.android.bluetooth.pbap.userconfirmtimeout" />
<protected-broadcast android:name="com.android.bluetooth.pbap.authresponse" />
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index defa83a9b5c6..516f25284282 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -19,10 +19,10 @@ Copyright (C) 2016 The Android Open Source Project
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
- android:fillColor="#FF7E5BBF"
+ android:fillColor="#FFc7d4b6"
android:pathData="M32.0,12.5l0.0,28.0l12.0,-5.0l0.0,-28.0z"/>
<path
- android:fillColor="#FF7E5BBF"
+ android:fillColor="#FFfbd3cb"
android:pathData="M4.0,40.5l12.0,-5.0l0.0,-11.0l-12.0,-12.0z"/>
<path
android:fillColor="#40000000"
@@ -31,7 +31,7 @@ Copyright (C) 2016 The Android Open Source Project
android:fillColor="#40000000"
android:pathData="M4.0,12.5l12.0,12.0l0.0,4.0z"/>
<path
- android:fillColor="#FF55C4F5"
+ android:fillColor="#FFe0e0d6"
android:pathData="M32.0,23.5l-16.0,-16.0l-12.0,5.0l0.0,0.0l12.0,12.0l16.0,16.0l12.0,-5.0l0.0,0.0z"/>
</vector>
diff --git a/core/res/res/layout/immersive_mode_cling.xml b/core/res/res/layout/immersive_mode_cling.xml
index 28fbea577aa5..b08b0f4d59c0 100644
--- a/core/res/res/layout/immersive_mode_cling.xml
+++ b/core/res/res/layout/immersive_mode_cling.xml
@@ -16,7 +16,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="#ff009688"
+ android:background="?android:attr/colorAccent"
android:gravity="center_vertical"
android:paddingBottom="24dp">
@@ -47,7 +47,7 @@
android:paddingTop="8dp"
android:scaleType="center"
android:src="@drawable/ic_expand_more_48dp"
- android:tint="#ff009688"/>
+ android:tint="?android:attr/colorAccent"/>
</FrameLayout>
<TextView
diff --git a/core/res/res/layout/unsupported_display_size_dialog_content.xml b/core/res/res/layout/unsupported_display_size_dialog_content.xml
new file mode 100644
index 000000000000..5e5cf00b27ac
--- /dev/null
+++ b/core/res/res/layout/unsupported_display_size_dialog_content.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="?attr/dialogPreferredPadding"
+ android:paddingLeft="?attr/dialogPreferredPadding"
+ android:paddingRight="?attr/dialogPreferredPadding">
+
+ <CheckBox
+ android:id="@+id/ask_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start"
+ android:text="@string/unsupported_display_size_show" />
+</FrameLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index a4a7e4e0e4ec..eaf45cad20c4 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skaal"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Wys altyd"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Heraktiveer hierdie in Stelselinstellings &gt; Programme &gt; Afgelaai."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> steun nie die huidige skermgrootte-instelling nie en sal dalk onverwags reageer."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Wys altyd"</string>
<string name="smv_application" msgid="3307209192155442829">"Die program <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) het sy selfopgelegde StrictMode-beleid oortree."</string>
<string name="smv_process" msgid="5120397012047462446">"Die proses <xliff:g id="PROCESS">%1$s</xliff:g> het die selfopgelegde StrictMode-beleid geskend."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android gradeer tans op..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Ontspeld"</string>
<string name="app_info" msgid="6856026610594615344">"Programinligting"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Herbegin sessie"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Tik om \'n nuwe demonstrasiesessie te begin"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Begin tans demonstrasie"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Herbegin tans sessie"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Doen \'n fabriekterugstelling om hierdie toestel sonder beperkinge te gebruik"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Raak om meer te wete te kom."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Het <xliff:g id="LABEL">%1$s</xliff:g> gedeaktiveer"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index e6875dabc8d9..8bf2b330463e 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"የልኬት ለውጥ"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"ሁልጊዜ አሳይ"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"በስርዓት ቅንብሮች ውስጥ ይሄንን ዳግም አንቃ&gt; Apps &amp;gt፤ወርዷል፡፡"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> አሁን ያለውን የማሳያ መጠን ቅንብር አይደግፍም እና ያልተጠብቀ ባሕሪ ሊያሳይ ይችላል።"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"ሁልጊዜ አሳይ"</string>
<string name="smv_application" msgid="3307209192155442829">"መተግበሪያው <xliff:g id="APPLICATION">%1$s</xliff:g>( ሂደት<xliff:g id="PROCESS">%2$s</xliff:g>) በራስ ተነሳሺ StrictMode ደንብን ይተላለፋል።"</string>
<string name="smv_process" msgid="5120397012047462446">"ሂደቱ <xliff:g id="PROCESS">%1$s</xliff:g> በራስ ተነሳሺ StrictMode ፖሊሲን ይተላለፋል።"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android እያሻሻለ ነው..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"ንቀል"</string>
<string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"ክፍለ-ጊዜን ዳግም ያስጀምሩ"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"አዲስ የማሳያ ክፍለ-ጊዜን ለመጀመር መታ ያድርጉ"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"ማሳያን ዳግም በማስጀመር ላይ"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"ክፍለ-ጊዜን ዳግም በማስጀመር ላይ"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"ይህን መሣሪያ ያለምንም ገደብ ለመጠቀም የፋብሪካ ዳግም ያስጀምሩ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"የበለጠ ለመረዳት ይንኩ።"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ተሰናክሏል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index b5e59f30830a..c4286bf13305 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1107,6 +1107,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"تدرج"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"الإظهار دائمًا"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"‏يمكنك إعادة تمكين هذا في إعدادات النظام &gt; التطبيقات &gt; ما تم تنزيله."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> غير متوافق مع الإعداد الحالي لحجم شاشة العرض وربما يعمل بطريقة غير متوقعة."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"العرض دائمًا"</string>
<string name="smv_application" msgid="3307209192155442829">"‏انتهك التطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> (العملية <xliff:g id="PROCESS">%2$s</xliff:g>) سياسة StrictMode المفروضة ذاتيًا."</string>
<string name="smv_process" msgid="5120397012047462446">"‏انتهكت العملية <xliff:g id="PROCESS">%1$s</xliff:g> سياسة StrictMode المفروضة ذاتيًا."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"‏جارٍ ترقية Android..."</string>
@@ -1793,10 +1795,14 @@
<string name="unpin_target" msgid="3556545602439143442">"إزالة تثبيت"</string>
<string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"إعادة تشغيل الجلسة"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"انقر لبدء جلسة عرض توضيحي جديدة"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"جارٍ بدء العرض التوضيحي"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"جارٍ إعادة تشغيل الجلسة"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"هل تريد إعادة تعيين الجهاز؟"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"انقر لإعادة تعيين الجهاز"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"جارٍ بدء العرض التوضيحي…"</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"جارٍ إعادة تعيين الجهاز…"</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"هل تريد إعادة تعيين الجهاز؟"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"ستفقد أي تغييرات وسيبدأ العرض التوضيحي مرة أخرى خلال <xliff:g id="TIMEOUT">%1$s</xliff:g> ثانية…"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"إلغاء"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"إعادة التعيين الآن"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"يمكنك إعادة تعيين بيانات المصنع لاستخدام هذا الجهاز بدون قيود"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"المس للتعرف على مزيد من المعلومات."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"تم تعطيل <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 407641587005..5d01fe17e2eb 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Miqyas"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Həmişə göstər"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Bunları Sistem ayarlarında yenidən aktivləşdir Yüklənmiş &gt; Tətbiqlər &gt;."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> cari Ekran ölçüsü ayarını dəstəkləmir və gözlənilməz şəkildə davrana bilər."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Həmişə göstərin"</string>
<string name="smv_application" msgid="3307209192155442829">"Tətbiq <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) StrictMode siyasətini pozdu."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> prosesi StrictMode siyasətini pozdu."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android təkmilləşdirilir..."</string>
@@ -1649,10 +1651,14 @@
<string name="unpin_target" msgid="3556545602439143442">"Çıxarın"</string>
<string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Sessiyanı Yenidən Başladın"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Yeni demo sessiyanı başlamaq üçün tıklayın"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Demo başlayır"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Sessiya yenidən başlayır"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"Cihaz sıfırlansın?"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"Cihazı sıfırlamaq üçün tıklayın"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"Demo başlayır…"</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"Cihaz sıfırlanır…"</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"Cihaz sıfırlansın?"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"Hər hansı dəyişikliyi itirəcəksiniz və demo <xliff:g id="TIMEOUT">%1$s</xliff:g> saniyəyə yenidən başlayacaq…"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"Ləğv edin"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"İndi sıfırlayın"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Bu cihazı məhdudiyyətsiz istifadə etmək üçün zavod sıfırlaması edin"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Daha çox məlumat üçün toxunun."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> deaktiv edildi"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index da7064598e1e..3aae1fda94b4 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Мащаб"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Винаги да се показва"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Активирайте отново това в „Системни настройки“ &gt; „Приложения“ &gt; „Изтеглени“."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> не поддържа текущата настройка за размер на дисплея и може да се държи по неочакван начин."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Винаги да се показва"</string>
<string name="smv_application" msgid="3307209192155442829">"Приложението „<xliff:g id="APPLICATION">%1$s</xliff:g>“ (процес „<xliff:g id="PROCESS">%2$s</xliff:g>“) наруши правилото за стриктен режим, наложено от самото него."</string>
<string name="smv_process" msgid="5120397012047462446">"Процесът <xliff:g id="PROCESS">%1$s</xliff:g> наруши правилото за стриктен режим, наложено от самия него."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android се надстройва..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Освобождаване"</string>
<string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string>
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Рестартиране на сесията"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Докоснете, за да стартирате нова демонстрационна сесия"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Демонстрацията се стартира"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Сесията се рестартира"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Възстановете фабричните настройки на това устройство, за да го използвате без ограничения"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Докоснете, за да научите повече."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g>: Деактивирано"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 3f26a49915a9..5974b1e4a488 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"স্কেল"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"সবসময় দেখান"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"সিস্টেম সেটিংস&gt; অ্যাপ্স&gt; ডাউনলোড করাগুলি এ এটি পুনঃসক্ষম করুন৷"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g>, বর্তমান প্রদর্শনের আকারের সেটিংস সমর্থন করে না এবং অপ্রত্যাশিত আচরণ করতে পারে৷"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"সর্বদা দেখান"</string>
<string name="smv_application" msgid="3307209192155442829">"অ্যাপ্লিকেশানটি <xliff:g id="APPLICATION">%1$s</xliff:g> (প্রক্রিয়া <xliff:g id="PROCESS">%2$s</xliff:g>) তার স্ব-প্রয়োগ করা কঠোর মোড নীতি লঙ্ঘন করেছে৷"</string>
<string name="smv_process" msgid="5120397012047462446">"প্রক্রিয়াটি <xliff:g id="PROCESS">%1$s</xliff:g> তার স্ব-প্রয়োগ করা কঠোর মোড নীতি লঙ্ঘন করেছে৷"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android আপগ্রেড করা হচ্ছে..."</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"কোনো অ্যাপ্লিকেশানকে সেশনগুলি পড়ার অনুমতি দেয়। এটি সক্রিয় প্যাকেজ ইনস্টলেশনের বিশদ বিবরণ দেখতে দেয়।"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"প্যাকেজগুলি ইনস্টল করার অনুরোধ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"একটি অ্যাপ্লিকেশানকে প্যাকেজগুলির ইনস্টল করার অনুরোধ জানাতে অনুমতি দেয়৷"</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"জুম নিয়ন্ত্রণের জন্য দুবার আলতো চাপুন"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"উইজেট যোগ করা যায়নি৷"</string>
<string name="ime_action_go" msgid="8320845651737369027">"যান"</string>
<string name="ime_action_search" msgid="658110271822807811">"অনুসন্ধান করুন"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"বিজ্ঞপ্তি র‌্যাঙ্কার পরিষেবা"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN সক্রিয়"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> এর দ্বারা VPN সক্রিয় করা হয়েছে"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"নেটওয়ার্ক পরিচালনা করতে আলতো চাপুন।"</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> তে সংযুক্ত হয়েছে৷ নেটওয়ার্ক পরিচালনা করতে আলতো চাপুন৷"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"সর্বদা-চালু VPN সংযুক্ত হচ্ছে..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"সর্বদা-চালু VPN সংযুক্ত হয়েছে"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"সর্বদা-চালু VPN ত্রুটি"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"আনপিন করুন"</string>
<string name="app_info" msgid="6856026610594615344">"অ্যাপ্লিকেশানের তথ্য"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"সেশন পুনঃসূচনা করুন"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"একটি নতুন ডেমো সেশন শুরু করতে আলতো চাপ দিন"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"ডেমো শুরু করা হচ্ছে"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"সেশন পুনরায় চালু করা হচ্ছে"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"কোনো বিধিনিষেধ ছাড়াই এই ডিভাইসটিকে ব্যবহার করতে ফ্যাক্টরি রিসেট করুন"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"আরো জানতে স্পর্শ করুন৷"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"অক্ষম করা <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 458e8102ba79..2fc2b567ae6d 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Escala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Mostra sempre"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Torna a activar-ho a Configuració del sistema &gt; Aplicacions &gt; Baixades."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admet la mida de pantalla actual i és possible que funcioni de manera inesperada."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mostra sempre"</string>
<string name="smv_application" msgid="3307209192155442829">"L\'aplicació <xliff:g id="APPLICATION">%1$s</xliff:g>(procés <xliff:g id="PROCESS">%2$s</xliff:g>) ha incomplert la seva política autoimposada de mode estricte."</string>
<string name="smv_process" msgid="5120397012047462446">"El procés <xliff:g id="PROCESS">%1$s</xliff:g> ha incomplert la seva política de mode estricte."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android s\'està actualitzant..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"No fixis"</string>
<string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string>
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Torna a iniciar la sessió"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Toca per iniciar una nova sessió de demostració"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"S\'està iniciant la demostració"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"S\'està tornant a iniciar la sessió"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Restableix les dades de fàbrica del dispositiu per utilitzar-lo sense restriccions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca per obtenir més informació."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> s\'ha desactivat"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 214f234d139c..0de5d4cfda82 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1061,6 +1061,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Měřítko"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Vždy zobrazovat"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Tento režim znovu povolíte v sekci Nastavení systému &gt; Aplikace &gt; Stažené."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> aktuální nastavení velikosti zobrazení nepodporuje a může se chovat neočekávaně."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Vždy zobrazovat"</string>
<string name="smv_application" msgid="3307209192155442829">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) porušila své vlastní vynucené zásady StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> porušil své vlastní vynucené zásady StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android se upgraduje..."</string>
@@ -1721,10 +1723,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Odepnout"</string>
<string name="app_info" msgid="6856026610594615344">"Informace o aplikaci"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Restartujte relaci"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Klepnutím zahájíte novou demonstrační relaci"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Spouštění ukázky"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Restartování relace"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Chcete-li toto zařízení používat bez omezení, obnovte jej do továrního nastavení"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Klepnutím zobrazíte další informace."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – zakázáno"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 59447c3a50b5..9df38689cd83 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skaler"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Vis altid"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Aktivér dette igen i Systemindstillinger &gt; Apps &gt; Downloadet."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> understøtter ikke den aktuelle indstilling for visningsstørrelse og vil muligvis ikke fungere som forventet."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Vis altid"</string>
<string name="smv_application" msgid="3307209192155442829">"Appen <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) har overtrådt sin egen StrictMode-politik."</string>
<string name="smv_process" msgid="5120397012047462446">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> har overtrådt sin egen StrictMode-politik."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android opgraderes..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Frigør"</string>
<string name="app_info" msgid="6856026610594615344">"Oplysninger om appen"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Genstart sessionen"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Tryk for at starte en ny demosession"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Starter demo"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Genstarter session"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Gendan fabriksdataene på enheden for at bruge den uden begrænsninger"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tryk for at få flere oplysninger."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – deaktiveret"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 79a2dbad5134..fe2d4f025825 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skalieren"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Immer anzeigen"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Eine erneute Aktivierung ist in den Systemeinstellungen unter \"Apps &gt; Heruntergeladen\" möglich."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> unterstützt nicht die aktuelle Einstellung für die Anzeigegröße, sodass ein unerwartetes Verhalten auftreten kann."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Immer anzeigen"</string>
<string name="smv_application" msgid="3307209192155442829">"Die App <xliff:g id="APPLICATION">%1$s</xliff:g> (Prozess <xliff:g id="PROCESS">%2$s</xliff:g>) hat gegen deine selbsterzwungene StrictMode-Richtlinie verstoßen."</string>
<string name="smv_process" msgid="5120397012047462446">"Der Prozess <xliff:g id="PROCESS">%1$s</xliff:g> hat gegen seine selbsterzwungene StrictMode-Richtlinie verstoßen."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android wird aktualisiert..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Markierung entfernen"</string>
<string name="app_info" msgid="6856026610594615344">"App-Informationen"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Sitzung neu starten"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Zum Starten einer neuen Demositzung tippen"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Demo wird gestartet"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Sitzung wird neu gestartet"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Gerät auf Werkseinstellungen zurücksetzen, um es ohne Einschränkungen zu nutzen"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Für weitere Informationen tippen."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> deaktiviert"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 4b388f884686..b34d6d7e82c1 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Κλίμακα"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Να εμφανίζονται πάντα"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Ενεργοποιήστε το ξανά στις Ρυθμίσεις συστημάτων &gt; Εφαρμογές &gt; Ληφθείσες."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν υποστηρίζει την τρέχουσα ρύθμιση Μεγέθους οθόνης και ενδέχεται να παρουσιάζει μη αναμενόμενη συμπεριφορά."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Να εμφανίζεται πάντα"</string>
<string name="smv_application" msgid="3307209192155442829">"Η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> (διεργασία <xliff:g id="PROCESS">%2$s</xliff:g>) παραβίασε την αυτοεπιβαλλόμενη πολιτική StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Η διεργασία <xliff:g id="PROCESS">%1$s</xliff:g> παραβίασε την αυτοεπιβαλόμενη πολιτική StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Το Android αναβαθμίζεται..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Ξεκαρφίτσωμα"</string>
<string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Επανεκκίνηση περιόδου σύνδεσης"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Πατήστε για να ξεκινήσετε μια νέα περίοδο σύνδεσης επίδειξης"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Έναρξη επίδειξης"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Επανεκκίνηση περιόδου σύνδεσης"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Επαναφέρετε τις εργοστασιακές ρυθμίσεις για να χρησιμοποιήσετε αυτήν τη συσκευή χωρίς περιορισμούς"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Αγγίξτε για να μάθετε περισσότερα."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Απενεργοποιημένο <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 12c5e2298fa6..eff9d81d8ddf 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Scale"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Always show"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Re-enable this in System settings &gt; Apps &gt; Downloaded."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> does not support the current Display size setting and may behave unexpectedly."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Always show"</string>
<string name="smv_application" msgid="3307209192155442829">"The app <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) has violated its self-enforced Strict Mode policy."</string>
<string name="smv_process" msgid="5120397012047462446">"The process <xliff:g id="PROCESS">%1$s</xliff:g> has violated its self-enforced StrictMode policy."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android is upgrading…"</string>
@@ -1649,10 +1651,14 @@
<string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Restart Session"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Tap to start a new demo session"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Starting demo"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Restarting session"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"Reset device?"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"Tap to reset device"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"Starting demo…"</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"Resetting device…"</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"Reset device?"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"You\'ll lose any changes and the demo will start again in <xliff:g id="TIMEOUT">%1$s</xliff:g> seconds…"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"Cancel"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reset now"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Factory reset to use this device without restrictions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Disabled <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 12c5e2298fa6..eff9d81d8ddf 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Scale"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Always show"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Re-enable this in System settings &gt; Apps &gt; Downloaded."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> does not support the current Display size setting and may behave unexpectedly."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Always show"</string>
<string name="smv_application" msgid="3307209192155442829">"The app <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) has violated its self-enforced Strict Mode policy."</string>
<string name="smv_process" msgid="5120397012047462446">"The process <xliff:g id="PROCESS">%1$s</xliff:g> has violated its self-enforced StrictMode policy."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android is upgrading…"</string>
@@ -1649,10 +1651,14 @@
<string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Restart Session"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Tap to start a new demo session"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Starting demo"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Restarting session"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"Reset device?"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"Tap to reset device"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"Starting demo…"</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"Resetting device…"</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"Reset device?"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"You\'ll lose any changes and the demo will start again in <xliff:g id="TIMEOUT">%1$s</xliff:g> seconds…"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"Cancel"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reset now"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Factory reset to use this device without restrictions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Disabled <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 12c5e2298fa6..eff9d81d8ddf 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Scale"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Always show"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Re-enable this in System settings &gt; Apps &gt; Downloaded."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> does not support the current Display size setting and may behave unexpectedly."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Always show"</string>
<string name="smv_application" msgid="3307209192155442829">"The app <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) has violated its self-enforced Strict Mode policy."</string>
<string name="smv_process" msgid="5120397012047462446">"The process <xliff:g id="PROCESS">%1$s</xliff:g> has violated its self-enforced StrictMode policy."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android is upgrading…"</string>
@@ -1649,10 +1651,14 @@
<string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
<string name="app_info" msgid="6856026610594615344">"App info"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Restart Session"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Tap to start a new demo session"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Starting demo"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Restarting session"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"Reset device?"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"Tap to reset device"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"Starting demo…"</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"Resetting device…"</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"Reset device?"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"You\'ll lose any changes and the demo will start again in <xliff:g id="TIMEOUT">%1$s</xliff:g> seconds…"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"Cancel"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Reset now"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Factory reset to use this device without restrictions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Disabled <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index c66a65931e26..70c6ad0b1bab 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Escala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Mostrar siempre"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Volver a activar Configuración del sistema &gt; Aplicaciones &gt; Descargas"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> no es compatible con la configuración del tamaño de pantalla actual. Es posible que no se comporte de manera correcta."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mostrar siempre"</string>
<string name="smv_application" msgid="3307209192155442829">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) ha infringido su política StrictMode de aplicación automática."</string>
<string name="smv_process" msgid="5120397012047462446">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha violado su política StrictMode autoimpuesta."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android se está actualizando..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"No fijar"</string>
<string name="app_info" msgid="6856026610594615344">"Información de la app"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Reiniciar sesión"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Presiona para iniciar una nueva sesión de demostración"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Iniciando demostración"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Reiniciando sesión"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Restablece la configuración de fábrica para usar este dispositivo sin restricciones"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para obtener más información."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Se inhabilitó <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index ae916caa910a..02314b838ff2 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Escala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Mostrar siempre"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Para volver a habilitar esta opción, accede a Ajustes &gt; Aplicaciones &gt; Descargadas."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admite el tamaño de pantalla actual y es posible que funcione de forma inesperada."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mostrar siempre"</string>
<string name="smv_application" msgid="3307209192155442829">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) ha infringido su política StrictMode autoaplicable."</string>
<string name="smv_process" msgid="5120397012047462446">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha infringido su política StrictMode autoaplicable."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Actualizando Android"</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"No fijar"</string>
<string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Reiniciar sesión"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Toca para iniciar una nueva sesión de demostración"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Iniciando demo"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Reiniciando sesión"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Restablece los datos de fábrica para usar este dispositivo sin restricciones"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para obtener más información."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> inhabilitado"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 15c9d830288d..f5da566ca97c 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Mõõtkava"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Kuva alati"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Lubage see uuesti valikutes Süsteemiseaded &gt; Rakendused &gt; Allalaaditud."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"Rakendus <xliff:g id="APP_NAME">%1$s</xliff:g> ei toeta praegust ekraani suuruse seadet ja võib ootamatult käituda."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Kuva alati"</string>
<string name="smv_application" msgid="3307209192155442829">"Rakendus <xliff:g id="APPLICATION">%1$s</xliff:g> (protsess <xliff:g id="PROCESS">%2$s</xliff:g>) on rikkunud isekehtestatud StrictMode\'i eeskirju."</string>
<string name="smv_process" msgid="5120397012047462446">"Protsess <xliff:g id="PROCESS">%1$s</xliff:g> on rikkunud isejõustatud StrictMode\'i eeskirju."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android viiakse üle uuemale versioonile ..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Vabasta"</string>
<string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Seansi taaskäivitamine"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Puudutage uue demoseansi alustamiseks"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Demo käivitamine"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Seansi taaskäivitamine"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Seadme piiranguteta kasutamiseks lähtestage see tehaseandmetele"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Lisateabe saamiseks puudutage."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Keelatud <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-eu-rES-watch/styles_material.xml b/core/res/res/values-eu-rES-watch/styles_material.xml
new file mode 100644
index 000000000000..36a459dc16a0
--- /dev/null
+++ b/core/res/res/values-eu-rES-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index bf6c2de6c270..2b41b53fc213 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Eskala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Erakutsi beti"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Gaitu hori berriro Sistemaren ezarpenak &gt; Aplikazioak &gt; Deskargatutakoak."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak ez du onartzen uneko pantailaren tamaina eta espero ez bezala joka lezake."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Erakutsi beti"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioak (<xliff:g id="PROCESS">%2$s</xliff:g> prozesua) berak aplikatutako StrictMode gidalerroa urratu du."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> prozesuak bere kabuz ezarritako StrictMode gidalerroak urratu ditu."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android bertsio-berritzen ari da…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Instalazio-saioak irakurtzea baimentzen die aplikazioei. Horrela, pakete-instalazio aktiboei buruzko xehetasunak ikus ditzakete."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"Eskatu instalazio-paketeak"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Paketeak instalatzeko eskatzea baimentzen die aplikazioei."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Sakatu birritan zooma kontrolatzeko"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Ezin izan da widgeta gehitu."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Joan"</string>
<string name="ime_action_search" msgid="658110271822807811">"Bilatu"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Jakinarazpenen sailkapen-zerbitzua"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN eginbidea aktibatuta"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN konexioa aktibatu du"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"Sakatu sarea kudeatzeko."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> saiora konektatuta. Sakatu sarea kudeatzeko."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Beti aktibatuta dagoen VPNa konektatzen…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Beti aktibatuta dagoen VPNa konektatu da"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Beti aktibatuta dagoen VPN errorea"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Kendu aingura"</string>
<string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Berrabiarazi saioa"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Demo-saio berria hasteko, sakatu hau"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Demoa abiarazten"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Saioa berrabiarazten"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Berrezarri jatorrizko ezarpenak gailua murriztapenik gabe erabili ahal izateko"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sakatu informazio gehiago lortzeko."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> desgaituta dago"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 52fa6b293515..5a8591726a06 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"مقیاس"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"همیشه نشان داده شود"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"‏در تنظیمات سیستم &gt;برنامه‎ها &gt; مورد بارگیری شده آن را دوباره فعال کنید."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> از تنظیم فعلی اندازه نمایشگر پشتیبانی نمی‌کند و ممکن است رفتار غیرمنتظره‌ای داشته باشد."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"همیشه نشان داده شود"</string>
<string name="smv_application" msgid="3307209192155442829">"‏برنامه <xliff:g id="APPLICATION">%1$s</xliff:g> (پردازش <xliff:g id="PROCESS">%2$s</xliff:g>) خط‌مشی StrictMode اجرایی خود را نقض کرده است."</string>
<string name="smv_process" msgid="5120397012047462446">"‏فرآیند <xliff:g id="PROCESS">%1$s</xliff:g> خط‌مشی StrictMode اجرای خودکار خود را نقض کرده است."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"‏Android در حال ارتقا است..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"برداشتن پین"</string>
<string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"راه‌اندازی مجدد جلسه"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"برای شروع جلسه آزمایشی جدید ضربه بزنید"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"شروع نسخه نمایشی"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"راه‌اندازی مجدد جلسه"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"برای استفاده بدون محدودیت از این دستگاه، بازنشانی کارخانه‌ای انجام دهید"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"برای یادگیری بیشتر لمس کنید."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> غیرفعال شد"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index edfd4a37cf89..4f11948e4329 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Asteikko"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Näytä aina"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Ota tämä uudelleen käyttöön kohdassa Järjestelmäasetukset &gt; Sovellukset &gt; Ladattu."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> ei tue nykyistä näytön kokoasetusta ja saattaa toimia odottamattomalla tavalla."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Näytä aina"</string>
<string name="smv_application" msgid="3307209192155442829">"Sovellus <xliff:g id="APPLICATION">%1$s</xliff:g> (prosessi <xliff:g id="PROCESS">%2$s</xliff:g>) on rikkonut itse käyttöön ottamaansa StrictMode-käytäntöä."</string>
<string name="smv_process" msgid="5120397012047462446">"Prosessi <xliff:g id="PROCESS">%1$s</xliff:g> on rikkonut itse käyttöön ottamaansa StrictMode-käytäntöä."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Androidia päivitetään…"</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Irrota"</string>
<string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Istunnon uudelleenaloitus"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Aloita uusi esittely napauttamalla."</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Aloitetaan esittelyä"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Aloitetaan istuntoa uudelleen"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Palauta tehdasasetukset, jotta voit käyttää tätä laitetta rajoituksitta"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Lue lisätietoja koskettamalla."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ei ole käytössä."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 528f2f3a1c6f..7446796794dc 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Redimensionner"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Toujours afficher"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Réactivez ce mode en accédant à Paramètres système &gt; Applications &gt; Téléchargements"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas compatible avec le paramètre de taille d\'affichage actuel et peut se comporter de manière inattendue."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Toujours afficher"</string>
<string name="smv_application" msgid="3307209192155442829">"L\'application <xliff:g id="APPLICATION">%1$s</xliff:g> (du processus <xliff:g id="PROCESS">%2$s</xliff:g>) a enfreint ses propres règles du mode strict."</string>
<string name="smv_process" msgid="5120397012047462446">"Le processus <xliff:g id="PROCESS">%1$s</xliff:g> a enfreint ses propres règles du mode strict."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Mise à jour d\'Android…"</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Annuler l\'épinglage"</string>
<string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Redémarrer la séance"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Touchez ici pour démarrer une nouvelle séance de démonstration"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Démarrage de la démonstration en cours..."</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Redémarrage de la séance en cours..."</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Rétablissez la configuration d\'usine de cet appareil pour l\'utiliser sans restrictions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touchez ici pour en savoir plus."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Désactivé : <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 55606ce3453d..ed7b14339bf5 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Mise à l\'échelle"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Toujours afficher"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Réactivez ce mode en accédant à Paramètres système &gt; Applications &gt; Téléchargements"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> n\'est pas compatible avec le paramètre de taille d\'affichage actuel et peut présenter un comportement inattendu."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Toujours afficher"</string>
<string name="smv_application" msgid="3307209192155442829">"L\'application <xliff:g id="APPLICATION">%1$s</xliff:g> (du processus <xliff:g id="PROCESS">%2$s</xliff:g>) a enfreint ses propres règles du mode strict."</string>
<string name="smv_process" msgid="5120397012047462446">"Le processus <xliff:g id="PROCESS">%1$s</xliff:g> a enfreint ses propres règles du mode strict."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Mise à jour d\'Android…"</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Retirer"</string>
<string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string>
<string name="negative_duration" msgid="5688706061127375131">"− <xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Redémarrer la session"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Appuyer pour lancer une nouvelle session de démonstration"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Lancement de la démo…"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Redémarrage de la session"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Rétablir la configuration d\'usine pour utiliser cet appareil sans restrictions"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Appuyez ici pour en savoir plus."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Élément \"<xliff:g id="LABEL">%1$s</xliff:g>\" désactivé"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index f09eafbd7144..8b1b06d6851d 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Escala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Mostrar sempre"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Volve activar esta función en Configuración do sistema &gt; Aplicacións &gt; Descargadas."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> non admite a configuración do tamaño de pantalla actual e quizais presente un comportamento inesperado."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mostrar sempre"</string>
<string name="smv_application" msgid="3307209192155442829">"A aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> (proceso <xliff:g id="PROCESS">%2$s</xliff:g>) infrinxiu a súa política StrictMode autoaplicada."</string>
<string name="smv_process" msgid="5120397012047462446">"O proceso <xliff:g id="PROCESS">%1$s</xliff:g> infrinxiu a política StrictMode de aplicación automática."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Estase actualizando Android…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Permite que unha aplicación consulte as sesións de instalación. Desta forma, pode ver os detalles acerca das instalacións de paquetes activas."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"solicitar instalación de paquetes"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Permite a unha aplicación solicitar a instalación dos paquetes."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Toca dúas veces para controlar o zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Non se puido engadir o widget."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Ir"</string>
<string name="ime_action_search" msgid="658110271822807811">"Buscar"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Servizo de clasificación de notificacións"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> activou a VPN"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"Toca aquí para xestionar a rede."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toca aquí para xestionar a rede."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sempre activada conectándose..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre activada conectada"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro na VPN sempre activada"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Soltar"</string>
<string name="app_info" msgid="6856026610594615344">"Información da aplicación"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Reiniciar sesión"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Toca para iniciar unha nova sesión de demostración"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Iniciando demostración"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Reiniciando sesión"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Restablecemento dos valores de fábrica para usar este dispositivo sen restricións"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para acceder a máis información"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Desactivouse <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 1970d3c30ce8..3666e0a5e152 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"સ્કેલ"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"હંમેશા બતાવો"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"આને સિસ્ટમ સેટિંગ્સ &gt; ઍપ્લિકેશનો &gt; ડાઉનલોડ કરેલમાં ફરીથી સક્ષમ કરો."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> વર્તમાન પ્રદર્શન કદની સેટિંગનું સમર્થન કરતું નથી અને અનપેક્ષિત રીતે વર્તી શકે છે."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"હંમેશાં બતાવો"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> ઍપ્લિકેશન (<xliff:g id="PROCESS">%2$s</xliff:g> પ્રક્રિયા)એ તેની સ્વ-લાગુ કરેલ StrictMode નીતિનું ઉલ્લંઘન કર્યું છે."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> પ્રક્રિયાએ તેની સ્વ-લાગુ કરેલ StrictMode નીતિનું ઉલ્લંઘન કર્યું છે."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android અપગ્રેડ થઈ રહ્યું છે..."</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"એપ્લિકેશનને ઇન્સ્ટોલ સત્રોને વાંચવાની મંજૂરી આપે છે. આ તેને સક્રિય પૅકેજ ઇન્સ્ટોલેશન્સ વિશે વિગતો જોવાની મંજૂરી આપે છે."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"પૅકેજેસ ઇન્સ્ટૉલ કરવાની વિનંતી કરો"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"એપ્લિકેશનને પૅકેજેસના ઇન્સ્ટોલેશનની વિનંતી કરવાની મંજૂરી આપો."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ઝૂમ નિયંત્રણ માટે બેવાર ટૅપ કરો"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"વિજેટ ઉમેરી શકાયું નથી."</string>
<string name="ime_action_go" msgid="8320845651737369027">"જાઓ"</string>
<string name="ime_action_search" msgid="658110271822807811">"શોધો"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"સૂચના રેંકર સેવા"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN સક્રિય કર્યું"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> દ્વારા VPN સક્રિય થયું"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"નેટવર્કને સંચાલિત કરવા માટે ટૅપ કરો."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> થી કનેક્ટ થયાં. નેટવર્કને સંચાલિત કરવા માટે ટૅપ કરો."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"હંમેશા-ચાલુ VPN કનેક્ટ થઈ રહ્યું છે…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"હંમેશા-ચાલુ VPN કનેક્ટ થયું"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"હંમેશાં ચાલુ VPN ભૂલ"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"અનપિન કરો"</string>
<string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"સત્ર પુનઃપ્રારંભ કરો"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"નવું ડેમો સત્ર પ્રારંભ કરવા માટે ટૅપ કરો"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"ડેમો પુનઃપ્રારંભ કરી રહ્યાં છે"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"સત્ર પુનઃપ્રારંભ કરી રહ્યાં છે"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"આ ઉપકરણનો પ્રતિબંધો વિના ઉપયોગ કરવા માટે ફેક્ટરી રીસેટ કરો"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"વધુ જાણવા માટે ટચ કરો."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> અક્ષમ કર્યું"</string>
diff --git a/core/res/res/values-hi-watch/styles_material.xml b/core/res/res/values-hi-watch/styles_material.xml
new file mode 100644
index 000000000000..36a459dc16a0
--- /dev/null
+++ b/core/res/res/values-hi-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 147e6778b2d5..ff971b556013 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"स्केल"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"हमेशा दिखाएं"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"इसे सिस्‍टम सेटिंग &gt; Apps &gt; डाउनलोड किए गए में पुन: सक्षम करें."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> वर्तमान स्क्रीन के आकार की सेटिंग का समर्थन नहीं करता है और अनपेक्षित रूप से व्यवहार कर सकता है."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"हमेशा दिखाएं"</string>
<string name="smv_application" msgid="3307209192155442829">"ऐप्स <xliff:g id="APPLICATION">%1$s</xliff:g> (प्रक्रिया <xliff:g id="PROCESS">%2$s</xliff:g>) ने उसकी स्‍वयं लागू होने वाली StrictMode नीति का उल्‍लंघन किया है."</string>
<string name="smv_process" msgid="5120397012047462446">"प्रक्रिया <xliff:g id="PROCESS">%1$s</xliff:g> ने उसकी स्‍व-प्रवर्तित StrictMode नीति का उल्‍लंघन किया है."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android अपग्रेड हो रहा है..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"अनपिन करें"</string>
<string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"सत्र पुन: प्रारंभ करें"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"एक नया डेमो सत्र प्रारंभ करने के लिए टैप करें"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"डेमो प्रारंभ हो रहा है"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"सत्र पुन: प्रारंभ हो रहा है"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"इस डिवाइस को प्रतिबंधों के बिना उपयोग करने के लिए फ़ैक्टरी रीसेट करें"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"अधिक जानने के लिए स्पर्श करें."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"अक्षम <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index d1752c69518c..a2bc46a18aca 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1038,6 +1038,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Mjerilo"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Uvijek prikaži"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Omogućiti to ponovo u Postavkama sustava &gt; Aplikacije &gt; Preuzimanja."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> ne podržava trenutačnu postavku veličine zaslona i može se ponašati neočekivano."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Uvijek prikaži"</string>
<string name="smv_application" msgid="3307209192155442829">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) prekršila je vlastito pravilo StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> prekršio je svoje vlastito pravilo StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android se nadograđuje…"</string>
@@ -1685,10 +1687,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Otkvači"</string>
<string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Ponovno pokretanje sesije"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Dodirnite za pokretanje nove demo-sesije"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Pokretanje demonstracije"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Ponovno pokretanje sesije"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Uređaj je vraćen na tvorničke postavke da biste ga mogli upotrebljavati bez ograničenja"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da biste saznali više."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – onemogućeno"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 73dc3c79fa81..aec5a3dc4ecf 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skála"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Mindig megjelenik"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Újbóli engedélyezés itt: Rendszerbeállítások &gt; Alkalmazások &gt; Letöltve."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás nem támogatja a képernyőméret jelenlegi beállításait, ezért nem várt módon viselkedhet."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mindig megjelenik"</string>
<string name="smv_application" msgid="3307209192155442829">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazás (<xliff:g id="PROCESS">%2$s</xliff:g> folyamat) megsértette az általa kényszerített Szigorú üzemmód irányelvet."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> folyamat megsértette az általa kényszerített Szigorú üzemmód irányelvet."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android frissítése folyamatban..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Feloldás"</string>
<string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Munkamenet újraindítása"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Koppintson az új, bemutató munkamenet indításához"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Bemutató indítása"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Munkamenet újraindítása"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Állítsa vissza a gyári beállításokat az eszköz korlátozások nélküli használata érdekében"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Érintse meg a további információkért."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"A(z) <xliff:g id="LABEL">%1$s</xliff:g> letiltva"</string>
diff --git a/core/res/res/values-hy-rAM-watch/styles_material.xml b/core/res/res/values-hy-rAM-watch/styles_material.xml
new file mode 100644
index 000000000000..36a459dc16a0
--- /dev/null
+++ b/core/res/res/values-hy-rAM-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index d9aac5a5d105..c95e25afc338 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Աստիճանակարգել"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Միշտ ցույց տալ"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Կրկին ակտիվացնել սա Համակարգի կարգավորումներում &amp;gt Ծրագրեր &gt; Ներբեռնումներ:"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը չի աջակցում Էկրանի չափի ընթացիկ կարգավորումները, ինչի պատճառով կարող են խնդիրներ առաջանալ:"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Միշտ ցուցադրել"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> ծրագիրը (գործընթաց <xliff:g id="PROCESS">%2$s</xliff:g>) խախտել է իր ինքնահարկադրված Խիստ ռեժիմ քաղաքականությունը:"</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> գործընթացը խախտել է իր ինքնահարկադրված Խիստ ռեժիմ քաղաքականությունը:"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android-ը նորացվում է..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Ապամրացնել"</string>
<string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Վերագործարկել աշխատաշրջանը"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Հպեք՝ նոր ցուցադրական աշխատաշրջան սկսելու համար"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Ցուցադրական օգտվողի գործարկում"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Աշխատաշրջանի վերագործարկում"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Սարքն առանց սահմանափակումների օգտագործելու համար կատարեք գործարանային վերակայում"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Հպեք՝ ավելին իմանալու համար:"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Անջատած <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 74efb2d7808f..e92680859b35 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Selalu tampilkan"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Aktifkan kembali dialog ini di Setelan sistem &gt; Apl &gt; Terunduh."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak mendukung setelan Ukuran layar saat ini dan dapat menunjukkan perilaku yang tak diharapkan."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Selalu tampilkan"</string>
<string name="smv_application" msgid="3307209192155442829">"Apl <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) telah melanggar kebijakan StrictMode yang diberlakukannya sendiri."</string>
<string name="smv_process" msgid="5120397012047462446">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> telah melanggar kebijakan StrictMode yang diberlakukan secara otomatis."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android sedang meningkatkan versi..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Lepas pin"</string>
<string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Mulai Ulang Sesi"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Ketuk untuk memulai sesi demo baru"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Memulai demo"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Memulai ulang sesi"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Dikembalikan ke setelan pabrik agar perangkat ini dapat digunakan tanpa batasan"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sentuh untuk mempelajari lebih lanjut."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> dinonaktifkan"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 25f921127c84..8964ecdf57ab 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Breyta stærð"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Sýna alltaf"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Þú getur kveikt aftur á þessu undir Kerfisstillingar &gt; Forrit &gt; Sótt."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> styður ekki núverandi skjástærðarstillingu og gæti því ekki virkað sem skyldi."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Sýna alltaf"</string>
<string name="smv_application" msgid="3307209192155442829">"Forritið <xliff:g id="APPLICATION">%1$s</xliff:g> (ferli <xliff:g id="PROCESS">%2$s</xliff:g>) hefur brotið gegn eigin StrictMode-stefnu."</string>
<string name="smv_process" msgid="5120397012047462446">"Forritið <xliff:g id="PROCESS">%1$s</xliff:g> braut gegn eigin StrictMode-stefnu."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android er að uppfæra…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Leyfir forriti að lesa uppsetningarlotur. Þetta gerir því kleift að sjá upplýsingar um virkar pakkauppsetningar."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"fara fram á uppsetningu pakka"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Leyfir forriti að fara fram á uppsetningu pakka."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ýttu tvisvar til að opna aðdráttarstýringar"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Ekki tókst að bæta græju við."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Áfram"</string>
<string name="ime_action_search" msgid="658110271822807811">"Leita"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Tilkynningaröðun"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN virkjað"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN er virkjað með <xliff:g id="APP">%s</xliff:g>"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"Ýttu til að hafa umsjón með netkerfi"</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"Tengt við <xliff:g id="SESSION">%s</xliff:g>. Ýttu til að hafa umsjón með netinu."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Sívirkt VPN tengist…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Sívirkt VPN tengt"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Villa í sívirku VPN"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Losa"</string>
<string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Endurræsa lotu"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Ýttu til að hefja nýja tilraunalotu"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Byrjar kynningu"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Endurræsir lotu"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Núllstilltu til að nota þetta tæki án takmarkana"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Snertu til að fá frekari upplýsingar."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Slökkt <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 8318d45dd500..e0c68c10ee04 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Scala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Mostra sempre"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Riattivala in Impostazioni di sistema &gt; Applicazioni &gt; Scaricate."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> non supporta le dimensioni di visualizzazione attualmente impostate e potrebbe comportarsi in modo imprevisto."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mostra sempre"</string>
<string name="smv_application" msgid="3307209192155442829">"L\'applicazione <xliff:g id="APPLICATION">%1$s</xliff:g> (processo <xliff:g id="PROCESS">%2$s</xliff:g>) ha violato la norma StrictMode autoimposta."</string>
<string name="smv_process" msgid="5120397012047462446">"Il processo <xliff:g id="PROCESS">%1$s</xliff:g> ha violato la norma StrictMode autoimposta."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Aggiornamento di Android..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Sblocca"</string>
<string name="app_info" msgid="6856026610594615344">"Informazioni app"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Riavvia la sessione"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Tocca per iniziare una nuova sessione demo"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Avvio della demo in corso"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Riavvio della sessione in corso"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Esegui il ripristino dei dati di fabbrica per utilizzare il dispositivo senza limitazioni"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tocca per ulteriori informazioni."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Widget <xliff:g id="LABEL">%1$s</xliff:g> disattivato"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index c1f5246a4618..dd732bebafd0 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1061,6 +1061,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"שינוי קנה-מידה"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"הצג תמיד"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"‏אפשר תכונה זו מחדש ב\'הגדרות מערכת\' &lt;‏ Google Apps‏ &lt; \'הורדות\'."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> אינו תומך בהגדרת הגודל הנוכחית של התצוגה, והתנהגותו עשויה להיות בלתי צפויה."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"הצג תמיד"</string>
<string name="smv_application" msgid="3307209192155442829">"‏האפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> (תהליך <xliff:g id="PROCESS">%2$s</xliff:g>) הפר את מדיניות StrictMode באכיפה עצמית שלו."</string>
<string name="smv_process" msgid="5120397012047462446">"‏התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הפר את מדיניות StrictMode באכיפה עצמית."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"‏Android מבצע שדרוג…"</string>
@@ -1721,10 +1723,22 @@
<string name="unpin_target" msgid="3556545602439143442">"בטל הצמדה"</string>
<string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"הפעלה מחדש"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"הקש כדי להפעיל הדגמה חדשה"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"מתחיל בהדגמה"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"מפעיל מחדש"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"איפוס להגדרות היצרן כדי לאפשר שימוש במכשיר ללא מגבלות"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"גע לקבלת מידע נוסף."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> הושבת"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 99e88d1c376f..3ec210995899 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"スケール"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"常に表示"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"[システム設定]&gt;[アプリ]&gt;[ダウンロード済み]で再度有効にします。"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」は現在の [表示サイズ] 設定に対応していないため、予期しない動作が発生するおそれがあります。"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"常に表示"</string>
<string name="smv_application" msgid="3307209192155442829">"アプリ「<xliff:g id="APPLICATION">%1$s</xliff:g>」(プロセス「<xliff:g id="PROCESS">%2$s</xliff:g>」)でStrictModeポリシー違反がありました。"</string>
<string name="smv_process" msgid="5120397012047462446">"プロセス<xliff:g id="PROCESS">%1$s</xliff:g>でStrictModeポリシー違反がありました。"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Androidをアップグレードしています..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"固定を解除"</string>
<string name="app_info" msgid="6856026610594615344">"アプリ情報"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"新しいセッションの開始"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"新しいデモセッションを開始するにはタップ"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"デモを開始しています"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"新しいセッションを開始しています"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"制限なしでこの端末を使用するには初期状態にリセットしてください"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"タップして詳細をご確認ください。"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"停止済みの「<xliff:g id="LABEL">%1$s</xliff:g>」"</string>
diff --git a/core/res/res/values-ka-rGE-watch/styles_material.xml b/core/res/res/values-ka-rGE-watch/styles_material.xml
new file mode 100644
index 000000000000..36a459dc16a0
--- /dev/null
+++ b/core/res/res/values-ka-rGE-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 0c7c42da4204..0ee74e9d2221 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"მასშტაბი"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"ყოველთვის ჩვენება"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"ხელახალი გააქტიურება განყოფილებაში: სისტემის პარამეტრები &gt; აპები &gt; ჩამოტვირთულები."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ის მიერ ეკრანის ამჟამინდელი პარამეტრები მხარდაუჭერელია და შეიძლება არასათანადოდ იმუშაოს."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"ყოველთვის ჩვენება"</string>
<string name="smv_application" msgid="3307209192155442829">"აპმა <xliff:g id="APPLICATION">%1$s</xliff:g> (პროცესი <xliff:g id="PROCESS">%2$s</xliff:g>) დაარღვია საკუთარი StrictMode დებულება."</string>
<string name="smv_process" msgid="5120397012047462446">"ამ პროცესმა <xliff:g id="PROCESS">%1$s</xliff:g> დააზიანა საკუთარი StrictMode დებულება."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android ახალ ვერსიაზე გადადის…"</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"ჩამაგრების მოხსნა"</string>
<string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"სესიის ხელახლა დაწყება"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"შეეხეთ ახალი სადემონსტრაციო სესიის დასაწყებად"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"მიმდინარეობს დემონსტრაციის დაწყება"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"მიმდინარეობს სესიის ხელახლა დაწყება"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"ამ მოწყობილობის შეზღუდვების გარეშე გამოსაყენებლად, დააბრუნეთ ქარხნული პარამეტრები"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"შეეხეთ მეტის გასაგებად."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"გათიშული <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-kk-rKZ-watch/styles_material.xml b/core/res/res/values-kk-rKZ-watch/styles_material.xml
new file mode 100644
index 000000000000..36a459dc16a0
--- /dev/null
+++ b/core/res/res/values-kk-rKZ-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 3f8ee0587b3d..7e34e8472899 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Меже"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Үнемі көрсету"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Мұны «Жүйелік параметрлер» &gt; «Қолданбалар» &gt; «Жүктелгендер» тармағында қосыңыз."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасында \"Дисплей өлшемі\" параметрінің таңдалған мәніне қолдау көрсетілмейді, сондықтан дұрыс жұмыс істемеуі мүмкін."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Үнемі көрсету"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасы (<xliff:g id="PROCESS">%2$s</xliff:g> процесі) өзі қолданған StrictMode саясатын бұзды."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> үрдісі өздігінен күшіне енген ҚатаңРежим ережесін бұзды."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android жаңартылуда…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Қолданбаға орнату сеанстарын оқуға рұқсат етеді. Бұл оған белсенді бума орнатулары туралы мәліметтерді көруге рұқсат етеді."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"орнату бумаларын сұрау"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Қолданбаның бумаларды орнатуға рұқсат сұрауына мүмкіндік береді."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Масштабтау параметрін басқару үшін екі рет түртіңіз"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Виджетті қосу."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Өту"</string>
<string name="ime_action_search" msgid="658110271822807811">"Іздеу"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Хабарландыруларды жіктеу қызметі"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN белсенді"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"ВЖЭ <xliff:g id="APP">%s</xliff:g> арқылы қосылған"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"Желіні басқару үшін түртіңіз"</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> жүйесіне жалғанған. Желіні басқару үшін түріңіз."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Әрқашан қосылған ВЖЖ жалғануда…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Әрқашан қосылған ВЖЖ жалғанған"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Әрқашан қосылған ВЖЖ қателігі"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Босату"</string>
<string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Сеансты қайта бастау"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Жаңа демо сеансты бастау үшін түртіңіз"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Демо нұсқасын бастау"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Сеансты қайта бастау"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Осы құрылғыны шектеусіз пайдалану үшін зауыттық параметрлерді қалпына келтіріңіз"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Қосымша мәліметтер алу үшін түртіңіз."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> өшірулі"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index aa7b35a11efe..4deaa4118b49 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1017,6 +1017,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"មាត្រដ្ឋាន"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"បង្ហាញ​ជា​និច្ច"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"បើក​វា​ឡើងវិញ​ក្នុង​ការ​កំណត់​ប្រព័ន្ធ &gt; កម្មវិធី &gt; ទាញ​យក។"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> មិនគាំទ្រការកំណត់ទំហំនៃការបង្ហាញបច្ចុប្បន្ន និងអាចមានសកម្មភាពខុសពីការរំពឹងទុក។"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"បង្ហាញ​ជា​និច្ច"</string>
<string name="smv_application" msgid="3307209192155442829">"កម្មវិធី <xliff:g id="APPLICATION">%1$s</xliff:g> (ដំណើរការ <xliff:g id="PROCESS">%2$s</xliff:g>) បាន​បំពាន​គោលនយោបាយ​របៀប​តឹងរ៉ឹង​អនុវត្ត​ដោយ​ខ្លួន​​ឯង។"</string>
<string name="smv_process" msgid="5120397012047462446">"ដំណើរការ <xliff:g id="PROCESS">%1$s</xliff:g> បាន​បំពាន​គោលនយោបាយ​​របៀប​​តឹង​រឹង​​​បង្ខំ​ដោយ​ខ្លួន​ឯង"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android កំពុង​ធ្វើ​បច្ចុប្បន្នភាព..."</string>
@@ -1651,10 +1653,22 @@
<string name="unpin_target" msgid="3556545602439143442">"មិនខ្ទាស់"</string>
<string name="app_info" msgid="6856026610594615344">"ព័ត៌មាន​កម្មវិធី"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"ចាប់ផ្តើមវេនម្តងទៀត"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"ប៉ះដើម្បីចាប់ផ្តើមវេនបង្ហាញសាកល្បងថ្មី"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"កំពុងចាប់ផ្តើមការបង្ហាញសាកល្បង"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"ចាប់ផ្តើមវេនសារជាថ្មី"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"កំណត់ដូចចេញពីរោងចក្រឡើងវិញដើម្បីប្រើឧបករណ៍នេះដោយគ្មានការរឹតបន្តឹង"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ប៉ះ​ ដើម្បី​​ស្វែងយល់​បន្ថែម។"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ដែលបានបិទដំណើរការ"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index d5e8fa2afb29..24307591d62e 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"ಮಾಪಕ"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"ಯಾವಾಗಲೂ ತೋರಿಸಿ"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"ಸಿಸ್ಟಂ ಸೆಟ್ಟಿಂಗ್‌ಗಳು &gt; ಅಪ್ಲಿಕೇಶನ್‌ಗಳು &gt; ಡೌನ್‌ಲೋಡ್‌ ಆಗಿರುವುದರಲ್ಲಿ ಇದನ್ನು ಮರು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಪ್ರಸ್ತುತ ಪ್ರದರ್ಶನ ಗಾತ್ರದ ಸೆಟ್ಟಿಂಗ್‌ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ ಮತ್ತು ಅನಿರೀಕ್ಷಿತವಾಗಿ ವರ್ತಿಸಬಹುದು."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"ಯಾವಾಗಲೂ ತೋರಿಸು"</string>
<string name="smv_application" msgid="3307209192155442829">"ಅಪ್ಲಿಕೇಶನ್‌‌ <xliff:g id="APPLICATION">%1$s</xliff:g> (ಪ್ರಕ್ರಿಯೆಯು <xliff:g id="PROCESS">%2$s</xliff:g>) ತನ್ನ ಸ್ವಯಂ-ಜಾರಿ ಕಠಿಣ ಮೋಡ್ ನೀತಿಯನ್ನು ಉಲ್ಲಂಘನೆ ಮಾಡಿದೆ."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> ಪ್ರಕ್ರಿಯೆಯು ತನ್ನ ಸ್ವಯಂ-ಜಾರಿ ಕಠಿಣ ಮೋಡ್ ನೀತಿಯನ್ನು ಉಲ್ಲಂಘನೆ ಮಾಡಿದೆ."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android ಅಪ್‌ಗ್ರೇಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ಸ್ಥಾಪಿತ ಸೆಷನ್‌ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ. ಸಕ್ರಿಯ ಪ್ಯಾಕೇಜ್‌ ಸ್ಥಾಪನೆಗಳ ಕುರಿತು ವಿವರಣೆಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಇದು ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ಸ್ಥಾಪನೆ ಪ್ಯಾಕೇಜ್‌ಗಳನ್ನು ವಿನಂತಿಸಿ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ಪ್ಯಾಕೇಜ್‌ಗಳ ಸ್ಥಾಪನೆಯನ್ನು ವಿನಂತಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ಝೂಮ್‌ ನಿಯಂತ್ರಿಸಲು ಎರಡು ಬಾರಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ವಿಜೆಟ್ ಸೇರಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string>
<string name="ime_action_go" msgid="8320845651737369027">"ಹೋಗು"</string>
<string name="ime_action_search" msgid="658110271822807811">"ಹುಡುಕು"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"ಅಧಿಸೂಚನೆ ಶ್ರೇಣಿಯ ಸೇವೆ"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ಮೂಲಕ VPN ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"ನೆಟ್‍ವರ್ಕ್ ನಿರ್ವಹಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ. ನೆಟ್‍ವರ್ಕ್ ನಿರ್ವಹಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ಯಾವಾಗಲೂ-ಆನ್ VPN ಸಂಪರ್ಕಗೊಳ್ಳುತ್ತಿದೆ…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"ಯಾವಾಗಲೂ-ಆನ್ VPN ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"ಯಾವಾಗಲೂ-ಆನ್ VPN ದೋಷ"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"ಅನ್‌ಪಿನ್"</string>
<string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"ಸೆಶನ್ ಮರುಪ್ರಾರಂಭಿಸಿ"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"ಹೊಸ ಡೆಮೊ ಸೆಶನ್ ಪ್ರಾರಂಭಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"ಡೆಮೋ ಪ್ರಾರಂಭವಾಗುತ್ತಿದೆ"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"ಸೆಶನ್ ಮರುಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"ನಿರ್ಬಂಧಗಳು ಇಲ್ಲದೆಯೇ ಈ ಸಾಧನವನ್ನು ಬಳಸಲು ಫ್ಯಾಕ್ಟರಿ ಮರುಹೊಂದಿಸಿ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಸ್ಪರ್ಶಿಸಿ."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
diff --git a/core/res/res/values-ko-watch/styles_material.xml b/core/res/res/values-ko-watch/styles_material.xml
index 0755eac374ea..36a459dc16a0 100644
--- a/core/res/res/values-ko-watch/styles_material.xml
+++ b/core/res/res/values-ko-watch/styles_material.xml
@@ -31,5 +31,5 @@ please see styles_device_defaults.xml.
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"후보"</font></string>
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 1c165f941338..c0e3819948c7 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"배율"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"항상 표시"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"시스템 설정 &gt; 앱 &gt; 다운로드로 이동하여 이 모드를 다시 사용하도록 설정합니다."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱은 현재 디스플레이 크기 설정을 지원하지 않으며 예기치 않게 동작할 수 있습니다."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"항상 표시"</string>
<string name="smv_application" msgid="3307209192155442829">"앱 <xliff:g id="APPLICATION">%1$s</xliff:g>(프로세스 <xliff:g id="PROCESS">%2$s</xliff:g>)이(가) 자체 시행 StrictMode 정책을 위반했습니다."</string>
<string name="smv_process" msgid="5120397012047462446">"프로세스(<xliff:g id="PROCESS">%1$s</xliff:g>)가 자체 시행 StrictMode 정책을 위반했습니다."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android 업그레이드 중.."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"고정 해제"</string>
<string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"세션 다시 시작"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"탭하여 새로운 데모 세션 시작"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"데모 시작 중"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"세션 다시 시작 중"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"제한 없이 기기를 사용하기 위한 초기화"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"자세한 내용을 보려면 터치하세요."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> 사용 중지됨"</string>
diff --git a/core/res/res/values-ky-rKG-watch/styles_material.xml b/core/res/res/values-ky-rKG-watch/styles_material.xml
new file mode 100644
index 000000000000..36a459dc16a0
--- /dev/null
+++ b/core/res/res/values-ky-rKG-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index ada25dc72c1b..3035bbce6e21 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Шкала"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Ар дайым көрсөтүлсүн"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Муну тутум жөндөөлөрүнөн кайра иштетүү &gt; Колдонмолор &gt; Жүктөлүп алынган."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу көрүнүштүн тандалган өлчөмүн экранда көрсөтө албайт жана туура эмес иштеши мүмкүн."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Ар дайым көрсөтүлсүн"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу (<xliff:g id="PROCESS">%2$s</xliff:g> процесси) өз алдынча иштеткен StrictMode саясатын бузду."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> процесси өзүнүн мажбурланган StrictMode саясатын бузуп койду."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android жаңыртылууда…"</string>
@@ -1652,10 +1654,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Кадоодон алып коюу"</string>
<string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Сеансты кайра баштоо"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Жаңы демо сеансын баштоо үчүн таптап коюңуз"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Демо башталууда"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Сеанс кайра башталууда"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Бул түзмөктү чектөөсүз колдонуу үчүн аны баштапкы абалга келтириңиз"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Көбүрөөк билүү үчүн тийип коюңуз."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> өчүрүлдү"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index b003764264da..67da53f21478 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"ຂະໜາດ"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"ສະແດງຕະຫຼອດເວລາ"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"ເປີດການເຮັດວຽກນີ້ຄືນໄດ້ໃນ ການຕັ້ງຄ່າລະບົບ &gt; ແອັບຯ &gt; ດາວໂຫລດແລ້ວ"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ່ຮອງຮັບການຕັ້ງຄ່າຂະໜາດສະແດງຜົນປັດຈຸບັນ ແລະ ອາດມີຄວາມຜິດພາດໄດ້."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"ສະແດງທຸກເທື່ອ"</string>
<string name="smv_application" msgid="3307209192155442829">"ແອັບຯ <xliff:g id="APPLICATION">%1$s</xliff:g> (ໂປຣເຊສ <xliff:g id="PROCESS">%2$s</xliff:g>) ໄດ້ລະເມີດນະໂຍບາຍ StrictMode ທີ່ບັງຄັບໃຊ້ດ້ວຍໂຕເອງ."</string>
<string name="smv_process" msgid="5120397012047462446">"ໂປຣເຊສ <xliff:g id="PROCESS">%1$s</xliff:g> ລະເມີດນະໂຍບາຍບັງຄັບໃຊ້ເອງ StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"ກຳລັງອັບເກຣດ Android..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"ຖອນປັກໝຸດ"</string>
<string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"ເລີ່ມເຊດຊັນຄືນໃໝ່"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"ແຕະເພື່ອເລີ່ມເຊດຊັນເດໂມໃໝ່"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"ກຳລັງເລີ່ມເດໂມ"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"ເລີ່ມເຊດຊັນໃໝ່"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"ຣີເຊັດໃຫ້ເປັນຄ່າໂຮງງານເພື່ອໃຊ້ອຸປະກອນນີ້ໂດຍບໍ່ມີຂໍ້ຈຳກັດ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ປິດການນຳໃຊ້ <xliff:g id="LABEL">%1$s</xliff:g> ແລ້ວ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 0e4c1d698a28..a78482d711ae 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1061,6 +1061,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Mastelis"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Visada rodyti"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Įgalinkite jį iš naujo nuėję į „Sistemos nustatymai“ &gt; „Programos“ &gt; „Atsisiųsta“."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"Programoje „<xliff:g id="APP_NAME">%1$s</xliff:g>“ nepalaikomas dabartinis ekrano dydžio nustatymas ir ji gali netinkamai veikti."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Visada rodyti"</string>
<string name="smv_application" msgid="3307209192155442829">"Programa „<xliff:g id="APPLICATION">%1$s</xliff:g>“ (procesas „<xliff:g id="PROCESS">%2$s</xliff:g>“) pažeidė savo vykdomą „StrictMode“ politiką."</string>
<string name="smv_process" msgid="5120397012047462446">"„<xliff:g id="PROCESS">%1$s</xliff:g>“ procesas pažeidė savo vykdomą „StrictMode“ politiką."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"„Android“ naujovinama..."</string>
@@ -1721,10 +1723,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Atsegti"</string>
<string name="app_info" msgid="6856026610594615344">"Programos informacija"</string>
<string name="negative_duration" msgid="5688706061127375131">"–<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Paleisti sesiją iš naujo"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Palieskite, kad pradėtumėte naują demonstracinės versijos sesiją"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Paleidžiama demonstracinė versija"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Seansas paleidžiamas iš naujo"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Atkurkite gamyklinius nustatymus, kad galėtumėte naudoti šį įrenginį be apribojimų"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Palieskite, kad sužinotumėte daugiau."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Išj. valdiklis „<xliff:g id="LABEL">%1$s</xliff:g>“"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 5b91848be619..de9aa505d0b5 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1038,6 +1038,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Mērogs"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Rādīt vienmēr"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Atkārtoti iespējojiet šeit: Sistēmas iestatījumi &gt; Lietotnes &gt; Lejupielādētās."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"Lietotnē <xliff:g id="APP_NAME">%1$s</xliff:g> netiek atbalstīts pašreizējais displeja lieluma iestatījums, tādēļ tā var tikt attēlota neparedzētā veidā."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Rādīt vienmēr"</string>
<string name="smv_application" msgid="3307209192155442829">"Lietotne <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) ir pārkāpusi savu pašieviesto StrictMode politiku."</string>
<string name="smv_process" msgid="5120397012047462446">"Process <xliff:g id="PROCESS">%1$s</xliff:g> ir pārkāpis savu pašieviesto StrictMode politiku."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Notiek Android jaunināšana..."</string>
@@ -1685,10 +1687,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Atspraust"</string>
<string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Atkārtoti palaidiet sesiju"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Pieskarieties, lai sāktu jaunu demonstrācijas sesiju."</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Demonstrācijas startēšana"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Sesijas restartēšana"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Rūpnīcas datu atiestatīšana ierīces neierobežotai izmantošanai"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Pieskarieties, lai uzzinātu vairāk."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> atspējots"</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 010958fda6c4..93ae4fb373a9 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Размер"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Покажи секогаш"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Повторно овозможете го ова во Системски поставки &gt; Апликации &gt; Преземено."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> не ја поддржува тековната поставка за големина на екранот и може да се однесува непредвидено."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Секогаш прикажувај"</string>
<string name="smv_application" msgid="3307209192155442829">"Апликацијата <xliff:g id="APPLICATION">%1$s</xliff:g> (процес <xliff:g id="PROCESS">%2$s</xliff:g>) ја прекрши политиката StrictMode што си ја наметна врз себеси."</string>
<string name="smv_process" msgid="5120397012047462446">"Процесот <xliff:g id="PROCESS">%1$s</xliff:g> ја прекрши својата самонаметната политика на строг режим."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android се ажурира…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Дозволува апликација да чита сесии на инсталирање. Тоа овозможува апликацијата да гледа детали за активни инсталации на пакет."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"барање пакети за инсталирање"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Дозволува апликацијата да бара инсталација на пакети."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Допрете двапати за контрола на зумот"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Не можеше да се додаде виџет."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Оди"</string>
<string name="ime_action_search" msgid="658110271822807811">"Пребарај"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Услуга за рангирање известувања"</string>
<string name="vpn_title" msgid="19615213552042827">"Активирана VPN"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана со <xliff:g id="APP">%s</xliff:g>"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"Допрете за да управувате со мрежата."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"Поврзани сте на <xliff:g id="SESSION">%s</xliff:g>. Допрете за да управувате со мрежата."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Поврзување со секогаш вклучена VPN..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Поврзани со секогаш вклучена VPN"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Грешка на секогаш вклучена VPN"</string>
@@ -1654,10 +1653,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Откачете"</string>
<string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Започнете сесија одново"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Допрете за да започнете нова демо сесија"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Демото стартува"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Сесијата се рестартира"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Ресетирајте до фабричките поставки за уредов да го користите без ограничувања"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Допрете за да дознаете повеќе."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Оневозможен <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 7120cada82d1..433ef87ef3e5 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"സ്കെയിൽ"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"എപ്പോഴും പ്രദര്‍ശിപ്പിക്കുക"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"സിസ്‌റ്റം ക്രമീകരണങ്ങൾ &gt; അപ്ലിക്കേഷനുകൾ &gt; ഡൗൺലോഡുചെയ്‌തവ എന്നതിൽ ഇത് വീണ്ടും പ്രവർത്തനക്ഷമമാക്കുക."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"നിലവിലെ ഡിസ്പ്ലേ വലുപ്പ ക്രമീകരണത്തെ <xliff:g id="APP_NAME">%1$s</xliff:g> പിന്തുണയ്ക്കുന്നില്ല, അതിനാൽ പ്രതീക്ഷിക്കാത്ത തരത്തിൽ ആപ്പ് പ്രവർത്തിച്ചേക്കാം."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"എല്ലായ്‌പ്പോഴും ദൃശ്യമാക്കുക"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> എന്ന അപ്ലിക്കേഷൻ (<xliff:g id="PROCESS">%2$s</xliff:g> പ്രോസസ്സ്) അതിന്റെ സ്വയം നിർബന്ധിത StrictMode നയം ലംഘിച്ചു."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> എന്ന പ്രോസസ്സ് അതിന്റെ സ്വയം നടപ്പിലാക്കിയ StrictMode നയം ലംഘിച്ചു."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android അപ്ഗ്രേഡുചെയ്യുന്നു…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ഇൻസ്റ്റാൾ ചെയ്‌ത സെഷനുകൾ റീഡുചെയ്യുന്നതിന് ഒരു അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. സജീവ പാക്കേജ് ഇൻസ്റ്റാളേഷനുകളെക്കുറിച്ചുള്ള വിശദാംശങ്ങൾ കാണുന്നതിന് ഇത് അനുവദിക്കുന്നു."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"പാക്കേജുകൾ ഇൻസ്റ്റാൾ ചെയ്യാൻ അഭ്യർത്ഥിക്കുക"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"പാക്കേജുകളുടെ ഇൻസ്റ്റാളേഷൻ അഭ്യർത്ഥിക്കാൻ ഒരു അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"സൂം നിയന്ത്രണം ലഭിക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"വിജറ്റ് ചേർക്കാനായില്ല."</string>
<string name="ime_action_go" msgid="8320845651737369027">"പോവുക"</string>
<string name="ime_action_search" msgid="658110271822807811">"തിരയൽ"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"അറിയിപ്പ് റാങ്കർ സേവനം"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN സജീവമാക്കി"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ഉപയോഗിച്ച് VPN പ്രവർത്തനക്ഷമമാക്കി"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"നെറ്റ്‌വർക്ക് മാനേജുചെയ്യാൻ ടാപ്പുചെയ്യുക"</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> എന്ന സെഷനിലേക്ക് കണക്റ്റുചെയ്തു. നെറ്റ്‌വർക്ക് മാനേജുചെയ്യാൻ ടാപ്പുചെയ്യുക."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"എല്ലായ്‌പ്പോഴും ഓണായിരിക്കുന്ന VPN കണക്റ്റുചെയ്യുന്നു…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"എല്ലായ്‌പ്പോഴും ഓണായിരിക്കുന്ന VPN കണക്റ്റുചെയ്‌തു"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"എല്ലായ്‌പ്പോഴും ഓണായിരിക്കുന്ന VPN പിശക്"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"അൺപിൻ ചെയ്യുക"</string>
<string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"സെഷൻ പുനരാരംഭിക്കുക"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"പുതിയൊരു ഡെമോ സെഷൻ ആരംഭിക്കാൻ ടാപ്പുചെയ്യുക"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"ഡെമോ ആരംഭിക്കുന്നു"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"സെഷൻ പുനരാരംഭിക്കുന്നു"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"നിയന്ത്രണങ്ങൾ ഇല്ലാതെ ഈ ഉപകരണം ഉപയോഗിക്കാൻ ഫാക്ടറി റീസെറ്റ് നടത്തുക"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"കൂടുതലറിയുന്നതിന് സ്‌പർശിക്കുക."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> പ്രവർത്തനരഹിതമാക്കി"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index ae9b7ef335f6..59d21eb654d0 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Цар хэмжээ"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Байнга харуулах"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Энийг Системийн тохиргоо &gt; Апп &gt; Татаж авсан дотроос дахин идэвхтэй болгох боломжтой."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь Дэлгэцийн хэмжээний одоогийн тохиргоог дэмждэггүй учир буруу ажиллаж болзошгүй."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Байнга харуулах"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> апп (<xliff:g id="PROCESS">%2$s</xliff:g> процесс) өөрийнхөө StrictMode бодлогыг зөрчив."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> процесс өөрийнхөө StrictMode бодлогыг зөрчив."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Андройдыг дэвшүүлж байна…"</string>
@@ -1647,10 +1649,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Unpin"</string>
<string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Харилцан үйлдлийг дахин эхлүүлэх"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Демо харилцан үйлдлийг шинээр эхлүүлэхийн тулд товшино уу"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Жишээг эхлүүлж байна"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Харилцан үйлдлийг дахин эхлүүлж байна"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Энэ төхөөрөмжийг хязгаарлалтгүй ашиглахын тулд үйлдвэрийн тохиргоонд дахин тохируулна уу"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Дэлгэрэнгүй үзэх бол дарна уу."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g>-г цуцалсан"</string>
diff --git a/core/res/res/values-mr-rIN-watch/styles_material.xml b/core/res/res/values-mr-rIN-watch/styles_material.xml
index 3c2513eda5dc..36a459dc16a0 100644
--- a/core/res/res/values-mr-rIN-watch/styles_material.xml
+++ b/core/res/res/values-mr-rIN-watch/styles_material.xml
@@ -31,5 +31,5 @@ please see styles_device_defaults.xml.
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"उमेद्वार"</font></string>
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
</resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 233a5295f43f..9b6aad0722ee 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"स्केल"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"नेहमी दर्शवा"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"सिस्टीम सेटिंग्ज &gt; Apps &gt; डाउनलोड केलेले मध्ये हे पुन्हा-सक्षम करा."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> वर्तमान प्रदर्शन आकार सेटिंगला समर्थन देत नाही आणि अनपेक्षित वर्तन करू शकते."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"नेहमी दर्शवा"</string>
<string name="smv_application" msgid="3307209192155442829">"अॅप <xliff:g id="APPLICATION">%1$s</xliff:g> (प्रक्रिया <xliff:g id="PROCESS">%2$s</xliff:g>) ने तिच्या स्वयं-लागू केलेल्या StrictMode धोरणाचे उल्लंघन केले आहे."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> प्रक्रियेने तिच्या स्वतः-लागू केलेल्या StrictMode धोरणाचे उल्लंघन केले."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android श्रेणीसुधारित होत आहे..."</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"अनुप्रयोगास स्‍थापना सत्र वाचण्‍याची अनुमती देते. हे सक्रिय पॅकेज स्‍थापनांविषयी तपशील पाहाण्‍याची यास अनुमती देते."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"पॅकेज स्थापित करण्यासाठी विनंती करा"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"पॅकेजच्या स्थापना करण्यासाठी अनुप्रयोगास अनुमती देते."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"झूम नियंत्रणासाठी दोनदा टॅप करा"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"विजेट जोडू शकलो नाही."</string>
<string name="ime_action_go" msgid="8320845651737369027">"जा"</string>
<string name="ime_action_search" msgid="658110271822807811">"शोधा"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"सूचना रॅंकर सेवा"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> द्वारे VPN सक्रिय केले आहे"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"नेटवर्क व्यवस्थापित करण्यासाठी टॅप करा."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> शी कनेक्ट केले. नेटवर्क व्यवस्थापित करण्यासाठी टॅप करा."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN कनेक्ट करणे नेहमी-चालू…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN कनेक्ट केलेले नेहमी-चालू"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"VPN त्रुटी नेहमी-चालू"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"अनपिन करा"</string>
<string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"सत्र पुन्हा सुरू करा"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"नवीन डेमो सत्र प्रारंभ करण्यासाठी टॅप करा"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"डेमो प्रारंभ करत आहे"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"सत्र पुन्हा सुरू करत आहे"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"हे डिव्हाइस निर्बंधांशिवाय वापरण्यासाठी फॅक्टरी रीसेट करा"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"अधिक जाणून घेण्यासाठी स्पर्श करा."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> अक्षम केले"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index e48d7d61791a..2ca35c30b863 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Sentiasa tunjukkan"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Dayakan semula kod kompak ini tetapan Sistem &gt; Apl &gt; Dimuat turun."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> tidak menyokong tetapan saiz Paparan semasa dan mungkin menunjukkan gelagat yang tidak dijangka."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Sentiasa tunjukkan"</string>
<string name="smv_application" msgid="3307209192155442829">"Apl <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) telah melanggar dasar Mod Tegasnya sendiri."</string>
<string name="smv_process" msgid="5120397012047462446">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> telah melanggar dasar Mod Tegasnya sendiri."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android sedang menaik taraf..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Nyahsemat"</string>
<string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Mulakan Semula Sesi"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Ketik untuk memulakan sesi tunjuk cara baharu"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Memulakan tunjuk cara"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Memulakan semula sesi"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Lakukan tetapan semula kilang untuk menggunakan peranti ini tanpa sekatan"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ketik untuk mengetahui lebih lanjut."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> dilumpuhkan"</string>
diff --git a/core/res/res/values-my-rMM-watch/styles_material.xml b/core/res/res/values-my-rMM-watch/styles_material.xml
index 616e13e184ee..36a459dc16a0 100644
--- a/core/res/res/values-my-rMM-watch/styles_material.xml
+++ b/core/res/res/values-my-rMM-watch/styles_material.xml
@@ -31,5 +31,5 @@ please see styles_device_defaults.xml.
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"ကိုယ်စားလှယ်များ"</font></string>
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
</resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 72fc86ea26ca..48c100d0a480 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"စကေး"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"အမြဲပြသရန်"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"ဒါကို စနစ် ဆက်တင်များထဲ ပြန်ဖွင့်ပေးရန် &gt; Apps &gt; ဒေါင်းလုဒ် လုပ်ပြီး။"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် လက်ရှိ မျက်နှာပြင်အရွယ်အစားကို ပံ့ပိုးထားခြင်း မရှိပါ။ မမျှော်လင့်နိုင်သည့် ချွတ်ယွင်းချက်များ ဖြစ်ပေါ်နိုင်ပါသည်။"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"အမြဲပြပါ"</string>
<string name="smv_application" msgid="3307209192155442829">"app <xliff:g id="APPLICATION">%1$s</xliff:g> (လုပ်ငန်းစဉ် <xliff:g id="PROCESS">%2$s</xliff:g>) က ကိုယ်တိုင် ပြဌာန်းခဲ့သည့် StrictMode မူဝါဒကို ချိုးဖောက်ခဲ့သည်။"</string>
<string name="smv_process" msgid="5120397012047462446">"ဤ<xliff:g id="PROCESS">%1$s</xliff:g>ဖြစ်စဥ်မှာ ကိုယ်တိုင်အကျိုးသက်ရောက်သော StrictModeမူဝါဒအား ချိုးဖောက်သည်"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"အန်ဒရွိုက်ကို မွမ်းမံနေ…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"အပလီကေးရှင်းအား တပ်ဆင်ရေး ချိတ်ဆက်မှုများကို ဖတ်ခွင့်ပြုသည်။ ၎င်းသည် ဖွင့်သုံးနေသည့် အထုပ်အား တပ်ဆင်မှုဆိုင်ရာ အသေးိစတ်များကို ကြည့်ရှုခွင့် ပြုသည်။"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"တပ်ဆင်ရေး အထုပ်များကို တောင်းဆိုပါ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ပက်ကေ့များ သွင်းယူခြင်းအတွက် တောင်းဆိုရန် အပ္ပလီကေးရှင်းအား ခွင့်ပြုပါ"</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ဇူးမ်အသုံးပြုရန် နှစ်ချက်တို့ပါ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ဝဒ်ဂျက်ထည့်လို့ မရပါ"</string>
<string name="ime_action_go" msgid="8320845651737369027">"သွားပါ"</string>
<string name="ime_action_search" msgid="658110271822807811">"ရှာဖွေခြင်း"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"သတိပေးချက် အဆင့်သတ်မှတ်ခြင်းဝန်ဆောင်မှု"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN ဖွင့်ထားပါသည်"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g>မှVPNအလုပ်လုပ်နေသည်"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"ကွန်ရက်ကို စီမံခန့်ခွဲရန် တို့ပါ။"</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> သို့ ချိတ်ဆက်ထားသည်။ ကွန်ရက်ကို စီမံခန့်ခွဲရန် တို့ပါ။"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"အမြဲတမ်းဖွင့်ထား VPN ဆက်သွယ်နေစဉ်…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"အမြဲတမ်းဖွင့်ထား VPN ဆက်သွယ်မှုရှိ"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"အမြဲတမ်းဖွင့်ထား VPN အမှား"</string>
@@ -1652,10 +1651,14 @@
<string name="unpin_target" msgid="3556545602439143442">"ဖြုတ်ပါ"</string>
<string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"စက်ရှင်ကို ပြန်စပါ"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"သရုပ်ပြစက်ရှင်အသစ်စတင်ရန် တို့ပါ"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"သရုပ်ပြချက်ကို စတင်နေသည်"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"စက်ရှင်ကို ပြန်လည်စတင်နေပါသည်"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"စက်ပစ္စည်းကို ပြန်လည်သတ်မှတ်မလား။"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"စက်ပစ္စည်းကို ပြန်လည်သတ်မှတ်ရန် တို့ပါ"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"သရုပ်ပြချက်ကို စတင်နေသည်…"</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"စက်ပစ္စည်းကို ပြန်လည်သတ်မှတ်နေသည်…"</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"စက်ပစ္စည်းကို ပြန်လည်သတ်မှတ်မလား။"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"ပြောင်းလဲမှုများကို ဆုံးရှုံးသွားမည်ဖြစ်ပြီး သရုပ်ပြချက်သည် <xliff:g id="TIMEOUT">%1$s</xliff:g> စက္ကန့်အတွင်း စတင်ပါမည်…"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"မလုပ်တော့"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"ယခုပြန်လည်သတ်မှတ်ပါ"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"ဤစက်ပစ္စည်းကို ကန့်သတ်ချက်များမပါဘဲ အသုံးပြုရန် စက်ရုံထုတ်ဆက်တင်အတိုင်း ပြန်လည်သတ်မှတ်ပါ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ပိုမိုလေ့လာရန် တို့ပါ။"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ပိတ်ထားသည့် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index c530593ddc5a..608b5fcdca4b 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Vis alltid"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Reaktiver dette i systeminnstillingene &gt; Apper &gt; Nedlastet."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> støtter ikke den nåværende innstillingen for skjermstørrelse og fungerer kanskje ikke som den skal."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Vis alltid"</string>
<string name="smv_application" msgid="3307209192155442829">"Appen <xliff:g id="APPLICATION">%1$s</xliff:g> (prosessen <xliff:g id="PROCESS">%2$s</xliff:g>) har brutt de selvpålagte StrictMode-retningslinjene."</string>
<string name="smv_process" msgid="5120397012047462446">"Prosessen<xliff:g id="PROCESS">%1$s</xliff:g> har brutt de selvpålagte StrictMode-retningslinjene."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android oppgraderes …"</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Løsne"</string>
<string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Start økten på nytt"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Trykk for å starte en ny demoøkt"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Starter demo"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Starte økten på nytt"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Tilbakestill til fabrikkstandard for å bruke denne enheten uten begrensninger"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Trykk for å finne ut mer."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> er slått av"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 0f4e99c4823c..05b735c44ee3 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1021,6 +1021,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"स्केल"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"सधैँ देखाउनुहोस्"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"प्रणाली सेटिङहरूमा यसलाई पुनःसक्षम गराउनुहोस् &gt; अनुप्रयोगहरू &gt; डाउनलोड गरेको।"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले हालको प्रदर्शनको आकार सम्बन्धी सेटिङलाई समर्थन गर्दैन र अप्रत्याशित तरिकाले व्यवहार गर्न सक्छ।"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"सधैँ देखाउनुहोस्"</string>
<string name="smv_application" msgid="3307209192155442829">"अनुप्रयोग <xliff:g id="APPLICATION">%1$s</xliff:g> (प्रक्रिया <xliff:g id="PROCESS">%2$s</xliff:g>) ले यसको स्वयं-लागु गरिएको स्ट्रिटमोड नीति उलङ्घन गरेको छ।"</string>
<string name="smv_process" msgid="5120397012047462446">"प्रक्रिया <xliff:g id="PROCESS">%1$s</xliff:g> यसको आफ्नै कडामोड नीतिका कारण उल्लङ्घन गरिएको छ।"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"एन्ड्रोइड अपग्रेड हुँदैछ…"</string>
@@ -1655,10 +1657,14 @@
<string name="unpin_target" msgid="3556545602439143442">"अनपिन गर्नुहोस्"</string>
<string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"सत्रलाई पुन:सुरु गर्नुहोस्"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"एउटा नयाँ डेमो सम्बन्धी सत्र सुरु गर्न ट्याप गर्नुहोस्"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"डेमो सुरु गर्दै"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"सत्रलाई पुन:सुरु गर्दै"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"यन्त्रलाई रिसेट गर्ने हो?"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"यन्त्रलाई रिसेट गर्न ट्याप गर्नुहोस्"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"डेमो सुरु गर्दै…"</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"यन्त्रलाई रिसेट गर्दै…"</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"यन्त्रलाई रिसेट गर्ने हो?"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"तपाईँ सबै परिवर्तनहरू गुमाउनु हुनेछ र <xliff:g id="TIMEOUT">%1$s</xliff:g> सेकेन्डमा डेमो फेरि सुरु हुनेछ…"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"रद्द गर्नुहोस्"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"अहिले रिसेट गर्नुहोस्"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"यस यन्त्रलाई सीमितताहरू बिना प्रयोग गर्नका लागि फ्याक्ट्री रिसेट गर्नुहोस्"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"थप जान्नका लागि छुनुहोस्।"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> लाई असक्षम गरियो"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index cce6c09e1bee..626fe4287b46 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Schaal"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Altijd weergeven"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"U kunt dit opnieuw inschakelen via Systeeminstellingen &gt; Apps &gt; Gedownload."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> biedt geen ondersteuning voor de huidige instelling voor weergavegrootte en kan onverwacht gedrag vertonen."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Altijd weergeven"</string>
<string name="smv_application" msgid="3307209192155442829">"De app <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) heeft het zelf afgedwongen StrictMode-beleid geschonden."</string>
<string name="smv_process" msgid="5120397012047462446">"Het proces <xliff:g id="PROCESS">%1$s</xliff:g> heeft het zelf afgedwongen StrictMode-beleid geschonden."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android wordt bijgewerkt..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Losmaken"</string>
<string name="app_info" msgid="6856026610594615344">"App-info"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Sessie opnieuw starten"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Tik om een nieuwe demosessie te starten"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Demo starten"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Sessie opnieuw starten"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Zet dit apparaat terug op de fabrieksinstellingen om het zonder beperkingen te gebruiken"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tik voor meer informatie."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> uitgeschakeld"</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 26b7db1289a0..42f8eb1d75a4 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"ਸਕੇਲ"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"ਹਮੇਸ਼ਾਂ ਦਿਖਾਓ"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"ਸਿਸਟਮ ਸੈਟਿੰਗਾਂ &gt; ਐਪਸ &gt; ਡਾਊਨਲੋਡ ਕੀਤਿਆਂ ਵਿੱਚ ਇਸਨੂੰ ਮੁੜ-ਸਮਰੱਥ ਬਣਾਓ।"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵਰਤਮਾਨ ਡਿਸਪਲੇ ਆਕਾਰ ਸੈਟਿੰਗ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ ਹੈ ਅਤੇ ਅਣਕਿਆਸੇ ਤੌਰ \'ਤੇ ਵਿਹਾਰ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"ਹਮੇਸ਼ਾ ਵਿਖਾਓ"</string>
<string name="smv_application" msgid="3307209192155442829">"ਐਪ <xliff:g id="APPLICATION">%1$s</xliff:g> (ਪ੍ਰਕਿਰਿਆ<xliff:g id="PROCESS">%2$s</xliff:g>) ਨੇ ਆਪਣੀ ਖੁਦ-ਲਾਗੂ ਕੀਤੀ ਸਟ੍ਰਿਕਟਮੋਡ ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕੀਤੀ ਹੈ।"</string>
<string name="smv_process" msgid="5120397012047462446">"ਪ੍ਰਕਿਰਿਆ <xliff:g id="PROCESS">%1$s</xliff:g> ਨੇ ਆਪਣੀ ਖੁਦ-ਲਾਗੂ ਕੀਤੀ ਸਟ੍ਰਿਕਟਮੋਡ ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕੀਤੀ ਹੈ।"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android ਅਪਗ੍ਰੇਡ ਕਰ ਰਿਹਾ ਹੈ…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਇੰਸਟੌਲ ਸੈਸ਼ਨ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਇਸਨੂੰ ਸਕਿਰਿਆ ਪੈਕੇਜ ਇੰਸਟੌਲੇਸ਼ਨਾਂ ਬਾਰੇ ਵੇਰਵੇ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ਪੈਕੇਜ ਸਥਾਪਿਤ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕਰੋ"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ਪੈਕੇਜ ਦੀ ਸਥਾਪਨਾ ਦੀ ਬੇਨਤੀ ਕਰਨ ਲਈ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਅਨੁਮਤੀ ਦਿੰਦਾ ਹੈ"</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ਜ਼ੂਮ ਕੰਟਰੋਲ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ਵਿਜੇਟ ਨਹੀਂ ਜੋੜ ਸਕਿਆ।"</string>
<string name="ime_action_go" msgid="8320845651737369027">"ਜਾਓ"</string>
<string name="ime_action_search" msgid="658110271822807811">"ਖੋਜੋ"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"ਸੂਚਨਾ ਰੈਂਕਰ ਸੇਵਾ"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN ਸਕਿਰਿਆ ਕੀਤਾ"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> ਰਾਹੀਂ ਸਕਿਰਿਆ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"ਨੈੱਟਵਰਕ ਦੇ ਪ੍ਰਬੰਧਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ। ਨੈੱਟਵਰਕ ਦੇ ਪ੍ਰਬੰਧਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ਹਮੇਸ਼ਾਂ-ਚਾਲੂ VPN ਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"ਹਮੇਸ਼ਾਂ-ਚਾਲੂ VPN ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"ਹਮੇਸ਼ਾਂ-ਚਾਲੂ VPN ਅਸ਼ੁੱਧੀ"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"ਅਨਪਿੰਨ ਕਰੋ"</string>
<string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"ਸੈਸ਼ਨ ਦੁਬਾਰਾ ਸ਼ੁਰੂ ਕਰੋ"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"ਇੱਕ ਨਵਾਂ ਡੈਮੋ ਸੈਸ਼ਨ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"ਡੈਮੋ ਚਾਲੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"ਸੈਸ਼ਨ ਮੁੜ-ਚਾਲੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਬਿਨਾਂ ਪਾਬੰਦੀਆਂ ਦੇ ਵਰਤਣ ਲਈ ਫੈਕਟਰੀ ਰੀਸੈੱਟ ਕਰੋ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ਹੋਰ ਜਾਣਨ ਲਈ ਸਪਰਸ਼ ਕਰੋ।"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 25638a58ea86..2188ee6750a8 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1061,6 +1061,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Zawsze pokazuj"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Włącz ponownie, wybierając Ustawienia systemowe &gt; Aplikacje &gt; Pobrane."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje obecnie ustawionego rozmiaru wyświetlacza i może działać niestabilnie."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Zawsze pokazuj"</string>
<string name="smv_application" msgid="3307209192155442829">"Aplikacja <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) naruszyła wymuszone przez siebie zasady StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> naruszył wymuszone przez siebie zasady StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android jest uaktualniany..."</string>
@@ -1721,10 +1723,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Odepnij"</string>
<string name="app_info" msgid="6856026610594615344">"O aplikacji"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Ponowne rozpoczęcie sesji"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Kliknij, by rozpocząć nową sesję demonstracyjną"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Uruchamiam wersję demo"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Uruchamiam ponownie sesję"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Aby używać tego urządzenia bez ograniczeń, przywróć ustawienia fabryczne"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Kliknij, by dowiedzieć się więcej."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Wyłączono: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 18c6d3e2719f..7729c9348548 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Escala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Mostrar sempre"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Reativar isso em Configurações do sistema &gt; Apps &gt; Transferidos."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com a configuração atual de tamanho de exibição e pode se comportar de forma inesperada."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mostrar sempre"</string>
<string name="smv_application" msgid="3307209192155442829">"O app <xliff:g id="APPLICATION">%1$s</xliff:g>, processo <xliff:g id="PROCESS">%2$s</xliff:g>, violou a política StrictMode imposta automaticamente."</string>
<string name="smv_process" msgid="5120397012047462446">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> violou a política StrictMode imposta automaticamente."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"O Android está sendo atualizado..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string>
<string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Reiniciar sessão"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Toque para iniciar uma nova sessão de demonstração"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Iniciando demonstração"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Reiniciando sessão"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Redefinir para a configuração original para usar este dispositivo sem restrições"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Widget <xliff:g id="LABEL">%1$s</xliff:g> desativado"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 1530b4f92da7..0e3af1fddf3a 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Escala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Mostrar sempre"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Reative este modo nas Definições do Sistema &gt; Aplicações &gt; Transferidas."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> não suporta a definição de Tamanho do ecrã atual e pode ter um comportamento inesperado."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mostrar sempre"</string>
<string name="smv_application" msgid="3307209192155442829">"A aplicação <xliff:g id="APPLICATION">%1$s</xliff:g> (processo <xliff:g id="PROCESS">%2$s</xliff:g>) violou a política StrictMode auto-imposta."</string>
<string name="smv_process" msgid="5120397012047462446">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> violou a política StrictMode auto-imposta."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"O Android está a ser atualizado..."</string>
@@ -1314,7 +1316,7 @@
<string name="storage_usb" msgid="3017954059538517278">"Armazenamento USB"</string>
<string name="extract_edit_menu_button" msgid="8940478730496610137">"Editar"</string>
<string name="data_usage_warning_title" msgid="1955638862122232342">"Aviso de utilização de dados"</string>
- <string name="data_usage_warning_body" msgid="6660692274311972007">"Toque para ver a utiliz. e def."</string>
+ <string name="data_usage_warning_body" msgid="6660692274311972007">"Toque para ver a utilização e definições"</string>
<string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Limite de dados 2G/3G atingido"</string>
<string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Limite de dados 4G atingido"</string>
<string name="data_usage_mobile_limit_title" msgid="557158376602636112">"Limite de dados móveis atingido"</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Soltar"</string>
<string name="app_info" msgid="6856026610594615344">"Informações da aplicação"</string>
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Reiniciar sessão"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Toque para iniciar uma nova sessão de demonstração"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"A iniciar a demonstração"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"A reiniciar a sessão"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Repor os dados de fábrica para utilizar o dispositivo sem restrições"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> desativado"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 18c6d3e2719f..7729c9348548 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Escala"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Mostrar sempre"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Reativar isso em Configurações do sistema &gt; Apps &gt; Transferidos."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com a configuração atual de tamanho de exibição e pode se comportar de forma inesperada."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Mostrar sempre"</string>
<string name="smv_application" msgid="3307209192155442829">"O app <xliff:g id="APPLICATION">%1$s</xliff:g>, processo <xliff:g id="PROCESS">%2$s</xliff:g>, violou a política StrictMode imposta automaticamente."</string>
<string name="smv_process" msgid="5120397012047462446">"O processo <xliff:g id="PROCESS">%1$s</xliff:g> violou a política StrictMode imposta automaticamente."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"O Android está sendo atualizado..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string>
<string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Reiniciar sessão"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Toque para iniciar uma nova sessão de demonstração"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Iniciando demonstração"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Reiniciando sessão"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Redefinir para a configuração original para usar este dispositivo sem restrições"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Widget <xliff:g id="LABEL">%1$s</xliff:g> desativado"</string>
diff --git a/core/res/res/values-ro-watch/styles_material.xml b/core/res/res/values-ro-watch/styles_material.xml
new file mode 100644
index 000000000000..36a459dc16a0
--- /dev/null
+++ b/core/res/res/values-ro-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 2d41ae653709..09586ec631f8 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1038,6 +1038,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Scară"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Afișați întotdeauna"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Reactivați acest mod din Setări de sistem &gt; Aplicații &gt; Descărcate."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> nu acceptă setarea actuală pentru Dimensiunea afișării și este posibil să aibă un comportament neașteptat."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Afișează întotdeauna"</string>
<string name="smv_application" msgid="3307209192155442829">"Aplicația <xliff:g id="APPLICATION">%1$s</xliff:g> (procesul <xliff:g id="PROCESS">%2$s</xliff:g>) a încălcat propria politică StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Procesul <xliff:g id="PROCESS">%1$s</xliff:g> a încălcat propria politică StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android trece la o versiune superioară..."</string>
@@ -1685,10 +1687,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Anulați fixarea"</string>
<string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Reporniți sesiunea"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Atingeți pentru a începe o nouă sesiune demonstrativă"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Se pornește demonstrația"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Se repornește sesiunea"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Reveniți la setările din fabrică pentru a folosi acest dispozitiv fără restricții"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Atingeți pentru a afla mai multe."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> a fost dezactivat"</string>
diff --git a/core/res/res/values-ru-watch/styles_material.xml b/core/res/res/values-ru-watch/styles_material.xml
new file mode 100644
index 000000000000..36a459dc16a0
--- /dev/null
+++ b/core/res/res/values-ru-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 16c5752f4e7f..5a3b5fcbbcb0 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1061,6 +1061,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Масштаб"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Всегда показывать"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Включить эту функцию можно в меню \"Настройки &gt; Приложения &gt; Загруженные\"."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" не поддерживает выбранный масштаб изображения на экране и может работать некорректно."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Всегда показывать"</string>
<string name="smv_application" msgid="3307209192155442829">"Приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" (процесс: <xliff:g id="PROCESS">%2$s</xliff:g>) нарушило собственную политику StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Процесс <xliff:g id="PROCESS">%1$s</xliff:g> нарушил собственную политику StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Обновление Android..."</string>
@@ -1721,10 +1723,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Открепить"</string>
<string name="app_info" msgid="6856026610594615344">"О приложении"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Начните сеанс заново"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Нажмите, чтобы начать новый демосеанс."</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Запуск деморежима"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Повтор сеанса"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Сброс до заводских настроек для работы без ограничений"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Нажмите, чтобы узнать больше."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Виджет <xliff:g id="LABEL">%1$s</xliff:g> отключен"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 0c28121b6f49..5befbb181468 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1017,6 +1017,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"පරිමාණය"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"සැමවිටම පෙන්වන්න"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"පද්ධති සැකසීම් තුළ මෙය නැවත ක්‍රියාත්මක කරන්න &gt; යෙදුම් &gt; බාගන්නා ලදි."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> වත්මන් සංදර්ශක තරම සඳහා සහාය නොදක්වන අතර අනපේක්ෂිත ලෙස හැසිරීමට හැකිය."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"සැම විටම පෙන්වන්න"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> යෙදුම (<xliff:g id="PROCESS">%2$s</xliff:g> ක්‍රියාවලිය) එහි StrictMode කොන්දේසිය උල්ලංඝනය කර ඇත."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> ක්‍රියාවලිය එහි StrictMode කොන්දේසිය උල්ලංඝනය කර ඇත."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android උත්ශ්‍රේණි වෙමින් පවතී..."</string>
@@ -1651,10 +1653,14 @@
<string name="unpin_target" msgid="3556545602439143442">"ගලවන්න"</string>
<string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"සැසිය ආරම්භ කරන්න"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"නව ආදර්ශ සැසියක් ආරම්භ කිරීම තට්ටු කරන්න"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"ආදර්ශනය ආරම්භ කරමින්"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"සැසිය නැවත ආරම්භ කරමින්"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"උපාංගය යළි සකසන්නද?"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"උපාංගය යළි සැකසීමට තට්ටු කරන්න"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"ආදර්ශනය ආරම්භ කරමින්..."</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"උපාංගය යළි සකසමින්..."</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"උපාංගය යළි සකසන්නද?"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"ඔබට යම් වෙනස් කිරීම් අහිමි වනු ඇති අතර ආදර්ශනය තත්පර <xliff:g id="TIMEOUT">%1$s</xliff:g>කින් නැවත ආරම්භ වනු ඇත…"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"අවලංගු කරන්න"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"දැන් යළි සකසන්න"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"සීමා කිරීම්වලින් තොරව මෙම උපාංගය භාවිත කිරීමට කර්මාන්ත ශාලා යළි සැකසීම"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"තව දැන ගැනීමට ස්පර්ශ කරන්න."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"අබල කළ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 89d762c9c189..62c2e52d0340 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1061,6 +1061,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Prispôsobiť veľkosť"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Vždy zobraziť"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Povoľte to znova v sekcii Nastavenia systému &gt; Aplikácie &gt; Stiahnuté súbory."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"Aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g> aktuálne nastavenie veľkosti zobrazenia nepodporuje a môže sa správať neočakávane."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Vždy zobrazovať"</string>
<string name="smv_application" msgid="3307209192155442829">"Aplikácia <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) porušila svoje vlastné vynútené pravidlá StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> porušil svoje vlastné vynútené pravidlá StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Prebieha inovácia systému Android..."</string>
@@ -1721,10 +1723,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Uvoľniť"</string>
<string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string>
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Reštartujte reláciu"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Klepnutím začnete novú demo reláciu"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Spúšťa sa ukážka"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Reštartuje sa relácia"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Ak chcete toto zariadenie používať bez obmedzení, obnovte na ňom továrenské nastavenia"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Klepnutím získate ďalšie informácie."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Deaktivovaná miniaplikácia <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 051e4dab69c6..34061f1f09ee 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1061,6 +1061,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Lestvica"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Vedno pokaži"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Znova omogočite to v sistemskih nastavitvah &gt; Aplikacije &gt; Preneseno."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> ne podpira trenutne nastavitve velikosti zaslona, kar lahko vodi v nepričakovano delovanje."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Vedno pokaži"</string>
<string name="smv_application" msgid="3307209192155442829">"Aplikacija <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) krši svoj samouveljavljiv pravilnik o strogem načinu."</string>
<string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> krši svoj samoizvedljivi pravilnik o strogem načinu."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Poteka nadgradnja Androida ..."</string>
@@ -1721,10 +1723,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Odpenjanje"</string>
<string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Vnovični zagon seje"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Dotaknite se, če želite začeti novo predstavitveno sejo"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Začenjanje predstavitve"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Vnovičen zagon seje"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Ponastavitev naprave na tovarniške nastavitve za uporabo brez omejitev"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dotaknite se, če želite izvedeti več."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> – onemogočeno"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index ca1745079b49..d94c9e9c4c99 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Shkalla"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Shfaq gjithnjë"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Aktivizoje sërish këtë te \"Cilësimet e sistemit\" &gt; \"Aplikacionet\" &gt; \"Të shkarkuara\"."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> nuk mbështet cilësimin aktual të madhësisë së ekranit dhe mund të shfaqë sjellje të papritura."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Shfaq gjithmonë"</string>
<string name="smv_application" msgid="3307209192155442829">"Aplikacioni <xliff:g id="APPLICATION">%1$s</xliff:g> (procesi <xliff:g id="PROCESS">%2$s</xliff:g>) ka shkelur politikën e tij të vetë-imponuar \"Modaliteti i ashpër\" (StrictMode)."</string>
<string name="smv_process" msgid="5120397012047462446">"Procesi <xliff:g id="PROCESS">%1$s</xliff:g> ka shkelur politikën e tij të vetë-imponuar \"Modaliteti i rreptë\" (StrictMode)"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"\"Androidi\" po përditësohet…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Lejon një aplikacion të lexojë sesionet e instalimit. Kjo e lejon atë të shohë detaje rreth instalimeve të paketave aktive."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"kërko paketat e instalimit"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Lejon që një aplikacion të kërkojë instalimin e paketave."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Trokit dy herë për të kontrolluar zmadhimin"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Nuk mundi të shtonte miniaplikacion."</string>
<string name="ime_action_go" msgid="8320845651737369027">"Shko"</string>
<string name="ime_action_search" msgid="658110271822807811">"Kërko"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Shërbimi i klasifikimit të njoftimeve"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN-ja u aktivizua"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN-ja është aktivizuar nga <xliff:g id="APP">%s</xliff:g>"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"Trokit për të menaxhuar rrjetin."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"Lidhur me <xliff:g id="SESSION">%s</xliff:g>. Trokit për të menaxhuar rrjetin."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Po lidh VPN-në për aktivizim të përhershëm…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN e lidhur në mënyrë të përhershme"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Gabimi VPN-je për aktivizimin e përhershëm"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Zhgozhdo"</string>
<string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Rinis sesionin"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Trokit për të nisur një sesion të ri të demonstrimit"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Demonstrimi po niset"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Sesioni po riniset"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Rivendos cilësimet e fabrikës për ta përdorur këtë pajisje pa kufizime"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Prek për të mësuar më shumë."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> u çaktivizua"</string>
diff --git a/core/res/res/values-sr-watch/styles_material.xml b/core/res/res/values-sr-watch/styles_material.xml
new file mode 100644
index 000000000000..36a459dc16a0
--- /dev/null
+++ b/core/res/res/values-sr-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 40fe943abb21..a14d4cfc5361 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1038,6 +1038,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Размера"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Увек приказуј"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Поново омогућите у менију Системска подешавања &gt; Апликације &gt; Преузето."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> не подржава тренутно подешавање величине приказа и може да се понаша неочекивано."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Увек приказуј"</string>
<string name="smv_application" msgid="3307209192155442829">"Апликација <xliff:g id="APPLICATION">%1$s</xliff:g> (процес <xliff:g id="PROCESS">%2$s</xliff:g>) је прекршила самонаметнуте StrictMode смернице."</string>
<string name="smv_process" msgid="5120397012047462446">"Процес <xliff:g id="PROCESS">%1$s</xliff:g> је прекршио самонаметнуте StrictMode смернице."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android се надограђује…"</string>
@@ -1685,10 +1687,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Откачи"</string>
<string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Поново покрените сесију"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Додирните да бисте покренули нову сесију демонстрације"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Демонстрација се покреће"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Сесија се поново покреће"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Ресетујте уређај на фабричка подешавања да бисте га користили без ограничења"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Додирните да бисте сазнали више."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Виџет <xliff:g id="LABEL">%1$s</xliff:g> је онемогућен"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2168d96d641d..26a3a19c9ded 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Anpassning"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Visa alltid"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Aktivera detta igen i Systeminställningar &gt; Appar &gt; Hämtat."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> har inte stöd för den nuvarande inställningen för skärmstorlek och kanske inte fungerar som förväntat."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Visa alltid"</string>
<string name="smv_application" msgid="3307209192155442829">"Appen <xliff:g id="APPLICATION">%1$s</xliff:g> (processen <xliff:g id="PROCESS">%2$s</xliff:g>) har brutit mot sin egen StrictMode-policy."</string>
<string name="smv_process" msgid="5120397012047462446">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> har brutit mot sin egen StrictMode-policy."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android uppgraderas ..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Lossa"</string>
<string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Starta om sessionen"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Tryck om du vill starta en ny demosession"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Demo startas"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Sessionen startas om"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Återställ enheten till standardinställningarna om du vill använda den utan begränsningar"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tryck här om du vill läsa mer."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> har inaktiverats"</string>
diff --git a/core/res/res/values-sw-watch/styles_material.xml b/core/res/res/values-sw-watch/styles_material.xml
index 2e3f7153c4d1..01392b243c57 100644
--- a/core/res/res/values-sw-watch/styles_material.xml
+++ b/core/res/res/values-sw-watch/styles_material.xml
@@ -31,5 +31,5 @@ please see styles_device_defaults.xml.
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"vipengee"</font></string>
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"yanayopendekezwa"</font></string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 7e6f03384b9f..a51d22089d32 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1013,6 +1013,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Kipimo"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Onyesha kila wakati"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Wezesha tena hii katika mipangilio ya Mfumo &gt; Programu &gt; iliyopakuliwa."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> haiwezi kutumia mipangilio ya sasa ya ukubwa wa Skrini na huenda isifanye kazi vizuri."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Onyesha kila wakati"</string>
<string name="smv_application" msgid="3307209192155442829">"Programu <xliff:g id="APPLICATION">%1$s</xliff:g> (utaratibu <xliff:g id="PROCESS">%2$s</xliff:g>) imeenda kinyume na sera yake ya StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Shughuli ya <xliff:g id="PROCESS">%1$s</xliff:g> imeenda kinyume na kulazimisha sera yake ya StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Toleo jipya la Android linawekwa..."</string>
@@ -1647,10 +1649,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Bandua"</string>
<string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Anzisha Kipindi Upya"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Gonga ili uanzishe kipindi kipya cha onyesho"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Inaanzisha onyesho"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Inaanzisha onyesho upya"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Rejesha mipangilio iliyotoka nayo kiwandani ili utumie kifaa hiki bila vikwazo"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Gusa ili kupata maelezo zaidi."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> imezimwa"</string>
diff --git a/core/res/res/values-ta-rIN-watch/styles_material.xml b/core/res/res/values-ta-rIN-watch/styles_material.xml
new file mode 100644
index 000000000000..d4605e6eaea9
--- /dev/null
+++ b/core/res/res/values-ta-rIN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"கேன்டிடேட்ஸ்"</font></string>
+</resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 1212bdda8a90..6c083a781210 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"அளவு"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"எப்போதும் காட்டு"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"சிஸ்டம் அமைப்பு &gt; பயன்பாடுகள் &gt; பதிவிறக்கம் என்பதில் இதை மீண்டும் இயக்கவும்."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"தற்போதைய திரை அளவு அமைப்பை <xliff:g id="APP_NAME">%1$s</xliff:g> ஆதரிக்காததால், அது வழக்கத்திற்கு மாறாகச் செயல்படக்கூடும்."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"எப்போதும் காட்டு"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> பயன்பாடு (செயல்முறை <xliff:g id="PROCESS">%2$s</xliff:g>), தனது சுய-செயலாக்க StrictMode கொள்கையை மீறியது."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> செயல்முறை, தனது சுய-செயலாக்க StrictMode கொள்கையை மீறியது."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android மேம்படுத்தப்படுகிறது…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"நிறுவல் அமர்வுகளைப் படிக்க, பயன்பாட்டை அனுமதிக்கிறது. இது செயல்படும் தொகுப்பு நிறுவல்களைப் பற்றிய விவரங்களைப் பார்க்க அனுமதிக்கிறது."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"நிறுவல் தொகுப்புகளைக் கோருதல்"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"தொகுப்புகளின் நிறுவலைக் கோர, பயன்பாட்டை அனுமதிக்கும்."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"அளவை மாற்றுவதற்கான கட்டுப்பாட்டிற்கு, இருமுறை தட்டவும்"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"விட்ஜெட்டைச் சேர்க்க முடியவில்லை."</string>
<string name="ime_action_go" msgid="8320845651737369027">"செல்"</string>
<string name="ime_action_search" msgid="658110271822807811">"தேடு"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"அறிவிப்பை மதிப்பீடு செய்யும் சேவை"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN செயல்படுத்தப்பட்டது"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ஆல் VPN செயல்படுத்தப்பட்டது"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"நெட்வொர்க்கை நிர்வகிக்க, தட்டவும்."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> உடன் இணைக்கப்பட்டது. நெட்வொர்க்கை நிர்வகிக்க, தட்டவும்."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"எப்போதும் இயங்கும் VPN உடன் இணைக்கிறது…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"எப்போதும் இயங்கும் VPN இணைக்கப்பட்டது"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"எப்போதும் இயங்கும் VPN பிழை"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"பின்னை அகற்று"</string>
<string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"அமர்வை மீண்டும் தொடங்கு"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"புதிய டெமோ அமர்வைத் தொடங்க, தட்டவும்"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"டெமோவைத் தொடங்குகிறது"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"அமர்வை மீண்டும் தொடங்குகிறது"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"இந்தச் சாதனத்தைக் கட்டுப்பாடுகளின்றிப் பயன்படுத்த, ஆரம்ப நிலைக்கு மீட்டமைக்கவும்"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"மேலும் அறிய தொடவும்."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"முடக்கப்பட்டது: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 675f824cfd6f..d7ddc23a736e 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"ప్రమాణం"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"ఎల్లప్పుడూ చూపు"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"సిస్టమ్ సెట్టింగ్‌లు &gt; అనువర్తనాలు &gt; డౌన్‌లోడ్ చేసినవిలో దీన్ని పునఃప్రారంభించండి."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> ప్రస్తుత ప్రదర్శన పరిమాణ సెట్టింగ్‌కు మద్దతు ఇవ్వదు, దీని వలన ఊహించని సమస్యలు తలెత్తవచ్చు."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"ఎల్లప్పుడూ చూపు"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> అనువర్తనం (<xliff:g id="PROCESS">%2$s</xliff:g> ప్రాసెస్) అది స్వయంగా అమలు చేసే ఖచ్చితమైన మోడ్ విధానాన్ని ఉల్లంఘించింది."</string>
<string name="smv_process" msgid="5120397012047462446">"ప్రక్రియ <xliff:g id="PROCESS">%1$s</xliff:g> అది స్వయంగా అమలు చేసే ఖచ్చితమైన మోడ్ విధానాన్ని ఉల్లంఘించింది."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android అప్‌గ్రేడ్ అవుతోంది…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ఇన్‌స్టాల్ సెషన్‌లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది సక్రియ ప్యాకేజీ ఇన్‌స్టాలేషన్‌ల గురించి వివరాలను చూడటానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ఇన్‌స్టాల్ ప్యాకేజీలను అభ్యర్థించడం"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ప్యాకేజీల ఇన్‌స్టాలేషన్ అభ్యర్థించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"జూమ్ నియంత్రణ కోసం రెండుసార్లు నొక్కండి"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"విడ్జెట్‌ను జోడించడం సాధ్యపడలేదు."</string>
<string name="ime_action_go" msgid="8320845651737369027">"వెళ్లు"</string>
<string name="ime_action_search" msgid="658110271822807811">"శోధించు"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"నోటిఫికేషన్ ర్యాంకర్ సేవ"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN సక్రియం చేయబడింది"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ద్వారా VPN సక్రియం చేయబడింది"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"నెట్‌వర్క్‌ను నిర్వహించడానికి నొక్కండి."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>కు కనెక్ట్ చేయబడింది. నెట్‌వర్క్‌ను నిర్వహించడానికి నొక్కండి."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ఎల్లప్పుడూ-ఆన్‌లో ఉండే VPN కనెక్ట్ చేయబడుతోంది…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"ఎల్లప్పుడూ-ఆన్‌లో ఉండే VPN కనెక్ట్ చేయబడింది"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"ఎల్లప్పుడూ-ఆన్‌లో ఉండే VPN లోపం"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"అన్‌‌పిన్‌ ‌చేయి"</string>
<string name="app_info" msgid="6856026610594615344">"అనువర్తన సమాచారం"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"సెషన్‌ను పునఃప్రారంభించండి"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"కొత్త డెమో సెషన్‌ను ప్రారంభించడానికి నొక్కండి"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"డెమోను ప్రారంభిస్తోంది"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"సెషన్‌ను పునఃప్రారంభిస్తోంది"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"ఈ పరికరాన్ని ఎటువంటి పరిమితులు లేకుండా ఉపయోగించడానికి ఫ్యాక్టరీ రీసెట్ చేయండి"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"మరింత తెలుసుకోవడానికి తాకండి."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> నిలిపివేయబడింది"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index c21d62824e79..0d4619c2aea9 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"สเกล"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"แสดงเสมอ"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"เปิดใช้งานอีกครั้งในการตั้งค่าระบบ &gt; แอปพลิเคชัน &gt; ดาวน์โหลด"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> ไม่สนับสนุนการตั้งค่าขนาดการแสดงผลปัจจุบันและอาจแสดงผลผิดปกติ"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"แสดงเสมอ"</string>
<string name="smv_application" msgid="3307209192155442829">"แอปพลิเคชัน <xliff:g id="APPLICATION">%1$s</xliff:g> (กระบวนการ <xliff:g id="PROCESS">%2$s</xliff:g>) ละเมิดนโยบาย StrictMode ที่บังคับใช้ด้วยตัวเอง"</string>
<string name="smv_process" msgid="5120397012047462446">"กระบวนการ <xliff:g id="PROCESS">%1$s</xliff:g> ละเมิดนโยบาย StrictMode ที่บังคับใช้ด้วยตัวเอง"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"กำลังอัปเกรด Android ..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"เลิกปักหมุด"</string>
<string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"เริ่มเซสชันอีกครั้ง"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"แตะเพื่อเริ่มเซสชันสาธิตใหม่"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"กำลังเริ่มการสาธิต"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"กำลังเริ่มเซสชันอีกครั้ง"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"รีเซ็ตเป็นค่าเริ่มต้นเพื่อใช้อุปกรณ์นี้โดยไร้ข้อจำกัด"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"แตะเพื่อเรียนรู้เพิ่มเติม"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ปิดใช้ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 269f2499e041..ada84650189a 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Sukat"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Palaging ipakita"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Muling paganahin ito sa mga setting ng System &gt; Apps &gt; Na-download."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"Hindi sinusuportahan ng <xliff:g id="APP_NAME">%1$s</xliff:g> ang kasalukuyang setting ng laki ng Display at maaaring may mangyaring hindi inaasahan."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Palaging ipakita"</string>
<string name="smv_application" msgid="3307209192155442829">"Ang app na <xliff:g id="APPLICATION">%1$s</xliff:g> (prosesong <xliff:g id="PROCESS">%2$s</xliff:g>) ay lumabag sa sarili nitong ipinapatupad na patakarang StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Ang prosesong <xliff:g id="PROCESS">%1$s</xliff:g> ay lumabag sa sarili nitong ipinapatupad na patakarang StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Nag-a-upgrade ang Android…"</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"I-unpin"</string>
<string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"I-restart ang Session"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"I-tap upang magsimula ng bagong session ng demo"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Sinisimulan ang demo"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Nire-restart ang session"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"I-factory reset upang magamit ang device na ito nang walang mga paghihigpit"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Pindutin upang matuto nang higit pa."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Na-disable ang <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 6c88fb2b6a79..0ac07c243c41 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Ölçek"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Her zaman göster"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Bunu Sistem ayarları &gt; Uygulamalar &gt; İndirilenler bölümünden yeniden etkinleştirin."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> geçerli Ekran boyutu ayarını desteklemiyor ve beklenmedik bir şekilde davranabilir."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Her zaman göster"</string>
<string name="smv_application" msgid="3307209192155442829">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması (<xliff:g id="PROCESS">%2$s</xliff:g> işlemi) kendiliğinden uyguladığı StrictMode politikasını ihlal etti."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> işlemi kendiliğinden uyguladığı StrictMode politikasını ihlal etti."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android yeni sürüme geçiriliyor..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Sabitlemeyi kaldır"</string>
<string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Oturumu Yeniden Başlatın"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Yeni bir demo oturumu başlatmak için dokunun"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Tanıtım başlatılıyor"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Oturum yeniden başlatılıyor"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Bu cihazı kısıtlama olmadan kullanmak için fabrika ayarlarına sıfırlayın"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Daha fazla bilgi edinmek için dokunun."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> devre dışı"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 15759b07efd7..fa05fa2dacdd 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1061,6 +1061,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Масштаб"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Завжди показувати"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Знову ввімкнути це в меню Налаштування системи &gt; Програми &gt; Завантажені."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> не підтримує поточне налаштування розміру екрана та може працювати неналежним чином."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Завжди показувати"</string>
<string name="smv_application" msgid="3307209192155442829">"Програма <xliff:g id="APPLICATION">%1$s</xliff:g> (процес <xliff:g id="PROCESS">%2$s</xliff:g>) порушила свою самозастосовну політику StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Процес <xliff:g id="PROCESS">%1$s</xliff:g> порушив свою самозастосовну політику StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android оновлюється..."</string>
@@ -1721,10 +1723,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Відкріпити"</string>
<string name="app_info" msgid="6856026610594615344">"Про додаток"</string>
<string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Новий сеанс"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Торкніться, щоб почати новий демо-сеанс"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Запускається демонстрація"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Починається новий сеанс"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Відновіть заводські параметри, щоб використовувати пристрій без обмежень"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Торкніться, щоб дізнатися більше."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> вимкнено"</string>
diff --git a/core/res/res/values-ur-rPK-watch/styles_material.xml b/core/res/res/values-ur-rPK-watch/styles_material.xml
new file mode 100644
index 000000000000..e569c7c78d10
--- /dev/null
+++ b/core/res/res/values-ur-rPK-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"امیدواران"</font></string>
+</resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 4ae5cbfe5774..3e3965910577 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"پیمانہ"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"ہمیشہ دکھائیں"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"‏سسٹم ترتیبات &gt; ایپس &gt; ڈاؤن لوڈ کردہ میں اسے دوبارہ فعال کریں۔"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> میں موجودہ ڈسپلے سائز ترتیبات کی معاونت نہیں ہے اور ہو سکتا ہے غیر متوقع طریقے سے کام کرے۔"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"ہمیشہ دکھائیں"</string>
<string name="smv_application" msgid="3307209192155442829">"‏ایپ <xliff:g id="APPLICATION">%1$s</xliff:g> (کارروائی <xliff:g id="PROCESS">%2$s</xliff:g>) نے خود نافذ کی گئی StrictMode پالیسی کی خلاف ورزی کی ہے۔"</string>
<string name="smv_process" msgid="5120397012047462446">"‏کارروائی <xliff:g id="PROCESS">%1$s</xliff:g> نے اپنی ذاتی طور پر نافذ کردہ StrictMode پلیسی کی خلاف ورزی کی ہے۔"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"‏Android اپ گریڈ ہو رہا ہے…"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ایک ایپلیکیشن کو انسٹال سیشنز پڑھنے کی اجازت دیتا ہے۔ یہ اسے فعال پیکیج انسٹالیشنز کے بارے میں تفصیلات دیکھنے کی اجازت دیتا ہے۔"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"پیکجز انسٹال کرنے کی درخواست کریں"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ایک ایپلیکیشن کو پیکجز انسٹال کرنے کی اجازت دیتی ہے۔"</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"زوم کنٹرول کیلئے دوبار تھپتھپائیں"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"ویجٹس کو شامل نہیں کرسکا۔"</string>
<string name="ime_action_go" msgid="8320845651737369027">"جائیں"</string>
<string name="ime_action_search" msgid="658110271822807811">"تلاش کریں"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"اطلاع کی درجہ بندی سروس"</string>
<string name="vpn_title" msgid="19615213552042827">"‏VPN فعال ہوگیا"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"‏<xliff:g id="APP">%s</xliff:g> کے ذریعہ VPN فعال ہے"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"نیٹ ورک نظم کرنے کیلئے تھپتھپائیں۔"</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> سے منسلک ہے۔ نیٹ ورک کا نظم کرنے کیلئے تھپتھپائیں۔"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"‏ہمیشہ آن VPN مربوط ہو رہا ہے…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"‏ہمیشہ آن VPN مربوط ہوگیا"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"‏ہمیشہ آن VPN کی خرابی"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"پن ہٹائیں"</string>
<string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"سیشن دوبارہ شروع کریں"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"نیا ڈیمو سیشن شروع کرنے کیلئے تھپتھپائیں"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"ڈیمو شروع ہو رہا ہے"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"سیشن دوبارہ شروع ہو رہا ہے"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"بغیر کسی حدود کے استعمال کرنے کیلئے اس آلے کو فیکٹری ری سیٹ کریں"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"مزید جاننے کیلئے ٹچ کریں۔"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"غیر فعال کردہ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index d777ea032c04..63a1c9f428db 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -325,9 +325,9 @@
<string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"Ilovaga tizim ishga tushishi bilanoq o‘zi ham ishga tushadigan qilib qo‘yish huquqini beradi. Buning natijasida televizorning ishga tushishi sekinlashishi hamda ilovaning doimiy ravishda ishlab turishi oqibatida butun planshetning ishlashi sekinlashi mumkin."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Ilova tizim qayta yoqilganidan so‘ng o‘zini ishga tushirishi mumkin. Bu telefonning yonish vaqtini uzaytirishi va doimiy ishlab turivchi ilova tufayli uning tezkor ishlashini kamaytirishi mumkin."</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"xabarlarni keyinchalik saqlash sharti bilan yuborish"</string>
- <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Ilovaga uzatish tugagandan keyin ham qoladigan yopishqoq uzatishlarni jo‘natishga ruxsat beradi. Bu uzatishdan juda ko‘p foydalanish ko‘p xotiradan foydalanishga olib keladi va natijada planshet sekin yoki beqaror ishlashi mumkin."</string>
- <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"Ilovaga efir tugagandan so‘ng ham saqlanib qoladigan turg‘un translatsiyalarni uzatish huquqini beradi. Undan ortiqcha foydalanish televizoringizni sekinlatishi yoki ko‘p xotira sarflaydigan qilib qo‘yishi mumkin."</string>
- <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Ilovaga uzatish tugagandan keyin ham qoladigan yopishqoq uzatishlarni jo‘natishga ruxsat beradi. Bu uzatishdan juda ko‘p foydalanish ko‘p xotiradan foydalanishga olib keladi va natijada telefon sekin yoki beqaror ishlashi mumkin."</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Ilova yuborilganidan keyin o‘chib ketmaydigan muddatsiz tarqatma xabarlarni yuborishi mumkin. Ulardan noto‘g‘ri maqsadda foydalanish qurilmaning ishlashini sekinlatishi yoki xotiraga haddan ziyod yuklanish tushishi oqibatida qurilma ishdan chiqishi mumkin."</string>
+ <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"Ilova yuborilganidan keyin o‘chib ketmaydigan muddatsiz tarqatma xabarlarni yuborishi mumkin. Ulardan noto‘g‘ri maqsadda foydalanish qurilmaning ishlashini sekinlatishi yoki xotiraga haddan ziyod yuklanish tushishi oqibatida qurilma ishdan chiqishi mumkin."</string>
+ <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Ilova yuborilganidan keyin o‘chib ketmaydigan muddatsiz tarqatma xabarlarni yuborishi mumkin. Ulardan noto‘g‘ri maqsadda foydalanish qurilmaning ishlashini sekinlatishi yoki xotiraga haddan ziyod yuklanish tushishi oqibatida qurilma ishdan chiqishi mumkin."</string>
<string name="permlab_readContacts" msgid="8348481131899886131">"kontaktlaringizni ko‘rish"</string>
<string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Ilovaga planshetingizda saqlangan kontaktlar ma’lumotlarini, shuningdek, ba‘zi shaxslarga qilgan qo‘ng‘iroqlar muntazamligi, ularga yozgan e-pochta xabarlari yoki boshqa xabar almashish yo‘llari orqali xabarlashganingiz haqidagi ma’lumotlarni o‘qishga ruxsat beradi. Ushbu ruxsat ilovalarga aloqa ma’lumotlaringizni saqlash uchun ruxsat beradi va zararli ilovalar sizga bildirmasdan kontaktlar ma’lumotlaringizni boshqalarga ulashishi mumkin."</string>
<string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"Ilovaga televizoringizda saqlanayotgan kontaktlar haqidagi ma’lumotlarni, jumladan, muayyan shaxslar bilan qo‘ng‘iroqlashish, e-pochta orqali xabarlashish yoki muloqot qilish oralig‘i haqidagi ma’lumotlarni o‘qish huquqini beradi. Ushbu ruxsatnoma ilovalarga kontaktlaringiz haqidagi ma’lumotlarni saqlash huquqini berib, zararli ilovalar uning yordamida kontakt ma’lumotlarini sizdan beruxsat boshqalarga ulashishi mumkin."</string>
@@ -486,7 +486,7 @@
<string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"tarmoq siyosatini boshqarish"</string>
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Ilova tarmoq siyosatini boshqarishi va alohida ilovalar uchun qoidalarni o‘rnatishi mumkin."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"tarmoqdan foydalanishni hisoblashni o‘zgartirish"</string>
- <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ilovaga ilovalarga nisbadan hisoblanadigan tarmoqdan foydalanish ma’lumotlarini o‘zgartirishga ruxsat beradi. Oddiy ilovalar tomonidan foydalanilmaydi."</string>
+ <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ilova turli dasturlar tomonidan ishlatiladigan tarmoq resurslari hisob-kitobini o‘zgartirishi mumkin. Bu ruxsat oddiy ilovalar uchun talab qilinmaydi."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"ruxsat bildirishnomalari"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Dasturga bildirishnomalar va boshqa dasturlar jo‘natgan xabarlarni qabul qilish, ko‘rib chiqish hamda tozalash imkonini beradi."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bildirishnomani tinglash xizmatiga bog‘lash"</string>
@@ -526,7 +526,7 @@
<string name="policydesc_resetPassword" msgid="1278323891710619128">"Ekran qulfini o‘zgartiradi."</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"Ekranni qulflash"</string>
<string name="policydesc_forceLock" msgid="1141797588403827138">"Ekranning qachon va qanday qulflanishini boshqaradi."</string>
- <string name="policylab_wipeData" msgid="3910545446758639713">"Barcha ma’lumotlarni tozalash"</string>
+ <string name="policylab_wipeData" msgid="3910545446758639713">"Barcha ma’lumotlarni o‘chirib tashlash"</string>
<string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Planshetdagi barcha ma’lumotlarni ogohlantirishsiz zavod sozlamalarini tiklash orqali o‘chirib tashlaydi."</string>
<string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Zavod sozlamalarini tiklaydi va televizordagi barcha ma’lumotlarni ogohlantirishsiz o‘chirib tashlaydi."</string>
<string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Telefondagi barcha ma’lumotlarni ogohlantirishsiz zavod sozlamalarini tiklash orqali o‘chirib tashlaydi."</string>
@@ -537,7 +537,7 @@
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Qurilmaga global proksi o‘rnatish"</string>
<string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Qoida faollashtirilgan vaqtda ishlatiladigan qurilmaning global proksi-serverini o‘rnatadi. Faqat qurilma egasi global proksi-serverini o‘rnatishi mumkin."</string>
<string name="policylab_expirePassword" msgid="5610055012328825874">"Parol muddatini o‘rnatish"</string>
- <string name="policydesc_expirePassword" msgid="5367525762204416046">"Ekran qulfi paroli, PIN kodi yoki chizmali paroli o‘zgartiriladigan muddatni o‘zgartiradi."</string>
+ <string name="policydesc_expirePassword" msgid="5367525762204416046">"Ekran qulfi paroli, PIN kodi yoki grafik kaliti o‘zgartiriladigan muddatni o‘zgartiradi."</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Xotirani kodlashni o‘rnatish"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Zaxiralangan ilovalar ma‘lumotlarini kodlashni talab qiladi."</string>
<string name="policylab_disableCamera" msgid="6395301023152297826">"Kameralarni o‘chirish"</string>
@@ -672,7 +672,7 @@
<string name="lockscreen_screen_locked" msgid="7288443074806832904">"Ekran qulflangan."</string>
<string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Qulfdan chiqarish yoki favqulodda qo‘ng‘iroqni amalga oshirish uchun \"Menyu\"ni bosing."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Qulfni ochish uchun \"Menyu\"ga bosing."</string>
- <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Qulfni ochish uchun namuna ustiga chizing"</string>
+ <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Qulfni ochish uchun grafik kalitni chizing"</string>
<string name="lockscreen_emergency_call" msgid="5298642613417801888">"Favqulodda chaqiruv"</string>
<string name="lockscreen_return_to_call" msgid="5244259785500040021">"Qo‘ng‘iroqni qaytarish"</string>
<string name="lockscreen_pattern_correct" msgid="9039008650362261237">"To‘g‘ri!"</string>
@@ -700,12 +700,12 @@
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Foydalanuvchi qo‘llanmasiga qarang yoki Abonentlarni qo‘llab-quvvatlash markaziga murojaat qiling."</string>
<string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM karta qulflangan."</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM karta qulfdan chiqarilmoqda…"</string>
- <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urining."</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urining."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Siz parolni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urining."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Siz PIN-kodni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urining."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Telefon qulfini ochish uchun yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri urinish qilsangiz, sizdan Google hisobingizga kirish talab qilinadi. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qayta urining."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizni qulfdan chiqarish uchun Google hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qaytadan urining."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Telefon qulfini ochish uchun yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri urinish qilsangiz, sizdan Google hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qayta urining."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Telefon qulfini ochish uchun yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri urinish qilsangiz, sizdan Google hisobingizga kirish talab qilinadi. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qayta urining."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizni qulfdan chiqarish uchun Google hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qaytadan urining."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Telefon qulfini ochish uchun yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri urinish qilsangiz, sizdan Google hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qayta urining."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Planshet qulfini <xliff:g id="NUMBER_0">%1$d</xliff:g> marta ochishga urinib ko‘rdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishlardan so‘ng, planshet ishlab chiqarilgan holatiga tiklanadi va barcha foydalanuvchi ma’lumotlari yo‘qoladi."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Siz televizorni qulfdan chiqarish parolini <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizda zavod sozlamalari qayta tiklanadi hamda undagi barcha ma’lumotlaringiz o‘chib ketadi."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Telefon qulfini <xliff:g id="NUMBER_0">%1$d</xliff:g> marta ochishga urinib ko‘rdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishlardan so‘ng, telefon ishlab chiqarilgan holatiga tiklanadi va barcha foydalanuvchi ma’lumotlari yo‘qoladi."</string>
@@ -713,9 +713,9 @@
<string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Siz televizorni qulfdan chiqarish parolini <xliff:g id="NUMBER">%d</xliff:g> marta noto‘g‘ri kiritdingiz. Endi, televizoringizda zavod sozlamalari qayta tiklanadi."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Telefon qulfini <xliff:g id="NUMBER">%d</xliff:g> marta ochishga urinib ko‘rdingiz. Telefon hozir ishlab chiqarilgan holatiga tiklanadi."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
- <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Chizma namunasi yodingizdan chiqdimi?"</string>
+ <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Grafik kalit esingizdan chiqdimi?"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Qulfni ochish hisobi"</string>
- <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Chizmali parolni ochishga juda ko‘p urinildi"</string>
+ <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Grafik kalit juda ko‘p marta chizildi"</string>
<string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Qulfni ochish uchun Google hisobingiz bilan kiring."</string>
<string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Foydalanuvchi nomi (e-pochta)"</string>
<string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Parol"</string>
@@ -726,12 +726,12 @@
<string name="lockscreen_unlock_label" msgid="737440483220667054">"Qulfdan chiqarish"</string>
<string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Ovozni yoqish"</string>
<string name="lockscreen_sound_off_label" msgid="996822825154319026">"Ovozni o‘chirish"</string>
- <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Chizma namunasi ishga tushirildi"</string>
- <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Chizma namunasi tozalandi"</string>
+ <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"Grafik kalitni chizish boshlandi"</string>
+ <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Grafik kalit tozalandi"</string>
<string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Katak qo‘shildi"</string>
<string name="lockscreen_access_pattern_cell_added_verbose" msgid="7264580781744026939">"<xliff:g id="CELL_INDEX">%1$s</xliff:g> katak qo‘shildi"</string>
- <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Chizma namunasi tugatildi"</string>
- <string name="lockscreen_access_pattern_area" msgid="400813207572953209">"Chizmali kalit hududi."</string>
+ <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Grafik kalitni chizish tugallandi"</string>
+ <string name="lockscreen_access_pattern_area" msgid="400813207572953209">"Grafik kalit chiziladigan hudud."</string>
<string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Vidjet %2$d / %3$d."</string>
<string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Vidjet qo‘shish."</string>
<string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Bo‘sh"</string>
@@ -747,11 +747,11 @@
<string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> vidjeti o‘chirildi."</string>
<string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Qulfni ochish maydonini kengaytirish."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Qulfni silab ochish"</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Chizmali qulfni ochish."</string>
+ <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Grafik kalit bilan ochish."</string>
<string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Qulfni yuzni tanitib ochish"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin qulfini ochish."</string>
<string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Parolli qulfni ochish."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Chizmali qulf maydoni."</string>
+ <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Grafik kalit chiziladigan hudud."</string>
<string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Maydonni silang"</string>
<string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
<string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Masshtab"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Doimo ko‘rsatish"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Uni Tizim sozlamalari &gt; Ilovalar &gt; Yuklab olingan menyusidan qayta yoqing."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"“<xliff:g id="APP_NAME">%1$s</xliff:g>” ilovasi joriy ekran o‘lchami sozlamalariga mos kelmasligi va noto‘g‘ri ishlashi mumkin."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Har doim ko‘rsatilsin"</string>
<string name="smv_application" msgid="3307209192155442829">"“<xliff:g id="APPLICATION">%1$s</xliff:g>” ilovasi (jarayaon: <xliff:g id="PROCESS">%2$s</xliff:g>) o‘zining StrictMode qoidasini buzdi."</string>
<string name="smv_process" msgid="5120397012047462446">"<xliff:g id="PROCESS">%1$s</xliff:g> jarayoni o‘zining o‘zi-bajaruvchi StrictMode siyosatini buzdi."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android yangilanmoqda…"</string>
@@ -1151,7 +1153,7 @@
<string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
<string name="candidates_style" msgid="4333913089637062257"><u>"nomzodlar"</u></string>
<string name="ext_media_checking_notification_title" msgid="5734005953288045806">"<xliff:g id="NAME">%s</xliff:g> tayyorlanmoqda"</string>
- <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Xatolar tekshirilmoqda"</string>
+ <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"Xatolar qidirilmoqda"</string>
<string name="ext_media_new_notification_message" msgid="7589986898808506239">"Yangi <xliff:g id="NAME">%s</xliff:g> kartasi aniqlandi"</string>
<string name="ext_media_ready_notification_message" msgid="4083398150380114462">"Rasm va boshqa fayllarni o‘tkazish"</string>
<string name="ext_media_unmountable_notification_title" msgid="8295123366236989588">"“<xliff:g id="NAME">%s</xliff:g>” buzilgan"</string>
@@ -1193,8 +1195,7 @@
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"Ilovaga o‘rnatilgan seanslarni o‘qish uchun ruxsat beradi. Bu unga faol paket o‘rnatmalari haqidagi ma’lumotlarni ko‘rish imkonini beradi."</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"paketlarni o‘rnatish so‘rovini yuborish"</string>
<string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Ilovaga paketlarni o‘rnatish so‘rovini yuborish imkonini beradi."</string>
- <!-- no translation found for tutorial_double_tap_to_zoom_message_short (1311810005957319690) -->
- <skip />
+ <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Ko‘lamini o‘zgartirish uchun ikki marta bosing"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"Vidjet qo‘shilmadi."</string>
<string name="ime_action_go" msgid="8320845651737369027">"O‘tish"</string>
<string name="ime_action_search" msgid="658110271822807811">"Qidirish"</string>
@@ -1225,10 +1226,8 @@
<string name="notification_ranker_binding_label" msgid="774540592299064747">"Bildirishnomalarni baholash xizmati"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN faollashtirildi"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> tomonidan faollashtirilgan"</string>
- <!-- no translation found for vpn_text (1610714069627824309) -->
- <skip />
- <!-- no translation found for vpn_text_long (4907843483284977618) -->
- <skip />
+ <string name="vpn_text" msgid="1610714069627824309">"Tarmoq sozlamalarini o‘zgartirish uchun bu yerni bosing."</string>
+ <string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> ulandi. Tarmoq sozlamalarini o‘zgartirish uchun bu yerni bosing."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Ulanmoqda…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Ulandi"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Xato"</string>
@@ -1368,7 +1367,7 @@
<string name="media_route_chooser_searching" msgid="4776236202610828706">"Qurilmalar izlanmoqda..."</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Sozlamalar"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"Uzish"</string>
- <string name="media_route_status_scanning" msgid="7279908761758293783">"Tekshirilmoqda..."</string>
+ <string name="media_route_status_scanning" msgid="7279908761758293783">"Qidirilmoqda..."</string>
<string name="media_route_status_connecting" msgid="6422571716007825440">"Ulanmoqda..."</string>
<string name="media_route_status_available" msgid="6983258067194649391">"Mavjud"</string>
<string name="media_route_status_not_available" msgid="6739899962681886401">"Mavjud emas"</string>
@@ -1378,8 +1377,8 @@
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Tasvir uzatish #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
<string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", xavfsiz"</string>
- <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Chizmali parol unutilgan"</string>
- <string name="kg_wrong_pattern" msgid="1850806070801358830">"Chizmali kalit noto‘g‘ri"</string>
+ <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Grafik kalit esimdan chiqdi"</string>
+ <string name="kg_wrong_pattern" msgid="1850806070801358830">"Grafik kalit noto‘g‘ri"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"Parol noto‘g‘ri"</string>
<string name="kg_wrong_pin" msgid="1131306510833563801">"PIN-kod noto‘g‘ri"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
@@ -1396,7 +1395,7 @@
<string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"PUK kod 8 ta raqam bo‘lishi shart."</string>
<string name="kg_invalid_puk" msgid="3638289409676051243">"To‘g‘ri PUK kodni qayta kiriting. Qayta-qayta urinishlar SIM kartani butunlay o‘chirib qo‘yadi."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN-kod mos kelmadi"</string>
- <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Chizmali parolni ochishga juda ko‘p urinildi"</string>
+ <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Grafik kalit juda ko‘p marta chizildi"</string>
<string name="kg_login_instructions" msgid="1100551261265506448">"Qulfni ochish uchun Google hisobingiz bilan kiring."</string>
<string name="kg_login_username_hint" msgid="5718534272070920364">"Foydalanuvchi nomi (e-pochta)"</string>
<string name="kg_login_password_hint" msgid="9057289103827298549">"Parol"</string>
@@ -1406,16 +1405,16 @@
<string name="kg_login_checking_password" msgid="1052685197710252395">"Hisob tekshirilmoqda…"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Siz PIN-kodni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Siz parolni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
- <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Siz planshet qulfini ochish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta muvaffaqiyatsiz urindingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishlardan so‘ng planshetning zavod sozlamalari tiklanadi va barcha foydalanuvchi ma’lumotlari o‘chiriladi."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"Siz televizorni qulfdan chiqarish parolini <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizda zavod sozlamalari qayta tiklanadi hamda undagi barcha ma’lumotlaringiz o‘chib ketadi."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Siz telefon qulfini ochish uchun <xliff:g id="NUMBER_0">%1$d</xliff:g> marta muvaffaqiyatsiz urindingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishlardan so‘ng telefonning zavod sozlamalari tiklanadi va barcha foydalanuvchi ma’lumotlari o‘chiriladi."</string>
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Planshet qulfini ochish uchun <xliff:g id="NUMBER">%d</xliff:g> marta muvaffaqiyatsiz urinib ko‘rdingiz. Planshetning hozir zavod sozlamari tiklanadi."</string>
<string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Siz televizorni qulfdan chiqarish parolini <xliff:g id="NUMBER">%d</xliff:g> marta noto‘g‘ri kiritdingiz. Endi, televizoringizda zavod sozlamalari qayta tiklanadi."</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Telefon qulfini ochish uchun <xliff:g id="NUMBER">%d</xliff:g> marta muvaffaqiyatsiz urinib ko‘rdingiz. Telefonning hozir zavod sozlamari tiklanadi."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, planshet qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizni qulfdan chiqarish uchun sizda e-pochta hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qaytadan urining."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Siz chizmali kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri chizdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, telefon qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, planshet qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri kiritdingiz. Agar uni yana <xliff:g id="NUMBER_1">%2$d</xliff:g> marta noto‘g‘ri kiritsangiz, televizoringizni qulfdan chiqarish uchun sizda e-pochta hisobingizga kirish talab qilinadi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng qaytadan urining."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri chizdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, telefon qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"O‘chirish"</string>
<string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Ovoz balandligi tavsiya etilgan darajadan ham yuqori ko‘tarilsinmi?\n\nUzoq vaqt davomida baland ovozda tinglash eshitish qobiliyatingizga salbiy ta’sir ko‘rsatishi mumkin."</string>
@@ -1550,7 +1549,7 @@
<string name="lock_to_app_start" msgid="6643342070839862795">"Ekran qadab qo‘yildi"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Ekran bo‘shatildi"</string>
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Yechishda PIN-kod so‘ralsin"</string>
- <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Bo‘shatishdan oldin chizmali parol so‘ralsin"</string>
+ <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Yechishdan oldin grafik kalit so‘ralsin"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bo‘shatishdan oldin parol so‘ralsin"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Administratoringiz tomonidan o‘rnatilgan"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Administratoringiz tomonidan yangilandi"</string>
@@ -1652,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Olib tashlash"</string>
<string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Yangi seans"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Yangi demo-seans boshlash uchun bosing"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Demo boshlanmoqda"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Seans qayta boshlanmoqda"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Bu qurilmadan cheklovlarsiz foydalanish uchun zavod sozlamalarini tiklang"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ko‘proq o‘rganish uchun bosing."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> vidjeti o‘chirilgan"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index a2a3143caa55..abfa6db2795d 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Tỷ lệ"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Luôn hiển thị"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Bật lại chế độ này trong cài đặt Hệ thống &gt; Ứng dụng &gt; Đã tải xuống."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> không hỗ trợ cài đặt kích thước Màn hình hiện tại và có thể hoạt động không như mong đợi."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Luôn hiển thị"</string>
<string name="smv_application" msgid="3307209192155442829">"Ứng dụng <xliff:g id="APPLICATION">%1$s</xliff:g> (quá trình <xliff:g id="PROCESS">%2$s</xliff:g>) đã vi phạm chính sách StrictMode tự thi hành của mình."</string>
<string name="smv_process" msgid="5120397012047462446">"Quá trình <xliff:g id="PROCESS">%1$s</xliff:g> đã vi phạm chính sách StrictMode tự thi hành của mình."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android đang nâng cấp..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"Bỏ ghim"</string>
<string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Khởi động lại phiên"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Nhấn để bắt đầu phiên trình diễn mới"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Bắt đầu bản trình diễn"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Bắt đầu lại phiên"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"Khôi phục cài đặt gốc để sử dụng thiết bị này mà không bị hạn chế"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Chạm để tìm hiểu thêm."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"Đã tắt <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rCN-watch/styles_material.xml b/core/res/res/values-zh-rCN-watch/styles_material.xml
new file mode 100644
index 000000000000..36a459dc16a0
--- /dev/null
+++ b/core/res/res/values-zh-rCN-watch/styles_material.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<!--
+===============================================================
+ PLEASE READ
+===============================================================
+
+The Material themes must not be modified in order to pass CTS.
+Many related themes and styles depend on other values defined in this file.
+If you would like to provide custom themes and styles for your device,
+please see styles_device_defaults.xml.
+
+===============================================================
+ PLEASE READ
+===============================================================
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="candidates_style" msgid="8052530148128607468"><font color="#80cbc4">"candidates"</font></string>
+</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c7462f11149a..6485b45b0453 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"缩放"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"始终显示"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"在“系统设置”&gt;“应用”&gt;“已下载”中重新启用此模式。"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g>不支持当前的显示大小设置,因此可能无法正常显示。"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"一律显示"</string>
<string name="smv_application" msgid="3307209192155442829">"“<xliff:g id="APPLICATION">%1$s</xliff:g>”应用(<xliff:g id="PROCESS">%2$s</xliff:g> 进程)违反了自我强制执行的严格模式 (StrictMode) 政策。"</string>
<string name="smv_process" msgid="5120397012047462446">"进程 <xliff:g id="PROCESS">%1$s</xliff:g> 违反了自我强制执行的严格模式 (StrictMode) 政策。"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android正在升级..."</string>
@@ -1649,10 +1651,22 @@
<string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
<string name="app_info" msgid="6856026610594615344">"应用信息"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"重新启动会话"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"点按即可启动新的演示会话"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"正在启动演示模式"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"正在重新启动会话"</string>
+ <!-- no translation found for reset_retail_demo_mode_title (2370249087943803584) -->
+ <skip />
+ <!-- no translation found for reset_retail_demo_mode_text (5481925817590883246) -->
+ <skip />
+ <!-- no translation found for demo_starting_message (5268556852031489931) -->
+ <skip />
+ <!-- no translation found for demo_restarting_message (952118052531642451) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_title (6596109959002331334) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_countdown (1743456683091721620) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_left_button (5314271347014802475) -->
+ <skip />
+ <!-- no translation found for demo_user_inactivity_timeout_right_button (5019306703066964808) -->
+ <skip />
<string name="audit_safemode_notification" msgid="6416076898350685856">"恢复出厂设置即可正常使用此设备,不受任何限制"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"触摸即可了解详情。"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"已停用的<xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index a791ccd6785e..c5186bceb54f 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"比例"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"永遠顯示"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"前往 [系統設定] &gt; [應用程式] &gt; [下載] 重新啟用這個模式。"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援目前的「螢幕」尺寸設定,畫面可能無法如預期顯示。"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"永遠顯示"</string>
<string name="smv_application" msgid="3307209192155442829">"應用程式 <xliff:g id="APPLICATION">%1$s</xliff:g> (處理程序 <xliff:g id="PROCESS">%2$s</xliff:g>) 已違反其自行強制實施的嚴格模式 (StrictMode) 政策。"</string>
<string name="smv_process" msgid="5120397012047462446">"處理程序 <xliff:g id="PROCESS">%1$s</xliff:g> 已違反其自行強制實施的嚴格模式 (StrictMode) 政策。"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"正在升級 Android..."</string>
@@ -1649,10 +1651,14 @@
<string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
<string name="app_info" msgid="6856026610594615344">"應用程式資料"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"重新開始時段"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"輕按即可開始新示範時段"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"正在開始示範"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"正在重新開始示範時段"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"要重設裝置嗎?"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"輕觸即可重設裝置"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"正在啟動示範模式..."</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"正在重設裝置..."</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"要重設裝置嗎?"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"系統不會儲存您所做的變更,示範模式將於 <xliff:g id="TIMEOUT">%1$s</xliff:g> 秒後重新開始…"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"取消"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"立即重設"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"將此裝置回復至原廠設定後,使用將不受限制"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"輕觸以瞭解詳情。"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"「<xliff:g id="LABEL">%1$s</xliff:g>」已停用"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index ec7b2fdc281a..3a1209efe985 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"比例"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"一律顯示"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"前往 [系統設定] &gt; [應用程式] &gt; [下載] 重新啟用這個模式。"</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援目前的顯示大小設定,可能會發生非預期的行為。"</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"一律顯示"</string>
<string name="smv_application" msgid="3307209192155442829">"應用程式 <xliff:g id="APPLICATION">%1$s</xliff:g> (處理程序 <xliff:g id="PROCESS">%2$s</xliff:g>) 已違反其自行強制實施的嚴格模式 (StrictMode) 政策。"</string>
<string name="smv_process" msgid="5120397012047462446">"處理程序 <xliff:g id="PROCESS">%1$s</xliff:g> 已違反其自行強制實施的嚴格模式 (StrictMode) 政策。"</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"正在升級 Android…"</string>
@@ -1649,10 +1651,14 @@
<string name="unpin_target" msgid="3556545602439143442">"取消固定"</string>
<string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"重新啟動工作階段"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"輕觸即可啟動新的示範工作階段"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"正在啟動示範模式"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"正在重新啟動工作階段"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"要重設裝置嗎?"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"輕觸即可重設裝置"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"正在啟動示範模式..."</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"正在重設裝置..."</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"要重設裝置嗎?"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"系統不會儲存您所做的變更,示範模式將於 <xliff:g id="TIMEOUT">%1$s</xliff:g> 秒後重新開始…"</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"取消"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"立即重設"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"恢復原廠設定即可正常使用這個裝置"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"輕觸即可瞭解詳情。"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"已停用的<xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6f5a6ea301d4..c7a4c06c3b70 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1015,6 +1015,8 @@
<string name="screen_compat_mode_scale" msgid="3202955667675944499">"Isilinganisi"</string>
<string name="screen_compat_mode_show" msgid="4013878876486655892">"Bonisa njalo"</string>
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"Yenza kuphinde kusebenze kuzilungiselelo Zesistimue &gt; Izinhlelo zokusebenza &gt; Okulayishiwe."</string>
+ <string name="unsupported_display_size_message" msgid="6545327290756295232">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> ayisekeli isilungiselelo sosayizi sokubonisa samanje futhi ingasebenza ngokungalindelekile."</string>
+ <string name="unsupported_display_size_show" msgid="7969129195360353041">"Bonisa njalo"</string>
<string name="smv_application" msgid="3307209192155442829">"Inqubo <xliff:g id="APPLICATION">%1$s</xliff:g> (yohlelo <xliff:g id="PROCESS">%2$s</xliff:g>) iphule inqubomgomo oziphoqelela yona Yemodi Ebukhali."</string>
<string name="smv_process" msgid="5120397012047462446">"Inqubo <xliff:g id="PROCESS">%1$s</xliff:g> yephule inqubomgomo yokuziphoqelela Yemodi Ebukhali."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"I-Android ifaka ezakamuva..."</string>
@@ -1649,10 +1651,14 @@
<string name="unpin_target" msgid="3556545602439143442">"Susa ukuphina"</string>
<string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="reset_retail_demo_mode_title" msgid="2187220736280147886">"Qalisa kabusha isikhathi"</string>
- <string name="reset_retail_demo_mode_text" msgid="5687062656885515019">"Thepha ukuze uqale isikhathi esisha sedemo"</string>
- <string name="demo_starting_message" msgid="7574017688324606624">"Ukuqalisa idemo"</string>
- <string name="demo_restarting_message" msgid="1363894248779727028">"Ukuqalisa kabusha iseshini"</string>
+ <string name="reset_retail_demo_mode_title" msgid="2370249087943803584">"Setha kabusha idivayisi?"</string>
+ <string name="reset_retail_demo_mode_text" msgid="5481925817590883246">"Thepha ukuze usethe kabusha idivayisi"</string>
+ <string name="demo_starting_message" msgid="5268556852031489931">"Iqalisa i-demo..."</string>
+ <string name="demo_restarting_message" msgid="952118052531642451">"Isetha kabusha idivayisi..."</string>
+ <string name="demo_user_inactivity_timeout_title" msgid="6596109959002331334">"Setha kabusha idivayisi?"</string>
+ <string name="demo_user_inactivity_timeout_countdown" msgid="1743456683091721620">"Uzolahlekelwa inoma iluphi ushintsho futhi idemo izoqala futhi kumasekhondi angu-<xliff:g id="TIMEOUT">%1$s</xliff:g>..."</string>
+ <string name="demo_user_inactivity_timeout_left_button" msgid="5314271347014802475">"Khansela"</string>
+ <string name="demo_user_inactivity_timeout_right_button" msgid="5019306703066964808">"Setha kabusha manje"</string>
<string name="audit_safemode_notification" msgid="6416076898350685856">"Setha kabusha ukuze usebenzise idivayisi ngaphandle kwemikhawulo"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Thinta ukuze ufunde kabanzi."</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"I-<xliff:g id="LABEL">%1$s</xliff:g> ekhutshaziwe"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 13e1d00458b2..a70c4fd1f97f 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1048,6 +1048,9 @@ i
the status bar (via statusBarColor) and navigation bar (via navigationBarColor). -->
<attr name="colorPrimaryDark" format="color" />
+ <!-- The secondary branding color for the app. -->
+ <attr name="colorSecondary" format="color" />
+
<!-- Bright complement to the primary branding color. By default, this is the color applied
to framework controls (via colorControlActivated). -->
<attr name="colorAccent" format="color" />
@@ -1832,10 +1835,10 @@ i
<enum name="KEYCODE_CUT" value="277" />
<enum name="KEYCODE_COPY" value="278" />
<enum name="KEYCODE_PASTE" value="279" />
- <enum name="KEYCODE_FP_NAV_UP" value="280" />
- <enum name="KEYCODE_FP_NAV_DOWN" value="281" />
- <enum name="KEYCODE_FP_NAV_LEFT" value="282" />
- <enum name="KEYCODE_FP_NAV_RIGHT" value="283" />
+ <enum name="KEYCODE_SYSTEM_NAVIGATION_UP" value="280" />
+ <enum name="KEYCODE_SYSTEM_NAVIGATION_DOWN" value="281" />
+ <enum name="KEYCODE_SYSTEM_NAVIGATION_LEFT" value="282" />
+ <enum name="KEYCODE_SYSTEM_NAVIGATION_RIGHT" value="283" />
</attr>
<!-- ***************************************************************** -->
@@ -7350,7 +7353,11 @@ i
<!-- Title of the uri that specifies a link for further context of this wallpaper, e.g. Explore collection. -->
<attr name="contextDescription" format="reference" />
- <!-- Whether to show any metadata when previewing the wallpaper. -->
+ <!-- Whether to show any metadata when previewing the wallpaper. If this value is
+ set to true, any component that shows a preview of this live wallpaper should also show
+ accompanying information like the title, the description, the author and the context
+ description of this wallpaper so the user gets to know further information about this
+ wallpaper. -->
<attr name="showMetadataInPreview" format="boolean" />
</declare-styleable>
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index e830b64094f4..5518de2d5c24 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -25,6 +25,7 @@
<color name="primary_dark_device_default_settings">@color/primary_dark_material_settings</color>
<color name="secondary_device_default_settings">@color/secondary_material_settings</color>
+ <color name="tertiary_device_default_settings">@color/tertiary_material_settings</color>
<color name="accent_device_default_light">@color/accent_material_light</color>
<color name="accent_device_default_dark">@color/accent_material_dark</color>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index a18abdf9712c..2ac4092a5079 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -33,6 +33,7 @@
<color name="primary_dark_material_settings">@color/material_blue_grey_950</color>
<color name="secondary_material_settings">@color/material_blue_grey_800</color>
+ <color name="tertiary_material_settings">@color/material_blue_grey_700</color>
<color name="accent_material_light">@color/material_deep_teal_500</color>
<color name="accent_material_dark">@color/material_deep_teal_200</color>
@@ -84,6 +85,7 @@
<color name="material_deep_teal_300">#ff4db6ac</color>
<color name="material_deep_teal_500">#ff009688</color>
+ <color name="material_blue_grey_700">#ff455a64</color>
<color name="material_blue_grey_800">#ff37474f</color>
<color name="material_blue_grey_900">#ff263238</color>
<color name="material_blue_grey_950">#ff21272b</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5fd3c36ed722..ebe48ce13c30 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2461,6 +2461,10 @@
<!-- True if the device supports Sustained Performance Mode-->
<bool name="config_sustainedPerformanceModeSupported">false</bool>
+ <!-- File used to enable the double touch gesture.
+ TODO: move to input HAL once ready. -->
+ <string name="config_doubleTouchGestureEnableFile"></string>
+
<!-- Controls how we deal with externally connected physical keyboards.
0 - When using this device, it is not clear for users to recognize when the physical
keyboard is (should be) connected and when it is (should be) disconnected. Most of
@@ -2487,7 +2491,7 @@
</string-array>
<!-- Component that is the default launcher when demo mode is enabled. -->
- <string name="config_demoModeLauncherComponent"></string>
+ <string name="config_demoModeLauncherComponent">com.android.retaildemo/.DemoPlayer</string>
<!-- Flag indicating whether round icons should be parsed from the application manifest. -->
<bool name="config_useRoundIcon">false</bool>
@@ -2495,4 +2499,6 @@
<!-- True if the device supports system navigation keys. -->
<bool name="config_supportSystemNavigationKeys">false</bool>
+ <!-- Package name for the device provisioning package. -->
+ <string name="config_deviceProvisioningPackage"></string>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c187d2ca7d88..9ccd39fa893e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2741,5 +2741,6 @@
<public type="attr" name="contextUri" />
<public type="attr" name="contextDescription" />
<public type="attr" name="showMetadataInPreview" />
+ <public type="attr" name="colorSecondary" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5db562d16134..a32faf8a8bce 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2768,6 +2768,11 @@
<!-- [CHAR LIMIT=200] Compat mode dialog: hint to re-enable compat mode dialog. -->
<string name="screen_compat_mode_hint">Re-enable this in System settings &gt; Apps &gt; Downloaded.</string>
+ <!-- [CHAR LIMIT=200] Unsupported display size dialog: message. Refers to "Display size" setting. -->
+ <string name="unsupported_display_size_message"><xliff:g id="app_name">%1$s</xliff:g> does not support the current Display size setting and may behave unexpectedly.</string>
+ <!-- [CHAR LIMIT=50] Unsupported display size dialog: check box label. -->
+ <string name="unsupported_display_size_show">Always show</string>
+
<!-- Text of the alert that is displayed when an application has violated StrictMode. -->
<string name="smv_application">The app <xliff:g id="application">%1$s</xliff:g>
(process <xliff:g id="process">%2$s</xliff:g>) has violated its self-enforced StrictMode policy.</string>
@@ -4367,15 +4372,21 @@
<string name="negative_duration">\u2212<xliff:g id="time" example="1:14">%1$s</xliff:g></string>
<!-- Title of notification to start a new demo session when device is in retail mode [CHAR LIMIT=NONE] -->
- <string name="reset_retail_demo_mode_title">Restart Session</string>
+ <string name="reset_retail_demo_mode_title">Reset device?</string>
<!-- Text of notification to start a new demo session when device is in retail mode [CHAR LIMIT=NONE] -->
- <string name="reset_retail_demo_mode_text">Tap to start a new demo session</string>
+ <string name="reset_retail_demo_mode_text">Tap to reset device</string>
<!-- Text of dialog shown when starting a demo user for the first time [CHAR LIMIT=40] -->
- <string name="demo_starting_message">Starting demo</string>
+ <string name="demo_starting_message">Starting demo\u2026</string>
<!-- Text of dialog shown when starting a new demo user in retail demo mode [CHAR LIMIT=40] -->
- <string name="demo_restarting_message">Restarting session</string>
-
-
+ <string name="demo_restarting_message">Resetting device\u2026</string>
+ <!-- Title of the dialog shown when user inactivity times out in retail demo mode [CHAR LIMIT=40] -->
+ <string name="demo_user_inactivity_timeout_title">Reset device?</string>
+ <!-- Warning message shown when user inactivity times out in retail demo mode [CHAR LIMIT=none] -->
+ <string name="demo_user_inactivity_timeout_countdown">You\u2019ll lose any changes and the demo will start again in <xliff:g id="timeout" example="9">%1$s</xliff:g> seconds\u2026</string>
+ <!-- Text of button to allow user to abort countdown and continue current session in retail demo mode [CHAR LIMIT=40] -->
+ <string name="demo_user_inactivity_timeout_left_button">Cancel</string>
+ <!-- Text of button to allow user to abort countdown and immediately start another session in retail demo mode [CHAR LIMIT=40] -->
+ <string name="demo_user_inactivity_timeout_right_button">Reset now</string>
<!-- Title of notification shown when device has been forced to safe mode after a security compromise. -->
<string name="audit_safemode_notification">Factory reset to use this device without restrictions</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 273086d5a35f..762cf31abd55 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1410,7 +1410,7 @@ please see styles_device_defaults.xml.
<item name="paddingEnd">?attr/dialogPreferredPadding</item>
<item name="background">?attr/selectableItemBackground</item>
<item name="drawablePadding">32dp</item>
- <item name="drawableTint">@color/accent_material_light</item>
+ <item name="drawableTint">?android:attr/colorAccent</item>
<item name="drawableTintMode">src_atop</item>
</style>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6e937ff48ccc..759ed32b7d31 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1892,6 +1892,10 @@
<java-symbol type="string" name="audit_safemode_notification_details" />
<java-symbol type="string" name="reset_retail_demo_mode_title" />
<java-symbol type="string" name="reset_retail_demo_mode_text" />
+ <java-symbol type="string" name="demo_user_inactivity_timeout_title" />
+ <java-symbol type="string" name="demo_user_inactivity_timeout_countdown" />
+ <java-symbol type="string" name="demo_user_inactivity_timeout_left_button" />
+ <java-symbol type="string" name="demo_user_inactivity_timeout_right_button" />
<java-symbol type="layout" name="resolver_list" />
<java-symbol type="id" name="resolver_list" />
@@ -2614,6 +2618,8 @@
<!-- Pinner Service -->
<java-symbol type="array" name="config_defaultPinnerServiceFiles" />
+ <java-symbol type="string" name="config_doubleTouchGestureEnableFile" />
+
<java-symbol type="string" name="suspended_widget_accessibility" />
<!-- Used internally for assistant to launch activity transitions -->
@@ -2623,4 +2629,10 @@
<!-- For System navigation keys -->
<java-symbol type="bool" name="config_supportSystemNavigationKeys" />
+
+ <java-symbol type="layout" name="unsupported_display_size_dialog_content" />
+ <java-symbol type="string" name="unsupported_display_size_message" />
+
+ <!-- Package name for the device provisioning package -->
+ <java-symbol type="string" name="config_deviceProvisioningPackage" />
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 998eea5ac9ab..5b2522f97c8b 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -57,6 +57,7 @@ please see themes_device_defaults.xml.
<item name="colorPrimaryDark">@color/legacy_primary_dark</item>
<item name="colorPrimary">@color/legacy_primary</item>
+ <item name="colorSecondary">?attr/colorPrimary</item>
<item name="colorControlActivated">@color/legacy_control_activated</item>
<item name="colorControlNormal">@color/legacy_control_normal</item>
<item name="colorControlHighlight">@color/legacy_button_pressed</item>
@@ -317,6 +318,7 @@ please see themes_device_defaults.xml.
<item name="activityChooserViewStyle">@style/Widget.ActivityChooserView</item>
<item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.MediaRouteButton</item>
<item name="fragmentBreadCrumbsStyle">@style/Widget.FragmentBreadCrumbs</item>
+ <item name="contextPopupMenuStyle">?attr/popupMenuStyle</item>
<!-- Preference styles -->
<item name="preferenceScreenStyle">@style/Preference.PreferenceScreen</item>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index e5b6c7830adf..50e588dfff7b 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -730,6 +730,51 @@ easier.
<!-- Color palette -->
<item name="colorPrimary">@color/primary_device_default_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+ <item name="colorSecondary">@color/secondary_device_default_settings</item>
+ <item name="colorAccent">@color/accent_device_default_light</item>
+ </style>
+
+ <!-- DeviceDefault theme for a window that should use Settings theme colors but has
+ a full dark palette (instead of Light with dark action bar like
+ Theme.DeviceDefault.Settings. -->
+ <style name="Theme.DeviceDefault.Settings.Dark" parent="Theme.Material">
+ <!-- Color palette -->
+ <item name="colorPrimary">@color/primary_device_default_settings</item>
+ <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+ <item name="colorSecondary">@color/secondary_device_default_settings</item>
+ <item name="colorAccent">@color/accent_device_default_dark</item>
+ </style>
+
+ <!-- Variant of {@link #Theme_DeviceDefault_Settings_Dark} with no action bar -->
+ <style name="Theme.DeviceDefault.Settings.Dark.NoActionBar" parent="Theme.Material.NoActionBar">
+ <!-- Color palette -->
+ <item name="colorPrimary">@color/primary_device_default_settings</item>
+ <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+ <item name="colorSecondary">@color/secondary_device_default_settings</item>
+ <item name="colorAccent">@color/accent_device_default_dark</item>
+ </style>
+
+ <style name="Theme.DeviceDefault.Settings.Dialog" parent="Theme.Material.Settings.Dialog">
+ <!-- Color palette -->
+ <item name="colorPrimary">@color/primary_device_default_settings</item>
+ <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+ <item name="colorSecondary">@color/secondary_device_default_settings</item>
+ <item name="colorAccent">@color/accent_device_default_light</item>
+ </style>
+
+ <style name="Theme.DeviceDefault.Settings.DialogWhenLarge" parent="Theme.Material.Settings.DialogWhenLarge">
+ <!-- Color palette -->
+ <item name="colorPrimary">@color/primary_device_default_settings</item>
+ <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+ <item name="colorSecondary">@color/secondary_device_default_settings</item>
+ <item name="colorAccent">@color/accent_device_default_light</item>
+ </style>
+
+ <style name="Theme.DeviceDefault.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.Alert">
+ <!-- Color palette -->
+ <item name="colorPrimary">@color/primary_device_default_settings</item>
+ <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+ <item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_light</item>
</style>
@@ -753,4 +798,19 @@ easier.
<!-- DeviceDefault theme for the default system theme. -->
<style name="Theme.DeviceDefault.System" parent="Theme.DeviceDefault.Light.DarkActionBar" />
+
+ <style name="ThemeOverlay.DeviceDefault" />
+
+ <style name="ThemeOverlay.DeviceDefault.Accent">
+ <item name="colorAccent">@color/accent_device_default_dark</item>
+ </style>
+
+ <style name="ThemeOverlay.DeviceDefault.Accent.Light">
+ <item name="colorAccent">@color/accent_device_default_light</item>
+ </style>
+
+ <style name="ThemeOverlay.DeviceDefault.Dark.ActionBar.Accent" parent="ThemeOverlay.Material.Dark.ActionBar">
+ <item name="colorAccent">@color/accent_device_default_dark</item>
+ </style>
+
</resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index d437032b0405..35ce9b049854 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1305,6 +1305,7 @@ please see themes_device_defaults.xml.
<style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar">
<item name="colorPrimary">@color/primary_material_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
+ <item name="colorSecondary">@color/secondary_material_settings</item>
<item name="presentationTheme">@style/Theme.Material.Settings.Dialog.Presentation</item>
<item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item>
@@ -1315,6 +1316,7 @@ please see themes_device_defaults.xml.
<style name="Theme.Material.Settings.NoActionBar" parent="Theme.Material.Light.NoActionBar">
<item name="colorPrimary">@color/primary_material_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
+ <item name="colorSecondary">@color/secondary_material_settings</item>
<item name="presentationTheme">@style/Theme.Material.Settings.Dialog.Presentation</item>
<item name="searchDialogTheme">@style/Theme.Material.Settings.SearchBar</item>
@@ -1324,6 +1326,7 @@ please see themes_device_defaults.xml.
<style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.Light.BaseDialog">
<item name="colorPrimary">@color/primary_material_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
+ <item name="colorSecondary">@color/secondary_material_settings</item>
</style>
<style name="Theme.Material.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog" />
@@ -1331,6 +1334,7 @@ please see themes_device_defaults.xml.
<style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert">
<item name="colorPrimary">@color/primary_material_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
+ <item name="colorSecondary">@color/secondary_material_settings</item>
</style>
<style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert" />
@@ -1338,25 +1342,30 @@ please see themes_device_defaults.xml.
<style name="Theme.Material.Settings.DialogWhenLarge" parent="Theme.Material.Light.DialogWhenLarge.DarkActionBar">
<item name="colorPrimary">@color/primary_material_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
+ <item name="colorSecondary">@color/secondary_material_settings</item>
</style>
<style name="Theme.Material.Settings.DialogWhenLarge.NoActionBar" parent="Theme.Material.Light.DialogWhenLarge.NoActionBar">
<item name="colorPrimary">@color/primary_material_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
+ <item name="colorSecondary">@color/secondary_material_settings</item>
</style>
<style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
<item name="colorPrimary">@color/primary_material_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
+ <item name="colorSecondary">@color/secondary_material_settings</item>
</style>
<style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.Light.SearchBar">
<item name="colorPrimary">@color/primary_material_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
+ <item name="colorSecondary">@color/secondary_material_settings</item>
</style>
<style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.Light.CompactMenu">
<item name="colorPrimary">@color/primary_material_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_material_settings</item>
+ <item name="colorSecondary">@color/secondary_material_settings</item>
</style>
</resources>
diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
index 39a29074acde..f088197609a8 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
@@ -23,6 +23,8 @@ import android.support.test.filters.SmallTest;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Display;
+import android.view.DisplayAdjustments;
+
import junit.framework.TestCase;
public class ResourcesManagerTest extends TestCase {
@@ -58,7 +60,7 @@ public class ResourcesManagerTest extends TestCase {
}
@Override
- protected DisplayMetrics getDisplayMetrics(int displayId) {
+ protected DisplayMetrics getDisplayMetrics(int displayId, DisplayAdjustments daj) {
return mDisplayMetrics;
}
};
diff --git a/core/tests/notificationtests/src/android/app/NotificationStressTest.java b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
index 6e86c37f65f8..f1740148ead6 100644
--- a/core/tests/notificationtests/src/android/app/NotificationStressTest.java
+++ b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
@@ -40,9 +40,9 @@ public class NotificationStressTest extends InstrumentationTestCase {
private static final int NUM_ITERATIONS = 200;
private static final int NUM_ITERATIONS_2 = 30;
private static final int LONG_TIMEOUT = 2000;
- // 50 notifications per app: defined as Variable MAX_PACKAGE_NOTIFICATIONS in
+ // 49 notifications per app: defined as Variable MAX_PACKAGE_NOTIFICATIONS in
// NotificationManagerService.java
- private static final int MAX_NOTIFCATIONS = 50;
+ private static final int MAX_NOTIFCATIONS = 49;
private static final int[] ICONS = new int[] {
android.R.drawable.stat_notify_call_mute,
android.R.drawable.stat_notify_chat,
@@ -76,9 +76,10 @@ public class NotificationStressTest extends InstrumentationTestCase {
@Override
protected void tearDown() throws Exception {
- super.tearDown();
mDevice.unfreezeRotation();
mNotificationManager.cancelAll();
+ mDevice.waitForIdle();
+ super.tearDown();
}
@RepetitiveTest(numIterations = NUM_ITERATIONS)
@@ -97,7 +98,7 @@ public class NotificationStressTest extends InstrumentationTestCase {
for (int j = 0; j < MAX_NOTIFCATIONS; j++) {
sendNotification(mNotifyId++, "testNotificationStressNotify");
}
- Thread.sleep(500);
+ Thread.sleep(LONG_TIMEOUT);
assertTrue(mNotificationManager.getActiveNotifications().length == MAX_NOTIFCATIONS);
for (int j = 0; j < MAX_NOTIFCATIONS; j++) {
mNotificationManager.cancel(--mNotifyId);
@@ -124,7 +125,8 @@ public class NotificationStressTest extends InstrumentationTestCase {
.setPriority(Notification.PRIORITY_HIGH)
.build();
mNotificationManager.notify(id, notification);
- SystemClock.sleep(10);
+ //update rate limit is 50 notifications/second.
+ SystemClock.sleep(20);
}
private boolean isLockScreen() {
diff --git a/docs/html-intl/intl/es/preview/images/bundles.png b/docs/html-intl/intl/es/preview/images/bundles.png
deleted file mode 100644
index 8b022b1c20e7..000000000000
--- a/docs/html-intl/intl/es/preview/images/bundles.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/bundles_2x.png b/docs/html-intl/intl/es/preview/images/bundles_2x.png
deleted file mode 100644
index 4669096a1c9b..000000000000
--- a/docs/html-intl/intl/es/preview/images/bundles_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/datasaver.png b/docs/html-intl/intl/es/preview/images/datasaver.png
deleted file mode 100644
index c5a58fb1f39b..000000000000
--- a/docs/html-intl/intl/es/preview/images/datasaver.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/doze-diagram-1.png b/docs/html-intl/intl/es/preview/images/doze-diagram-1.png
deleted file mode 100644
index 08144479f559..000000000000
--- a/docs/html-intl/intl/es/preview/images/doze-diagram-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/doze-diagram-2.png b/docs/html-intl/intl/es/preview/images/doze-diagram-2.png
deleted file mode 100644
index c20c6cb2e323..000000000000
--- a/docs/html-intl/intl/es/preview/images/doze-diagram-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/inline-reply.png b/docs/html-intl/intl/es/preview/images/inline-reply.png
deleted file mode 100644
index 79a1a72bb0ee..000000000000
--- a/docs/html-intl/intl/es/preview/images/inline-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/inline-reply_2x.png b/docs/html-intl/intl/es/preview/images/inline-reply_2x.png
deleted file mode 100644
index 13c6e35bf207..000000000000
--- a/docs/html-intl/intl/es/preview/images/inline-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/inline-type-reply.png b/docs/html-intl/intl/es/preview/images/inline-type-reply.png
deleted file mode 100644
index b22aacda02d8..000000000000
--- a/docs/html-intl/intl/es/preview/images/inline-type-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/inline-type-reply_2x.png b/docs/html-intl/intl/es/preview/images/inline-type-reply_2x.png
deleted file mode 100644
index 6e52a802296e..000000000000
--- a/docs/html-intl/intl/es/preview/images/inline-type-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/m-preview-timeline-crop.png b/docs/html-intl/intl/es/preview/images/m-preview-timeline-crop.png
deleted file mode 100644
index 724a6af8bc51..000000000000
--- a/docs/html-intl/intl/es/preview/images/m-preview-timeline-crop.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/m-preview-timeline.png b/docs/html-intl/intl/es/preview/images/m-preview-timeline.png
deleted file mode 100644
index e9a339ef8276..000000000000
--- a/docs/html-intl/intl/es/preview/images/m-preview-timeline.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/mw-portrait.png b/docs/html-intl/intl/es/preview/images/mw-portrait.png
deleted file mode 100644
index e752387f11c3..000000000000
--- a/docs/html-intl/intl/es/preview/images/mw-portrait.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/mw-splitscreen.png b/docs/html-intl/intl/es/preview/images/mw-splitscreen.png
deleted file mode 100644
index bf719997635d..000000000000
--- a/docs/html-intl/intl/es/preview/images/mw-splitscreen.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/mw-splitscreen_2x.png b/docs/html-intl/intl/es/preview/images/mw-splitscreen_2x.png
deleted file mode 100644
index 38114db497aa..000000000000
--- a/docs/html-intl/intl/es/preview/images/mw-splitscreen_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/n-preview-setup.png b/docs/html-intl/intl/es/preview/images/n-preview-setup.png
deleted file mode 100644
index 612e0316bc96..000000000000
--- a/docs/html-intl/intl/es/preview/images/n-preview-setup.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/notifications-1.png b/docs/html-intl/intl/es/preview/images/notifications-1.png
deleted file mode 100644
index 57120026a97c..000000000000
--- a/docs/html-intl/intl/es/preview/images/notifications-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/notifications-2.png b/docs/html-intl/intl/es/preview/images/notifications-2.png
deleted file mode 100644
index 0d07948171ea..000000000000
--- a/docs/html-intl/intl/es/preview/images/notifications-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/notifications-3.png b/docs/html-intl/intl/es/preview/images/notifications-3.png
deleted file mode 100644
index 261d01074f84..000000000000
--- a/docs/html-intl/intl/es/preview/images/notifications-3.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/notifications-card.png b/docs/html-intl/intl/es/preview/images/notifications-card.png
deleted file mode 100644
index d9d05900e5d8..000000000000
--- a/docs/html-intl/intl/es/preview/images/notifications-card.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/pip-active.png b/docs/html-intl/intl/es/preview/images/pip-active.png
deleted file mode 100644
index a24cb0368b7d..000000000000
--- a/docs/html-intl/intl/es/preview/images/pip-active.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/pip-button.png b/docs/html-intl/intl/es/preview/images/pip-button.png
deleted file mode 100644
index b876b12605e1..000000000000
--- a/docs/html-intl/intl/es/preview/images/pip-button.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/quicksettings.png b/docs/html-intl/intl/es/preview/images/quicksettings.png
deleted file mode 100644
index 68e1f740a6d2..000000000000
--- a/docs/html-intl/intl/es/preview/images/quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/sample-activenotifications.png b/docs/html-intl/intl/es/preview/images/sample-activenotifications.png
deleted file mode 100644
index 8817469feb9d..000000000000
--- a/docs/html-intl/intl/es/preview/images/sample-activenotifications.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/sample-directboot.png b/docs/html-intl/intl/es/preview/images/sample-directboot.png
deleted file mode 100644
index cc409d381263..000000000000
--- a/docs/html-intl/intl/es/preview/images/sample-directboot.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/sample-messagingservice.png b/docs/html-intl/intl/es/preview/images/sample-messagingservice.png
deleted file mode 100644
index 0d8fb3e6e10c..000000000000
--- a/docs/html-intl/intl/es/preview/images/sample-messagingservice.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/sample-multiwindow.png b/docs/html-intl/intl/es/preview/images/sample-multiwindow.png
deleted file mode 100644
index 979bf619f5e8..000000000000
--- a/docs/html-intl/intl/es/preview/images/sample-multiwindow.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/sample-scopeddirectoryaccess.png b/docs/html-intl/intl/es/preview/images/sample-scopeddirectoryaccess.png
deleted file mode 100644
index 58515dcac0b3..000000000000
--- a/docs/html-intl/intl/es/preview/images/sample-scopeddirectoryaccess.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/scoped-folder-access-dont-ask.png b/docs/html-intl/intl/es/preview/images/scoped-folder-access-dont-ask.png
deleted file mode 100644
index 5c505d956f5e..000000000000
--- a/docs/html-intl/intl/es/preview/images/scoped-folder-access-dont-ask.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/scoped-folder-access-dont-ask_2x.png b/docs/html-intl/intl/es/preview/images/scoped-folder-access-dont-ask_2x.png
deleted file mode 100644
index 612b69f8926f..000000000000
--- a/docs/html-intl/intl/es/preview/images/scoped-folder-access-dont-ask_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/scoped-folder-access-framed.png b/docs/html-intl/intl/es/preview/images/scoped-folder-access-framed.png
deleted file mode 100644
index 0169e4196aff..000000000000
--- a/docs/html-intl/intl/es/preview/images/scoped-folder-access-framed.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/scoped-folder-access-framed_2x.png b/docs/html-intl/intl/es/preview/images/scoped-folder-access-framed_2x.png
deleted file mode 100644
index fd59ef17d94c..000000000000
--- a/docs/html-intl/intl/es/preview/images/scoped-folder-access-framed_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/screen-zoom-1.png b/docs/html-intl/intl/es/preview/images/screen-zoom-1.png
deleted file mode 100644
index f62d04e2a186..000000000000
--- a/docs/html-intl/intl/es/preview/images/screen-zoom-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/screen-zoom-2.png b/docs/html-intl/intl/es/preview/images/screen-zoom-2.png
deleted file mode 100644
index 172b5b3dc3b2..000000000000
--- a/docs/html-intl/intl/es/preview/images/screen-zoom-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/es/preview/images/studio-jdk-location.jpg b/docs/html-intl/intl/es/preview/images/studio-jdk-location.jpg
deleted file mode 100644
index 1b1ba2357726..000000000000
--- a/docs/html-intl/intl/es/preview/images/studio-jdk-location.jpg
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/bundles.png b/docs/html-intl/intl/in/preview/images/bundles.png
deleted file mode 100644
index 8b022b1c20e7..000000000000
--- a/docs/html-intl/intl/in/preview/images/bundles.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/bundles_2x.png b/docs/html-intl/intl/in/preview/images/bundles_2x.png
deleted file mode 100644
index 4669096a1c9b..000000000000
--- a/docs/html-intl/intl/in/preview/images/bundles_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/datasaver.png b/docs/html-intl/intl/in/preview/images/datasaver.png
deleted file mode 100644
index c5a58fb1f39b..000000000000
--- a/docs/html-intl/intl/in/preview/images/datasaver.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/doze-diagram-1.png b/docs/html-intl/intl/in/preview/images/doze-diagram-1.png
deleted file mode 100644
index 08144479f559..000000000000
--- a/docs/html-intl/intl/in/preview/images/doze-diagram-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/doze-diagram-2.png b/docs/html-intl/intl/in/preview/images/doze-diagram-2.png
deleted file mode 100644
index c20c6cb2e323..000000000000
--- a/docs/html-intl/intl/in/preview/images/doze-diagram-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/inline-reply.png b/docs/html-intl/intl/in/preview/images/inline-reply.png
deleted file mode 100644
index 79a1a72bb0ee..000000000000
--- a/docs/html-intl/intl/in/preview/images/inline-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/inline-reply_2x.png b/docs/html-intl/intl/in/preview/images/inline-reply_2x.png
deleted file mode 100644
index 13c6e35bf207..000000000000
--- a/docs/html-intl/intl/in/preview/images/inline-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/inline-type-reply.png b/docs/html-intl/intl/in/preview/images/inline-type-reply.png
deleted file mode 100644
index b22aacda02d8..000000000000
--- a/docs/html-intl/intl/in/preview/images/inline-type-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/inline-type-reply_2x.png b/docs/html-intl/intl/in/preview/images/inline-type-reply_2x.png
deleted file mode 100644
index 6e52a802296e..000000000000
--- a/docs/html-intl/intl/in/preview/images/inline-type-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/m-preview-timeline-crop.png b/docs/html-intl/intl/in/preview/images/m-preview-timeline-crop.png
deleted file mode 100644
index 724a6af8bc51..000000000000
--- a/docs/html-intl/intl/in/preview/images/m-preview-timeline-crop.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/m-preview-timeline.png b/docs/html-intl/intl/in/preview/images/m-preview-timeline.png
deleted file mode 100644
index e9a339ef8276..000000000000
--- a/docs/html-intl/intl/in/preview/images/m-preview-timeline.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/mw-portrait.png b/docs/html-intl/intl/in/preview/images/mw-portrait.png
deleted file mode 100644
index e752387f11c3..000000000000
--- a/docs/html-intl/intl/in/preview/images/mw-portrait.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/mw-splitscreen.png b/docs/html-intl/intl/in/preview/images/mw-splitscreen.png
deleted file mode 100644
index bf719997635d..000000000000
--- a/docs/html-intl/intl/in/preview/images/mw-splitscreen.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/mw-splitscreen_2x.png b/docs/html-intl/intl/in/preview/images/mw-splitscreen_2x.png
deleted file mode 100644
index 38114db497aa..000000000000
--- a/docs/html-intl/intl/in/preview/images/mw-splitscreen_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/n-preview-setup.png b/docs/html-intl/intl/in/preview/images/n-preview-setup.png
deleted file mode 100644
index 612e0316bc96..000000000000
--- a/docs/html-intl/intl/in/preview/images/n-preview-setup.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/notifications-1.png b/docs/html-intl/intl/in/preview/images/notifications-1.png
deleted file mode 100644
index 57120026a97c..000000000000
--- a/docs/html-intl/intl/in/preview/images/notifications-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/notifications-2.png b/docs/html-intl/intl/in/preview/images/notifications-2.png
deleted file mode 100644
index 0d07948171ea..000000000000
--- a/docs/html-intl/intl/in/preview/images/notifications-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/notifications-3.png b/docs/html-intl/intl/in/preview/images/notifications-3.png
deleted file mode 100644
index 261d01074f84..000000000000
--- a/docs/html-intl/intl/in/preview/images/notifications-3.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/notifications-card.png b/docs/html-intl/intl/in/preview/images/notifications-card.png
deleted file mode 100644
index d9d05900e5d8..000000000000
--- a/docs/html-intl/intl/in/preview/images/notifications-card.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/pip-active.png b/docs/html-intl/intl/in/preview/images/pip-active.png
deleted file mode 100644
index a24cb0368b7d..000000000000
--- a/docs/html-intl/intl/in/preview/images/pip-active.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/pip-button.png b/docs/html-intl/intl/in/preview/images/pip-button.png
deleted file mode 100644
index b876b12605e1..000000000000
--- a/docs/html-intl/intl/in/preview/images/pip-button.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/quicksettings.png b/docs/html-intl/intl/in/preview/images/quicksettings.png
deleted file mode 100644
index 68e1f740a6d2..000000000000
--- a/docs/html-intl/intl/in/preview/images/quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/sample-activenotifications.png b/docs/html-intl/intl/in/preview/images/sample-activenotifications.png
deleted file mode 100644
index 8817469feb9d..000000000000
--- a/docs/html-intl/intl/in/preview/images/sample-activenotifications.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/sample-directboot.png b/docs/html-intl/intl/in/preview/images/sample-directboot.png
deleted file mode 100644
index cc409d381263..000000000000
--- a/docs/html-intl/intl/in/preview/images/sample-directboot.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/sample-messagingservice.png b/docs/html-intl/intl/in/preview/images/sample-messagingservice.png
deleted file mode 100644
index 0d8fb3e6e10c..000000000000
--- a/docs/html-intl/intl/in/preview/images/sample-messagingservice.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/sample-multiwindow.png b/docs/html-intl/intl/in/preview/images/sample-multiwindow.png
deleted file mode 100644
index 979bf619f5e8..000000000000
--- a/docs/html-intl/intl/in/preview/images/sample-multiwindow.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/sample-scopeddirectoryaccess.png b/docs/html-intl/intl/in/preview/images/sample-scopeddirectoryaccess.png
deleted file mode 100644
index 58515dcac0b3..000000000000
--- a/docs/html-intl/intl/in/preview/images/sample-scopeddirectoryaccess.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/scoped-folder-access-dont-ask.png b/docs/html-intl/intl/in/preview/images/scoped-folder-access-dont-ask.png
deleted file mode 100644
index 5c505d956f5e..000000000000
--- a/docs/html-intl/intl/in/preview/images/scoped-folder-access-dont-ask.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/scoped-folder-access-dont-ask_2x.png b/docs/html-intl/intl/in/preview/images/scoped-folder-access-dont-ask_2x.png
deleted file mode 100644
index 612b69f8926f..000000000000
--- a/docs/html-intl/intl/in/preview/images/scoped-folder-access-dont-ask_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/scoped-folder-access-framed.png b/docs/html-intl/intl/in/preview/images/scoped-folder-access-framed.png
deleted file mode 100644
index 0169e4196aff..000000000000
--- a/docs/html-intl/intl/in/preview/images/scoped-folder-access-framed.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/scoped-folder-access-framed_2x.png b/docs/html-intl/intl/in/preview/images/scoped-folder-access-framed_2x.png
deleted file mode 100644
index fd59ef17d94c..000000000000
--- a/docs/html-intl/intl/in/preview/images/scoped-folder-access-framed_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/screen-zoom-1.png b/docs/html-intl/intl/in/preview/images/screen-zoom-1.png
deleted file mode 100644
index f62d04e2a186..000000000000
--- a/docs/html-intl/intl/in/preview/images/screen-zoom-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/screen-zoom-2.png b/docs/html-intl/intl/in/preview/images/screen-zoom-2.png
deleted file mode 100644
index 172b5b3dc3b2..000000000000
--- a/docs/html-intl/intl/in/preview/images/screen-zoom-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/in/preview/images/studio-jdk-location.jpg b/docs/html-intl/intl/in/preview/images/studio-jdk-location.jpg
deleted file mode 100644
index 1b1ba2357726..000000000000
--- a/docs/html-intl/intl/in/preview/images/studio-jdk-location.jpg
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/bundles.png b/docs/html-intl/intl/ja/preview/images/bundles.png
deleted file mode 100644
index 8b022b1c20e7..000000000000
--- a/docs/html-intl/intl/ja/preview/images/bundles.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/bundles_2x.png b/docs/html-intl/intl/ja/preview/images/bundles_2x.png
deleted file mode 100644
index 4669096a1c9b..000000000000
--- a/docs/html-intl/intl/ja/preview/images/bundles_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/datasaver.png b/docs/html-intl/intl/ja/preview/images/datasaver.png
deleted file mode 100644
index c5a58fb1f39b..000000000000
--- a/docs/html-intl/intl/ja/preview/images/datasaver.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/doze-diagram-1.png b/docs/html-intl/intl/ja/preview/images/doze-diagram-1.png
deleted file mode 100644
index 08144479f559..000000000000
--- a/docs/html-intl/intl/ja/preview/images/doze-diagram-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/doze-diagram-2.png b/docs/html-intl/intl/ja/preview/images/doze-diagram-2.png
deleted file mode 100644
index c20c6cb2e323..000000000000
--- a/docs/html-intl/intl/ja/preview/images/doze-diagram-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/inline-reply.png b/docs/html-intl/intl/ja/preview/images/inline-reply.png
deleted file mode 100644
index 79a1a72bb0ee..000000000000
--- a/docs/html-intl/intl/ja/preview/images/inline-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/inline-reply_2x.png b/docs/html-intl/intl/ja/preview/images/inline-reply_2x.png
deleted file mode 100644
index 13c6e35bf207..000000000000
--- a/docs/html-intl/intl/ja/preview/images/inline-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/inline-type-reply.png b/docs/html-intl/intl/ja/preview/images/inline-type-reply.png
deleted file mode 100644
index b22aacda02d8..000000000000
--- a/docs/html-intl/intl/ja/preview/images/inline-type-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/inline-type-reply_2x.png b/docs/html-intl/intl/ja/preview/images/inline-type-reply_2x.png
deleted file mode 100644
index 6e52a802296e..000000000000
--- a/docs/html-intl/intl/ja/preview/images/inline-type-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/m-preview-timeline-crop.png b/docs/html-intl/intl/ja/preview/images/m-preview-timeline-crop.png
deleted file mode 100644
index 724a6af8bc51..000000000000
--- a/docs/html-intl/intl/ja/preview/images/m-preview-timeline-crop.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/m-preview-timeline.png b/docs/html-intl/intl/ja/preview/images/m-preview-timeline.png
deleted file mode 100644
index e9a339ef8276..000000000000
--- a/docs/html-intl/intl/ja/preview/images/m-preview-timeline.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/mw-portrait.png b/docs/html-intl/intl/ja/preview/images/mw-portrait.png
deleted file mode 100644
index e752387f11c3..000000000000
--- a/docs/html-intl/intl/ja/preview/images/mw-portrait.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/mw-splitscreen.png b/docs/html-intl/intl/ja/preview/images/mw-splitscreen.png
deleted file mode 100644
index bf719997635d..000000000000
--- a/docs/html-intl/intl/ja/preview/images/mw-splitscreen.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/mw-splitscreen_2x.png b/docs/html-intl/intl/ja/preview/images/mw-splitscreen_2x.png
deleted file mode 100644
index 38114db497aa..000000000000
--- a/docs/html-intl/intl/ja/preview/images/mw-splitscreen_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/n-preview-setup.png b/docs/html-intl/intl/ja/preview/images/n-preview-setup.png
deleted file mode 100644
index 612e0316bc96..000000000000
--- a/docs/html-intl/intl/ja/preview/images/n-preview-setup.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/notifications-1.png b/docs/html-intl/intl/ja/preview/images/notifications-1.png
deleted file mode 100644
index 57120026a97c..000000000000
--- a/docs/html-intl/intl/ja/preview/images/notifications-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/notifications-2.png b/docs/html-intl/intl/ja/preview/images/notifications-2.png
deleted file mode 100644
index 0d07948171ea..000000000000
--- a/docs/html-intl/intl/ja/preview/images/notifications-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/notifications-3.png b/docs/html-intl/intl/ja/preview/images/notifications-3.png
deleted file mode 100644
index 261d01074f84..000000000000
--- a/docs/html-intl/intl/ja/preview/images/notifications-3.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/notifications-card.png b/docs/html-intl/intl/ja/preview/images/notifications-card.png
deleted file mode 100644
index d9d05900e5d8..000000000000
--- a/docs/html-intl/intl/ja/preview/images/notifications-card.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/pip-active.png b/docs/html-intl/intl/ja/preview/images/pip-active.png
deleted file mode 100644
index a24cb0368b7d..000000000000
--- a/docs/html-intl/intl/ja/preview/images/pip-active.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/pip-button.png b/docs/html-intl/intl/ja/preview/images/pip-button.png
deleted file mode 100644
index b876b12605e1..000000000000
--- a/docs/html-intl/intl/ja/preview/images/pip-button.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/quicksettings.png b/docs/html-intl/intl/ja/preview/images/quicksettings.png
deleted file mode 100644
index 68e1f740a6d2..000000000000
--- a/docs/html-intl/intl/ja/preview/images/quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/sample-activenotifications.png b/docs/html-intl/intl/ja/preview/images/sample-activenotifications.png
deleted file mode 100644
index 8817469feb9d..000000000000
--- a/docs/html-intl/intl/ja/preview/images/sample-activenotifications.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/sample-directboot.png b/docs/html-intl/intl/ja/preview/images/sample-directboot.png
deleted file mode 100644
index cc409d381263..000000000000
--- a/docs/html-intl/intl/ja/preview/images/sample-directboot.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/sample-messagingservice.png b/docs/html-intl/intl/ja/preview/images/sample-messagingservice.png
deleted file mode 100644
index 0d8fb3e6e10c..000000000000
--- a/docs/html-intl/intl/ja/preview/images/sample-messagingservice.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/sample-multiwindow.png b/docs/html-intl/intl/ja/preview/images/sample-multiwindow.png
deleted file mode 100644
index 979bf619f5e8..000000000000
--- a/docs/html-intl/intl/ja/preview/images/sample-multiwindow.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/sample-scopeddirectoryaccess.png b/docs/html-intl/intl/ja/preview/images/sample-scopeddirectoryaccess.png
deleted file mode 100644
index 58515dcac0b3..000000000000
--- a/docs/html-intl/intl/ja/preview/images/sample-scopeddirectoryaccess.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/scoped-folder-access-dont-ask.png b/docs/html-intl/intl/ja/preview/images/scoped-folder-access-dont-ask.png
deleted file mode 100644
index 5c505d956f5e..000000000000
--- a/docs/html-intl/intl/ja/preview/images/scoped-folder-access-dont-ask.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/scoped-folder-access-dont-ask_2x.png b/docs/html-intl/intl/ja/preview/images/scoped-folder-access-dont-ask_2x.png
deleted file mode 100644
index 612b69f8926f..000000000000
--- a/docs/html-intl/intl/ja/preview/images/scoped-folder-access-dont-ask_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/scoped-folder-access-framed.png b/docs/html-intl/intl/ja/preview/images/scoped-folder-access-framed.png
deleted file mode 100644
index 0169e4196aff..000000000000
--- a/docs/html-intl/intl/ja/preview/images/scoped-folder-access-framed.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/scoped-folder-access-framed_2x.png b/docs/html-intl/intl/ja/preview/images/scoped-folder-access-framed_2x.png
deleted file mode 100644
index fd59ef17d94c..000000000000
--- a/docs/html-intl/intl/ja/preview/images/scoped-folder-access-framed_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/screen-zoom-1.png b/docs/html-intl/intl/ja/preview/images/screen-zoom-1.png
deleted file mode 100644
index f62d04e2a186..000000000000
--- a/docs/html-intl/intl/ja/preview/images/screen-zoom-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/screen-zoom-2.png b/docs/html-intl/intl/ja/preview/images/screen-zoom-2.png
deleted file mode 100644
index 172b5b3dc3b2..000000000000
--- a/docs/html-intl/intl/ja/preview/images/screen-zoom-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ja/preview/images/studio-jdk-location.jpg b/docs/html-intl/intl/ja/preview/images/studio-jdk-location.jpg
deleted file mode 100644
index 1b1ba2357726..000000000000
--- a/docs/html-intl/intl/ja/preview/images/studio-jdk-location.jpg
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/bundles.png b/docs/html-intl/intl/ko/preview/images/bundles.png
deleted file mode 100644
index 8b022b1c20e7..000000000000
--- a/docs/html-intl/intl/ko/preview/images/bundles.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/bundles_2x.png b/docs/html-intl/intl/ko/preview/images/bundles_2x.png
deleted file mode 100644
index 4669096a1c9b..000000000000
--- a/docs/html-intl/intl/ko/preview/images/bundles_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/datasaver.png b/docs/html-intl/intl/ko/preview/images/datasaver.png
deleted file mode 100644
index c5a58fb1f39b..000000000000
--- a/docs/html-intl/intl/ko/preview/images/datasaver.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/doze-diagram-1.png b/docs/html-intl/intl/ko/preview/images/doze-diagram-1.png
deleted file mode 100644
index 08144479f559..000000000000
--- a/docs/html-intl/intl/ko/preview/images/doze-diagram-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/doze-diagram-2.png b/docs/html-intl/intl/ko/preview/images/doze-diagram-2.png
deleted file mode 100644
index c20c6cb2e323..000000000000
--- a/docs/html-intl/intl/ko/preview/images/doze-diagram-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/inline-reply.png b/docs/html-intl/intl/ko/preview/images/inline-reply.png
deleted file mode 100644
index 79a1a72bb0ee..000000000000
--- a/docs/html-intl/intl/ko/preview/images/inline-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/inline-reply_2x.png b/docs/html-intl/intl/ko/preview/images/inline-reply_2x.png
deleted file mode 100644
index 13c6e35bf207..000000000000
--- a/docs/html-intl/intl/ko/preview/images/inline-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/inline-type-reply.png b/docs/html-intl/intl/ko/preview/images/inline-type-reply.png
deleted file mode 100644
index b22aacda02d8..000000000000
--- a/docs/html-intl/intl/ko/preview/images/inline-type-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/inline-type-reply_2x.png b/docs/html-intl/intl/ko/preview/images/inline-type-reply_2x.png
deleted file mode 100644
index 6e52a802296e..000000000000
--- a/docs/html-intl/intl/ko/preview/images/inline-type-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/m-preview-timeline-crop.png b/docs/html-intl/intl/ko/preview/images/m-preview-timeline-crop.png
deleted file mode 100644
index 724a6af8bc51..000000000000
--- a/docs/html-intl/intl/ko/preview/images/m-preview-timeline-crop.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/m-preview-timeline.png b/docs/html-intl/intl/ko/preview/images/m-preview-timeline.png
deleted file mode 100644
index e9a339ef8276..000000000000
--- a/docs/html-intl/intl/ko/preview/images/m-preview-timeline.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/mw-portrait.png b/docs/html-intl/intl/ko/preview/images/mw-portrait.png
deleted file mode 100644
index e752387f11c3..000000000000
--- a/docs/html-intl/intl/ko/preview/images/mw-portrait.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/mw-splitscreen.png b/docs/html-intl/intl/ko/preview/images/mw-splitscreen.png
deleted file mode 100644
index bf719997635d..000000000000
--- a/docs/html-intl/intl/ko/preview/images/mw-splitscreen.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/mw-splitscreen_2x.png b/docs/html-intl/intl/ko/preview/images/mw-splitscreen_2x.png
deleted file mode 100644
index 38114db497aa..000000000000
--- a/docs/html-intl/intl/ko/preview/images/mw-splitscreen_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/n-preview-setup.png b/docs/html-intl/intl/ko/preview/images/n-preview-setup.png
deleted file mode 100644
index 612e0316bc96..000000000000
--- a/docs/html-intl/intl/ko/preview/images/n-preview-setup.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/notifications-1.png b/docs/html-intl/intl/ko/preview/images/notifications-1.png
deleted file mode 100644
index 57120026a97c..000000000000
--- a/docs/html-intl/intl/ko/preview/images/notifications-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/notifications-2.png b/docs/html-intl/intl/ko/preview/images/notifications-2.png
deleted file mode 100644
index 0d07948171ea..000000000000
--- a/docs/html-intl/intl/ko/preview/images/notifications-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/notifications-3.png b/docs/html-intl/intl/ko/preview/images/notifications-3.png
deleted file mode 100644
index 261d01074f84..000000000000
--- a/docs/html-intl/intl/ko/preview/images/notifications-3.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/notifications-card.png b/docs/html-intl/intl/ko/preview/images/notifications-card.png
deleted file mode 100644
index d9d05900e5d8..000000000000
--- a/docs/html-intl/intl/ko/preview/images/notifications-card.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/pip-active.png b/docs/html-intl/intl/ko/preview/images/pip-active.png
deleted file mode 100644
index a24cb0368b7d..000000000000
--- a/docs/html-intl/intl/ko/preview/images/pip-active.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/pip-button.png b/docs/html-intl/intl/ko/preview/images/pip-button.png
deleted file mode 100644
index b876b12605e1..000000000000
--- a/docs/html-intl/intl/ko/preview/images/pip-button.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/quicksettings.png b/docs/html-intl/intl/ko/preview/images/quicksettings.png
deleted file mode 100644
index 68e1f740a6d2..000000000000
--- a/docs/html-intl/intl/ko/preview/images/quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/sample-activenotifications.png b/docs/html-intl/intl/ko/preview/images/sample-activenotifications.png
deleted file mode 100644
index 8817469feb9d..000000000000
--- a/docs/html-intl/intl/ko/preview/images/sample-activenotifications.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/sample-directboot.png b/docs/html-intl/intl/ko/preview/images/sample-directboot.png
deleted file mode 100644
index cc409d381263..000000000000
--- a/docs/html-intl/intl/ko/preview/images/sample-directboot.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/sample-messagingservice.png b/docs/html-intl/intl/ko/preview/images/sample-messagingservice.png
deleted file mode 100644
index 0d8fb3e6e10c..000000000000
--- a/docs/html-intl/intl/ko/preview/images/sample-messagingservice.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/sample-multiwindow.png b/docs/html-intl/intl/ko/preview/images/sample-multiwindow.png
deleted file mode 100644
index 979bf619f5e8..000000000000
--- a/docs/html-intl/intl/ko/preview/images/sample-multiwindow.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/sample-scopeddirectoryaccess.png b/docs/html-intl/intl/ko/preview/images/sample-scopeddirectoryaccess.png
deleted file mode 100644
index 58515dcac0b3..000000000000
--- a/docs/html-intl/intl/ko/preview/images/sample-scopeddirectoryaccess.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/scoped-folder-access-dont-ask.png b/docs/html-intl/intl/ko/preview/images/scoped-folder-access-dont-ask.png
deleted file mode 100644
index 5c505d956f5e..000000000000
--- a/docs/html-intl/intl/ko/preview/images/scoped-folder-access-dont-ask.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/scoped-folder-access-dont-ask_2x.png b/docs/html-intl/intl/ko/preview/images/scoped-folder-access-dont-ask_2x.png
deleted file mode 100644
index 612b69f8926f..000000000000
--- a/docs/html-intl/intl/ko/preview/images/scoped-folder-access-dont-ask_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/scoped-folder-access-framed.png b/docs/html-intl/intl/ko/preview/images/scoped-folder-access-framed.png
deleted file mode 100644
index 0169e4196aff..000000000000
--- a/docs/html-intl/intl/ko/preview/images/scoped-folder-access-framed.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/scoped-folder-access-framed_2x.png b/docs/html-intl/intl/ko/preview/images/scoped-folder-access-framed_2x.png
deleted file mode 100644
index fd59ef17d94c..000000000000
--- a/docs/html-intl/intl/ko/preview/images/scoped-folder-access-framed_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/screen-zoom-1.png b/docs/html-intl/intl/ko/preview/images/screen-zoom-1.png
deleted file mode 100644
index f62d04e2a186..000000000000
--- a/docs/html-intl/intl/ko/preview/images/screen-zoom-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/screen-zoom-2.png b/docs/html-intl/intl/ko/preview/images/screen-zoom-2.png
deleted file mode 100644
index 172b5b3dc3b2..000000000000
--- a/docs/html-intl/intl/ko/preview/images/screen-zoom-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/ko/preview/images/studio-jdk-location.jpg b/docs/html-intl/intl/ko/preview/images/studio-jdk-location.jpg
deleted file mode 100644
index 1b1ba2357726..000000000000
--- a/docs/html-intl/intl/ko/preview/images/studio-jdk-location.jpg
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/bundles.png b/docs/html-intl/intl/pt-br/preview/images/bundles.png
deleted file mode 100644
index 8b022b1c20e7..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/bundles.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/bundles_2x.png b/docs/html-intl/intl/pt-br/preview/images/bundles_2x.png
deleted file mode 100644
index 4669096a1c9b..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/bundles_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/datasaver.png b/docs/html-intl/intl/pt-br/preview/images/datasaver.png
deleted file mode 100644
index c5a58fb1f39b..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/datasaver.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/doze-diagram-1.png b/docs/html-intl/intl/pt-br/preview/images/doze-diagram-1.png
deleted file mode 100644
index 08144479f559..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/doze-diagram-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/doze-diagram-2.png b/docs/html-intl/intl/pt-br/preview/images/doze-diagram-2.png
deleted file mode 100644
index c20c6cb2e323..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/doze-diagram-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/inline-reply.png b/docs/html-intl/intl/pt-br/preview/images/inline-reply.png
deleted file mode 100644
index 79a1a72bb0ee..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/inline-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/inline-reply_2x.png b/docs/html-intl/intl/pt-br/preview/images/inline-reply_2x.png
deleted file mode 100644
index 13c6e35bf207..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/inline-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/inline-type-reply.png b/docs/html-intl/intl/pt-br/preview/images/inline-type-reply.png
deleted file mode 100644
index b22aacda02d8..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/inline-type-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/inline-type-reply_2x.png b/docs/html-intl/intl/pt-br/preview/images/inline-type-reply_2x.png
deleted file mode 100644
index 6e52a802296e..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/inline-type-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/m-preview-timeline-crop.png b/docs/html-intl/intl/pt-br/preview/images/m-preview-timeline-crop.png
deleted file mode 100644
index 724a6af8bc51..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/m-preview-timeline-crop.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/m-preview-timeline.png b/docs/html-intl/intl/pt-br/preview/images/m-preview-timeline.png
deleted file mode 100644
index e9a339ef8276..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/m-preview-timeline.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/mw-portrait.png b/docs/html-intl/intl/pt-br/preview/images/mw-portrait.png
deleted file mode 100644
index e752387f11c3..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/mw-portrait.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/mw-splitscreen.png b/docs/html-intl/intl/pt-br/preview/images/mw-splitscreen.png
deleted file mode 100644
index bf719997635d..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/mw-splitscreen.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/mw-splitscreen_2x.png b/docs/html-intl/intl/pt-br/preview/images/mw-splitscreen_2x.png
deleted file mode 100644
index 38114db497aa..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/mw-splitscreen_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/n-preview-setup.png b/docs/html-intl/intl/pt-br/preview/images/n-preview-setup.png
deleted file mode 100644
index 612e0316bc96..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/n-preview-setup.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/notifications-1.png b/docs/html-intl/intl/pt-br/preview/images/notifications-1.png
deleted file mode 100644
index 57120026a97c..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/notifications-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/notifications-2.png b/docs/html-intl/intl/pt-br/preview/images/notifications-2.png
deleted file mode 100644
index 0d07948171ea..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/notifications-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/notifications-3.png b/docs/html-intl/intl/pt-br/preview/images/notifications-3.png
deleted file mode 100644
index 261d01074f84..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/notifications-3.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/notifications-card.png b/docs/html-intl/intl/pt-br/preview/images/notifications-card.png
deleted file mode 100644
index d9d05900e5d8..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/notifications-card.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/pip-active.png b/docs/html-intl/intl/pt-br/preview/images/pip-active.png
deleted file mode 100644
index a24cb0368b7d..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/pip-active.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/pip-button.png b/docs/html-intl/intl/pt-br/preview/images/pip-button.png
deleted file mode 100644
index b876b12605e1..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/pip-button.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/quicksettings.png b/docs/html-intl/intl/pt-br/preview/images/quicksettings.png
deleted file mode 100644
index 68e1f740a6d2..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/sample-activenotifications.png b/docs/html-intl/intl/pt-br/preview/images/sample-activenotifications.png
deleted file mode 100644
index 8817469feb9d..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/sample-activenotifications.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/sample-directboot.png b/docs/html-intl/intl/pt-br/preview/images/sample-directboot.png
deleted file mode 100644
index cc409d381263..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/sample-directboot.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/sample-messagingservice.png b/docs/html-intl/intl/pt-br/preview/images/sample-messagingservice.png
deleted file mode 100644
index 0d8fb3e6e10c..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/sample-messagingservice.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/sample-multiwindow.png b/docs/html-intl/intl/pt-br/preview/images/sample-multiwindow.png
deleted file mode 100644
index 979bf619f5e8..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/sample-multiwindow.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/sample-scopeddirectoryaccess.png b/docs/html-intl/intl/pt-br/preview/images/sample-scopeddirectoryaccess.png
deleted file mode 100644
index 58515dcac0b3..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/sample-scopeddirectoryaccess.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-dont-ask.png b/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-dont-ask.png
deleted file mode 100644
index 5c505d956f5e..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-dont-ask.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-dont-ask_2x.png b/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-dont-ask_2x.png
deleted file mode 100644
index 612b69f8926f..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-dont-ask_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-framed.png b/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-framed.png
deleted file mode 100644
index 0169e4196aff..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-framed.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-framed_2x.png b/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-framed_2x.png
deleted file mode 100644
index fd59ef17d94c..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/scoped-folder-access-framed_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/screen-zoom-1.png b/docs/html-intl/intl/pt-br/preview/images/screen-zoom-1.png
deleted file mode 100644
index f62d04e2a186..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/screen-zoom-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/screen-zoom-2.png b/docs/html-intl/intl/pt-br/preview/images/screen-zoom-2.png
deleted file mode 100644
index 172b5b3dc3b2..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/screen-zoom-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/pt-br/preview/images/studio-jdk-location.jpg b/docs/html-intl/intl/pt-br/preview/images/studio-jdk-location.jpg
deleted file mode 100644
index 1b1ba2357726..000000000000
--- a/docs/html-intl/intl/pt-br/preview/images/studio-jdk-location.jpg
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/bundles.png b/docs/html-intl/intl/zh-cn/preview/images/bundles.png
deleted file mode 100644
index 8b022b1c20e7..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/bundles.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/bundles_2x.png b/docs/html-intl/intl/zh-cn/preview/images/bundles_2x.png
deleted file mode 100644
index 4669096a1c9b..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/bundles_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/datasaver.png b/docs/html-intl/intl/zh-cn/preview/images/datasaver.png
deleted file mode 100644
index c5a58fb1f39b..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/datasaver.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/doze-diagram-1.png b/docs/html-intl/intl/zh-cn/preview/images/doze-diagram-1.png
deleted file mode 100644
index 08144479f559..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/doze-diagram-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/doze-diagram-2.png b/docs/html-intl/intl/zh-cn/preview/images/doze-diagram-2.png
deleted file mode 100644
index c20c6cb2e323..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/doze-diagram-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/inline-reply.png b/docs/html-intl/intl/zh-cn/preview/images/inline-reply.png
deleted file mode 100644
index 79a1a72bb0ee..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/inline-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/inline-reply_2x.png b/docs/html-intl/intl/zh-cn/preview/images/inline-reply_2x.png
deleted file mode 100644
index 13c6e35bf207..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/inline-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/inline-type-reply.png b/docs/html-intl/intl/zh-cn/preview/images/inline-type-reply.png
deleted file mode 100644
index b22aacda02d8..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/inline-type-reply.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/inline-type-reply_2x.png b/docs/html-intl/intl/zh-cn/preview/images/inline-type-reply_2x.png
deleted file mode 100644
index 6e52a802296e..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/inline-type-reply_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/m-preview-timeline-crop.png b/docs/html-intl/intl/zh-cn/preview/images/m-preview-timeline-crop.png
deleted file mode 100644
index 724a6af8bc51..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/m-preview-timeline-crop.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/m-preview-timeline.png b/docs/html-intl/intl/zh-cn/preview/images/m-preview-timeline.png
deleted file mode 100644
index e9a339ef8276..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/m-preview-timeline.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/mw-portrait.png b/docs/html-intl/intl/zh-cn/preview/images/mw-portrait.png
deleted file mode 100644
index e752387f11c3..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/mw-portrait.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/mw-splitscreen.png b/docs/html-intl/intl/zh-cn/preview/images/mw-splitscreen.png
deleted file mode 100644
index bf719997635d..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/mw-splitscreen.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/mw-splitscreen_2x.png b/docs/html-intl/intl/zh-cn/preview/images/mw-splitscreen_2x.png
deleted file mode 100644
index 38114db497aa..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/mw-splitscreen_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/n-preview-setup.png b/docs/html-intl/intl/zh-cn/preview/images/n-preview-setup.png
deleted file mode 100644
index 612e0316bc96..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/n-preview-setup.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/notifications-1.png b/docs/html-intl/intl/zh-cn/preview/images/notifications-1.png
deleted file mode 100644
index 57120026a97c..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/notifications-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/notifications-2.png b/docs/html-intl/intl/zh-cn/preview/images/notifications-2.png
deleted file mode 100644
index 0d07948171ea..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/notifications-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/notifications-3.png b/docs/html-intl/intl/zh-cn/preview/images/notifications-3.png
deleted file mode 100644
index 261d01074f84..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/notifications-3.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/notifications-card.png b/docs/html-intl/intl/zh-cn/preview/images/notifications-card.png
deleted file mode 100644
index d9d05900e5d8..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/notifications-card.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/pip-active.png b/docs/html-intl/intl/zh-cn/preview/images/pip-active.png
deleted file mode 100644
index a24cb0368b7d..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/pip-active.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/pip-button.png b/docs/html-intl/intl/zh-cn/preview/images/pip-button.png
deleted file mode 100644
index b876b12605e1..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/pip-button.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/quicksettings.png b/docs/html-intl/intl/zh-cn/preview/images/quicksettings.png
deleted file mode 100644
index 68e1f740a6d2..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/quicksettings.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/sample-activenotifications.png b/docs/html-intl/intl/zh-cn/preview/images/sample-activenotifications.png
deleted file mode 100644
index 8817469feb9d..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/sample-activenotifications.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/sample-directboot.png b/docs/html-intl/intl/zh-cn/preview/images/sample-directboot.png
deleted file mode 100644
index cc409d381263..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/sample-directboot.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/sample-messagingservice.png b/docs/html-intl/intl/zh-cn/preview/images/sample-messagingservice.png
deleted file mode 100644
index 0d8fb3e6e10c..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/sample-messagingservice.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/sample-multiwindow.png b/docs/html-intl/intl/zh-cn/preview/images/sample-multiwindow.png
deleted file mode 100644
index 979bf619f5e8..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/sample-multiwindow.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/sample-scopeddirectoryaccess.png b/docs/html-intl/intl/zh-cn/preview/images/sample-scopeddirectoryaccess.png
deleted file mode 100644
index 58515dcac0b3..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/sample-scopeddirectoryaccess.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-dont-ask.png b/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-dont-ask.png
deleted file mode 100644
index 5c505d956f5e..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-dont-ask.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-dont-ask_2x.png b/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-dont-ask_2x.png
deleted file mode 100644
index 612b69f8926f..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-dont-ask_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-framed.png b/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-framed.png
deleted file mode 100644
index 0169e4196aff..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-framed.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-framed_2x.png b/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-framed_2x.png
deleted file mode 100644
index fd59ef17d94c..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/scoped-folder-access-framed_2x.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/screen-zoom-1.png b/docs/html-intl/intl/zh-cn/preview/images/screen-zoom-1.png
deleted file mode 100644
index f62d04e2a186..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/screen-zoom-1.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/screen-zoom-2.png b/docs/html-intl/intl/zh-cn/preview/images/screen-zoom-2.png
deleted file mode 100644
index 172b5b3dc3b2..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/screen-zoom-2.png
+++ /dev/null
Binary files differ
diff --git a/docs/html-intl/intl/zh-cn/preview/images/studio-jdk-location.jpg b/docs/html-intl/intl/zh-cn/preview/images/studio-jdk-location.jpg
deleted file mode 100644
index 1b1ba2357726..000000000000
--- a/docs/html-intl/intl/zh-cn/preview/images/studio-jdk-location.jpg
+++ /dev/null
Binary files differ
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index ae858fe13a45..774339a964db 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -797,54 +797,6 @@ redirects:
to: https://code.google.com/p/android/issues/list?can=2&q=label%3ADevPreview-N
- from: /2016/03/first-preview-of-android-n-developer.html
to: http://android-developers.blogspot.com/2016/03/first-preview-of-android-n-developer.html
-- from: /r/studio-ui/vector-asset-studio.html
- to: /studio/write/vector-asset-studio.html
-- from: /r/studio-ui/image-asset-studio.html
- to: /studio/write/image-asset-studio.html
-- from: /r/studio-ui/project-structure.html
- to: /studio/projects/index.html
-- from: /r/studio-ui/android-monitor.html
- to: /studio/profile/android-monitor.html
-- from: /r/studio-ui/am-logcat.html
- to: /studio/debug/am-logcat.html
-- from: /r/studio-ui/am-memory.html
- to: /studio/profile/am-memory.html
-- from: /r/studio-ui/am-cpu.html
- to: /studio/profile/am-cpu.html
-- from: /r/studio-ui/am-gpu.html
- to: /studio/profile/am-gpu.html
-- from: /r/studio-ui/am-network.html
- to: /studio/profile/am-network.html
-- from: /r/studio-ui/am-hprof.html
- to: /studio/profile/am-hprof.html
-- from: /r/studio-ui/am-allocation.html
- to: /studio/profile/am-allocation.html
-- from: /r/studio-ui/am-methodtrace.html
- to: /studio/profile/am-methodtrace.html
-- from: /r/studio-ui/am-sysinfo.html
- to: /studio/profile/am-sysinfo.html
-- from: /r/studio-ui/am-screenshot.html
- to: /studio/debug/am-screenshot.html
-- from: /r/studio-ui/am-video.html
- to: /studio/debug/am-video.html
-- from: /r/studio-ui/avd-manager.html
- to: /studio/run/managing-avds.html
-- from: /r/studio-ui/rundebugconfig.html
- to: /studio/run/index.html
-- from: /r/studio-ui/devicechooser.html
- to: /studio/run/emulator.html
-- from: /r/studio-ui/virtualdeviceconfig.html
- to: /studio/run/managing-avds.html
-- from: /r/studio-ui/emulator.html
- to: /studio/run/emulator.html
-- from: /r/studio-ui/instant-run.html
- to: /studio/run/index.html#instant-run
-- from: /r/studio-ui/test-recorder.html
- to: http://tools.android.com/tech-docs/test-recorder
-- from: /r/studio-ui/export-licenses.html
- to: http://tools.android.com/tech-docs/new-build-system/license
-- from: /r/studio-ui/experimental-to-stable-gradle.html
- to: http://tools.android.com/tech-docs/new-build-system/gradle-experimental/experimental-to-stable-gradle
- from: /reference/org/apache/http/...
to: /about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client
- from: /shareables/...
@@ -1066,6 +1018,8 @@ redirects:
to: /studio/projects/templates.html
- from: /tools/publishing/app-signing.html
to: /studio/publish/app-signing.html
+- from: /guide/publishing/app-signing.html
+ to: /studio/publish/app-signing.html
- from: /tools/publishing/preparing.html
to: /studio/publish/preparing.html
- from: /tools/publishing/publishing_overview.html
@@ -1169,3 +1123,57 @@ redirects:
to: /preview/features/background-optimization.html
- from: /bgopt/
to: /preview/features/background-optimization.html
+
+
+
+# Android Studio help button redirects
+- from: /r/studio-ui/vector-asset-studio.html
+ to: /studio/write/vector-asset-studio.html
+- from: /r/studio-ui/image-asset-studio.html
+ to: /studio/write/image-asset-studio.html
+- from: /r/studio-ui/project-structure.html
+ to: /studio/projects/index.html
+- from: /r/studio-ui/android-monitor.html
+ to: /studio/profile/android-monitor.html
+- from: /r/studio-ui/am-logcat.html
+ to: /studio/debug/am-logcat.html
+- from: /r/studio-ui/am-memory.html
+ to: /studio/profile/am-memory.html
+- from: /r/studio-ui/am-cpu.html
+ to: /studio/profile/am-cpu.html
+- from: /r/studio-ui/am-gpu.html
+ to: /studio/profile/am-gpu.html
+- from: /r/studio-ui/am-network.html
+ to: /studio/profile/am-network.html
+- from: /r/studio-ui/am-hprof.html
+ to: /studio/profile/am-hprof.html
+- from: /r/studio-ui/am-allocation.html
+ to: /studio/profile/am-allocation.html
+- from: /r/studio-ui/am-methodtrace.html
+ to: /studio/profile/am-methodtrace.html
+- from: /r/studio-ui/am-sysinfo.html
+ to: /studio/profile/am-sysinfo.html
+- from: /r/studio-ui/am-screenshot.html
+ to: /studio/debug/am-screenshot.html
+- from: /r/studio-ui/am-video.html
+ to: /studio/debug/am-video.html
+- from: /r/studio-ui/avd-manager.html
+ to: /studio/run/managing-avds.html
+- from: /r/studio-ui/rundebugconfig.html
+ to: /studio/run/rundebugconfig.html
+- from: /r/studio-ui/devicechooser.html
+ to: /studio/run/emulator.html
+- from: /r/studio-ui/virtualdeviceconfig.html
+ to: /studio/run/managing-avds.html
+- from: /r/studio-ui/emulator.html
+ to: /studio/run/emulator.html
+- from: /r/studio-ui/instant-run.html
+ to: /studio/run/index.html#instant-run
+- from: /r/studio-ui/test-recorder.html
+ to: http://tools.android.com/tech-docs/test-recorder
+- from: /r/studio-ui/export-licenses.html
+ to: http://tools.android.com/tech-docs/new-build-system/license
+- from: /r/studio-ui/experimental-to-stable-gradle.html
+ to: http://tools.android.com/tech-docs/new-build-system/gradle-experimental/experimental-to-stable-gradle
+- from: /r/studio-ui/sdk-manager.html
+ to: https://developer.android.com/studio/intro/update.html#sdk-manager \ No newline at end of file
diff --git a/docs/html/distribute/essentials/quality/core.jd b/docs/html/distribute/essentials/quality/core.jd
index 4b0b5467af88..0ff44eb97e00 100644
--- a/docs/html/distribute/essentials/quality/core.jd
+++ b/docs/html/distribute/essentials/quality/core.jd
@@ -1041,7 +1041,7 @@ data-cardsizes="6x3,6x3,6x3,6x3,6x3,6x3" data-maxresults="6">
CR-11
</td>
<td>
- Trigger and observe in the notications drawer all types of notifications
+ Trigger and observe in the notifications drawer all types of notifications
that the app can display. Expand notifications where applicable (Android
4.1 and higher), and tap all actions offered.
</td>
diff --git a/docs/html/distribute/googleplay/guide.jd b/docs/html/distribute/googleplay/guide.jd
index 6cb8cc0a68c2..293ccae4a234 100644
--- a/docs/html/distribute/googleplay/guide.jd
+++ b/docs/html/distribute/googleplay/guide.jd
@@ -1,43 +1,81 @@
page.title=Find Success on Google Play
-page.metaDescription=The updated guide that helps you find success with your app or game business on Google Play.
-page.tags="play,protips"
-page.timestamp=1447437450
-meta.tags="secrets, success, play, google"
-page.image=distribute/images/play_dev_guide.png
+page.metaDescription=Stay up to date with features, best practices, and strategies to help you grow your business and find success on Google Play.
+page.tags="playbook,play,protips"
+page.timestamp=1466793455
+meta.tags="playbook,play,google"
+page.image=images/cards/card-secrets-playbook_2x.jpg
@jd:body
+<div class="figure-right">
+ <img src="{@docRoot}images/gp-secrets-playbook.png"
+ style="width:180px" />
+ <div style="text-align:center">
+ <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&utm_source=dac&utm_medium=page&utm_campaign=evergreen&utm_source=global_co&utm_medium=prtnr&utm_content=Mar2515&utm_campaign=PartBadge&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1">
+ <img alt="Get it on Google Play"
+ src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
+ style="height:60px" />
+ </a>
+ </div>
+</div>
<p>
- We’ve created a downloadable guide to help you find success with your app or
- game business on Google Play. In it, you’ll find features, tips, and best
- practices to help you build an effective strategy to improve the quality,
- reach, retention, and monetization of your apps and games.
+ With the Playbook app for developers you can stay on top of the
+ features and best practices you can use to grow your app or game
+ business on Google Play.
</p>
+<ul>
+ <li>Choose topics relating to your business objectives to personalize
+ <strong>My Playbook</strong> with curated articles and videos from
+ Google, and from experts across the web.</li>
+ <li><strong>Explore</strong> the in-depth guide to Google’s developer
+ products, grouped by what you’re trying to do: develop, launch, engage,
+ grow, earn. </li>
+ <li>Take actions on items &mdash; complete, share, or dismiss them &mdash; and read
+ your <strong>Saved</strong> articles later, including offline if they’re
+ written in the app.</li>
+</ul>
+
+<p>
+The app is available in the following languages: <a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&utm_source=dac&utm_medium=page&utm_campaign=evergreen&hl=en">English</a>,
+<a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=id&utm_source=dac&utm_medium=page&utm_campaign=id">Bahasa
+Indonesia</a>, <a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=de&utm_source=dac&utm_medium=page&utm_campaign=de">Deutsch</a>,
+<a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=es-419&utm_source=dac&utm_medium=page&utm_campaign=es-419">español
+(Latinoamérica)</a>, <a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=fr&utm_source=dac&utm_medium=page&utm_campaign=fr">le
+français</a>, <a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=pt-BR&utm_source=dac&utm_medium=page&utm_campaign=pr-BR">português
+do Brasil</a>, <a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=vi&utm_source=dac&utm_medium=page&utm_campaign=vi">tiếng
+Việt</a>, <a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=ru&utm_source=dac&utm_medium=page&utm_campaign=ru">русский
+язы́к</a>, <a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=ko&utm_source=dac&utm_medium=page&utm_campaign=ko">한국어</a>,
+<a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=zh-CN&utm_source=dac&utm_medium=page&utm_campaign=zh-CN">中文
+(简体)</a>, <a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=zh-TW&utm_source=dac&utm_medium=page&utm_campaign=zh-TW">中文
+(繁體)</a>, and <a
+href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&hl=ja&utm_source=dac&utm_medium=page&utm_campaign=ja">日本語</a>.
+</p>
+
+<p>The Playbook app replaces the
+<a href="https://play.google.com/store/books/details?id=O2a5CgAAQBAJ">Secrets to
+App Success on Google Play</a> guides, which you can still read on Google Play Books.</p>
-<a href="https://play.google.com/store/books/details?id=O2a5CgAAQBAJ&utm_source=global_co&utm_medium=prtnr&utm_content=Mar2515&utm_campaign=PartBadge&pcampaignid=MKT-AC-global-none-all-co-pr-py-PartBadges-Oct1515-1">
- <img src="{@docRoot}images/distribute/secrets_v2_banner.jpg">
-</a>
<div style="text-align:center">
- <a href="https://play.google.com/store/books/details?id=O2a5CgAAQBAJ&utm_source=global_co&utm_medium=prtnr&utm_content=Mar2515&utm_campaign=PartBadge&pcampaignid=MKT-AC-global-none-all-co-pr-py-PartBadges-Oct1515-1">
- <img alt="Get it on Google Play"
- src="https://play.google.com/intl/en_us/badges/images/books/en-play-badge-border.png"
- style="height:60px" />
+ <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&utm_source=dac&utm_medium=page&utm_campaign=evergreen&utm_source=global_co&utm_medium=prtnr&utm_content=Mar2515&utm_campaign=PartBadge&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1">
+ <img src="{@docRoot}images/gp-secrets-playbook-lg.png" style="padding-top:1em;" />
</a>
+ <div style="text-align:center">
+ <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.secrets&utm_source=dac&utm_medium=page&utm_campaign=evergreen&utm_source=global_co&utm_medium=prtnr&utm_content=Mar2515&utm_campaign=PartBadge&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1">
+ <img alt="Get it on Google Play"
+ src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png"
+ style="height:60px" />
+ </a>
+ </div>
</div>
-
-<p><a
- href="https://docs.google.com/forms/d/1KFE9D7NlOrxM_jzmyMeZGaczgg1xo57jBoGq0R5nnsU/viewform">Sign
- up to be notified</a> when the guide is released in the following languages:
- Bahasa Indonesia, Deutsch, español (Latinoamérica), le français, português do
- Brasil, <span style="white-space: nowrap;">tiếng Việt</span>, <span style="white-space:
- nowrap;">русский язы́к</span>, <span style="white-space: nowrap;">ไทย</span>,
- <span style="white-space: nowrap;">한국어</span>, <span style="white-space: nowrap;">中文
- (简体)</span>, <span style="white-space: nowrap;">中文 (繁體)</span>, and <span style="white-space:
- nowrap;">日本語</span>.
-</p>
-
-<p>You can also <a
- href="{@docRoot}shareables/distribute/secrets_play/v2/web/secrets_to_app_success_v2_en.pdf">download
- the pdf</a>.
-</p>
diff --git a/docs/html/google/play/billing/billing_admin.jd b/docs/html/google/play/billing/billing_admin.jd
index a1135bfbb919..05f3ad593b9d 100644
--- a/docs/html/google/play/billing/billing_admin.jd
+++ b/docs/html/google/play/billing/billing_admin.jd
@@ -747,6 +747,15 @@ you at the conclusion of the purchase flow, as the value of the
<code>orderId</code> field of the <code>PURCHASE_STATE_CHANGED</code>
intent.</p>
+<p class="note">
+ <strong>Note:</strong> When a user completes a test purchase, the
+ <code>orderId</code> field remains blank. To track test transactions, use
+ the <code>purchaseToken</code> field instead. For more information about
+ working with test purchases, see <a
+ href="{@docRoot}google/play/billing/billing_testing.html">Testing In-app
+ Billing</a>.
+</p>
+
<p>In your app, you can use the order number as a general-purpose identifier for
the in-app purchase transaction. After the purchase, you can use the order
number as a means of tracking the transaction in reconciliation reports and for
diff --git a/docs/html/google/play/billing/billing_testing.jd b/docs/html/google/play/billing/billing_testing.jd
index 018276defb84..755f3ffd6220 100644
--- a/docs/html/google/play/billing/billing_testing.jd
+++ b/docs/html/google/play/billing/billing_testing.jd
@@ -79,14 +79,11 @@ launch. They let authorized user accounts make purchases of your in-app products
through Google Play without incurring any actual charges to the user
accounts.</p>
-<p>Once authorized for testing access, those users can make purchases without
-being charged.
-Test purchases are real orders and Google Play processes them in the same way as
-other orders. However, the <code>orderId</code> field for test purchases is
-blank.
-When purchases are complete, Google Play prevents the orders from
-going to financial processing, ensuring that there are no actual charges to user
-accounts, and automatically canceling the completed orders after 14 days.</p>
+<p>
+ Once authorized for testing access, those users can make purchases without
+ being charged. The <code>orderId</code> field for test purchases remains
+ blank, ensuring that there are no actual charges to user accounts.
+</p>
<p class="note">
<strong>Note:</strong> Test subscription purchases recur daily, regardless of
@@ -130,8 +127,8 @@ account. Users can confirm the account that is making a purchase by expanding th
purchase dialog.</p>
<p class="note">
- <strong>Note:</strong> For test subscription purchases, leave the {@code orderId}
- field blank. You can use the {@code purchaseToken} field to identify test purchases.
+ <strong>Note:</strong> For test purchases, leave the {@code orderId} field
+ blank. You can use the {@code purchaseToken} field to identify test purchases.
</p>
@@ -150,33 +147,22 @@ with a notice across the center of the purchase dialog, for easy identification.
<h4 id="cancelling">Canceling completed test purchases</h4>
<p>Google Play accumulates completed test purchases for each user but does not
-pass them on to financial processing. Over time, it automatically clears out
-the purchases by canceling them. </p>
+pass them on to financial processing.</p>
<p>In some cases, you might want to manually cancel a test purchase to continue
-testing. For canceling purchases, you have these options:</p>
-
-<ul>
-<li>Wait for the transactions to expire&mdash;Google Play clears completed test
-purchases 14 days after their purchase date. </li>
-<li>Cancel purchases manually&mdash;you can go to the Google payments merchant
-center, look up the transaction, and then cancel it. You can find transactions
-by looking up their order numbers.</li>
+testing. To do so, open the app page in the Play Store. If the test purchase
+that you want to cancel is a subscription, you can also use the
+<a href="https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/cancel">
+{@code cancel()}</a> method of the Purchases.subscriptions API.
</ul>
-<p>
- You can cancel test subscriptions purchases from the app page in the Play Store,
- or use the
- <a href="https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/cancel">
- {@code cancel}</a> method.
-</p>
-
<p class="caution">
<strong>Important:</strong> The
<a href="https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/refund">
- {@code refund}</a> and
+ {@code refund()}</a> and
<a href="https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/revoke">
- {@code revoke}</a> methods do not support test purchases.
+ {@code revoke()}</a> methods of the Purchases.subscriptions API don't support
+ test purchases.
</p>
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index 564215ead4af..fc795ff6a63f 100755
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -21,7 +21,7 @@ parent.link=index.html
<h2>Related Samples</h2>
<ol>
- <li><a href="{@docRoot}resources/samples/RenderScript/HelloCompute/index.html">Hello
+ <li><a class="external-link"href="https://github.com/android/platform_development/tree/master/samples/RenderScript/HelloCompute">Hello
Compute</a></li>
</ol>
</div>
diff --git a/docs/html/images/cards/card-secrets-playbook_2x.jpg b/docs/html/images/cards/card-secrets-playbook_2x.jpg
new file mode 100644
index 000000000000..87e6c8c37124
--- /dev/null
+++ b/docs/html/images/cards/card-secrets-playbook_2x.jpg
Binary files differ
diff --git a/docs/html/images/gp-secrets-playbook-lg.png b/docs/html/images/gp-secrets-playbook-lg.png
new file mode 100644
index 000000000000..08b2a338b0e6
--- /dev/null
+++ b/docs/html/images/gp-secrets-playbook-lg.png
Binary files differ
diff --git a/docs/html/images/gp-secrets-playbook.png b/docs/html/images/gp-secrets-playbook.png
new file mode 100644
index 000000000000..831376b9aef2
--- /dev/null
+++ b/docs/html/images/gp-secrets-playbook.png
Binary files differ
diff --git a/docs/html/images/testing/test-types.zip b/docs/html/images/testing/test-types.zip
new file mode 100644
index 000000000000..d433b915ff15
--- /dev/null
+++ b/docs/html/images/testing/test-types.zip
Binary files differ
diff --git a/docs/html/images/testing/test-types_2x.png b/docs/html/images/testing/test-types_2x.png
new file mode 100644
index 000000000000..0a374aaf6538
--- /dev/null
+++ b/docs/html/images/testing/test-types_2x.png
Binary files differ
diff --git a/docs/html/jd_extras_en.js b/docs/html/jd_extras_en.js
index 6295e0efd00c..5e271b978580 100644
--- a/docs/html/jd_extras_en.js
+++ b/docs/html/jd_extras_en.js
@@ -3758,8 +3758,8 @@ METADATA['en'].carousel = {
},
"distribute/googleplay/guide.html": {
"image": "images/distribute/hero-secrets-to-app-success.jpg",
- "title": "Secrets to App Success on Google Play",
- "summary": "Get the updated guide full of useful features, tips, and best practices that will help you grow a successful app or game business on Google Play.",
+ "title": "Playbook for Developers",
+ "summary": "Stay up to date with features, best practices, and strategies to help you grow your business and find success on Google Play.",
},
"about/versions/lollipop.html": {
"image": "images/home/hero-lollipop_2x.png",
diff --git a/docs/html/ndk/downloads/index.jd b/docs/html/ndk/downloads/index.jd
index 47d3113b8921..28860b28894c 100644
--- a/docs/html/ndk/downloads/index.jd
+++ b/docs/html/ndk/downloads/index.jd
@@ -332,35 +332,199 @@ $('#Downloads').after($('#download-table'));
<h2 id="rel">Release Notes</h2>
<p>
- Android NDK, Revision 11c <em>(March 2016)</em>
+ Android NDK, Revision 12 <em>(June 2016)</em>
</p>
<dl>
- <dt>
- NDK
- </dt>
-
- <dd>
- <ul>
- <li>Changes
- <ul>
- <li>Applied additional fixes to the {@code ndk-gdb.py} script.
- </li>
- <li>Added an optional package name argument to the {@code ndk-gdb}
- command {@code --attach} option.
- (<a href="https://github.com/android-ndk/ndk/issues/13">Issue 13</a>)
- </li>
- <li>Fixed invalid toolchain paths for 32-bit Windows platform.
- (<a href="https://github.com/android-ndk/ndk/issues/45">Issue 45</a>)
- </li>
- <li>Fixed the relative path for the {@code ndk-which} command.
- (<a href="https://github.com/android-ndk/ndk/issues/29">Issue 29</a>)
- </li>
- <li>Fixed use of cygpath for the libgcc compiler.
- (Android <a href="http://b.android.com/195486">Issue 195486</a>)
- </li>
- </ul>
- </li>
- </ul>
- </dd>
-</dl> \ No newline at end of file
+<dt>
+ Announcements
+</dt>
+
+<ul>
+ <li>The <code>ndk-build</code> command will default to using
+ Clang in an upcoming release. GCC will be removed in a later release.
+ </li>
+ <li>The <code>make-standalone-toolchain.sh</code> script will be removed
+ in an upcoming release. If you use this script, please plan to migrate to the
+ <code>make_standalone_toolchain.py</code> as soon as possible.
+ </li>
+</ul>
+
+<dt>
+ NDK
+</dt>
+
+<ul>
+ <li>Removed support for the armeabi-v7a-hard ABI. See the explanation in the
+ <a href=
+ "https://android.googlesource.com/platform/ndk/+/ndk-r12-release/docs/HardFloatAbi.md">
+ documentation</a>.
+ </li>
+
+ <li>Removed all sysroots for platform levels prior to Android 2.3 (API level 9).
+ We dropped support for them in NDK r11, but neglected to actually remove them.
+ </li>
+
+ <li>Updated exception handling when using c++_shared on ARM32 so that it
+ mostly works (see <a href="#known-issues">Known Issues</a>). The unwinder
+ is now linked into each linked object rather than into libc++ itself.
+ </li>
+
+ <li>Pruned the default compiler flags (<a href=
+ "https://github.com/android-ndk/ndk/issues/27">NDK Issue 27</a>). You can see
+ details of this update in <a href=
+ "https://android-review.googlesource.com/#/c/207721/5">Change 207721</a>.
+ </li>
+
+ <li>Added a Python implementation of standalone toolchains in <code>
+ build/tools/make_standalone_toolchain.py</code>. On Windows, you no longer
+ need Cygwin to use this feature. Note that the bash flavor will be removed
+ in an upcoming release, so please test the new one now.
+ </li>
+
+ <li>Configured Clang debug builds to have the <code>-fno-limit-debug-info</code>
+ option is enabled by default. This change enables better debugging with LLDB.
+ </li>
+
+ <li>Enabled the <code>--build-id</code> as a default option. This option
+ causes an identifier to be shown in native crash reports so you can easily
+ identify which version of your code was running.
+ </li>
+
+ <li>Fixed issue with <code>NDK_USE_CYGPATH</code> so that it no longer causes
+ problems with libgcc
+ (<a href="http://b.android.com/195486">Issue 195486</a>).
+ </li>
+
+ <li>Enabled the following options as default:
+ <code>-Wl,--warn-shared-textrel</code> and <code>-Wl,--fatal-warnings</code>.
+ If you have shared text relocations, your app does not load on Android 6.0
+ (API level 23) and higher. Note that this configuration has never been
+ allowed for 64-bit apps.
+ </li>
+
+ <li>Fixed a few issues so that precompiled headers work better
+ (<a href="https://github.com/android-ndk/ndk/issues/14">NDK Issue 14</a>,
+ <a href="https://github.com/android-ndk/ndk/issues/16">NDK Issue 16</a>).
+ </li>
+
+ <li>Removed unreachable ARM (non-thumb) STL libraries.
+ </li>
+
+ <li>Added Vulkan support to android-24.
+ </li>
+
+ <li>Added Choreographer API to android-24.
+ </li>
+
+ <li>Added libcamera2 APIs for devices that support the
+ <code>INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED</code> feature level or higher.
+ For more information, see the
+ <a href="{@docRoot}reference/android/hardware/camera2/CameraCharacteristics.html#INFO_SUPPORTED_HARDWARE_LEVEL">
+ <code>CameraCharacteristics</code></a> reference.
+ </li>
+
+</ul>
+
+<dt>
+ Clang
+</dt>
+
+<ul>
+ <li>Clang has been updated to 3.8svn (r256229, build 2812033). Note that
+ Clang packaged in the Windows 64-bit NDK is actually 32-bit.
+ </li>
+
+ <li>Fixed <code>__thread</code> so that it works for real this time.
+ </li>
+</ul>
+
+<dt>
+ GCC
+</dt>
+
+<ul>
+ <li>Synchronized the compiler with the ChromeOS GCC @ google/gcc-4_9 r227810.
+ </li>
+
+ <li>Backported coverage sanitizer patch from ToT (r231296).
+ </li>
+
+ <li>Fixed <code>libatomic</code> to not use ifuncs (<a href=
+ "https://github.com/android-ndk/ndk/issues/31">NDK Issue 31</a>).
+ </li>
+</ul>
+
+<dt>
+ Binutils
+</dt>
+
+<ul>
+ <li>Silenced the "Erratum 843419 found and fixed" info messages.
+ </li>
+
+ <li>Introduced option <code>--long-plt</code> to fix an internal linker error
+ when linking huge arm32 binaries.
+ </li>
+
+ <li>Fixed wrong run time stubs for <code>AArch64</code>. This problem was
+ causing jump addresses to be calculated incorrectly for very large
+ dynamic shared objects (DSOs).
+ </li>
+
+ <li>Introduced default option <code>--no-apply-dynamic</code> to work around
+ a dynamic linker bug for earlier Android releases.
+ </li>
+
+ <li>Fixed a known issue with NDK r11 where <code>dynamic_cast</code> was not
+ working with Clang, x86, stlport_static and optimization.
+ </li>
+</ul>
+
+<dt>
+ GDB
+</dt>
+
+<ul>
+ <li>Updated to GDB version 7.11. For more information about this release, see
+ <a href="https://www.gnu.org/software/gdb/news/">GDB News</a>.
+ </li>
+
+ <li>Fixed a number of bugs in the <code>ndk-gdb.py</code> script.
+ </li>
+</ul>
+
+<dt id="known-issues">
+ Known Issues
+</dt>
+
+<ul>
+ <li>The x86 <a href="http://source.android.com/devices/tech/debug/asan.html">Address
+ Sanitizer</a> (ASAN) currently does not work. For more information, see
+ <a href="https://android-review.googlesource.com/#/c/186276/">Issue 186276</a>.
+ </li>
+
+ <li>Exception unwinding with <code>c++_shared</code> does not work for ARM on
+ Android 2.3 (API level 9) or Android 4.0 (API level 14).
+ </li>
+
+ <li>Bionic headers and libraries for Android 6.0 (API level 23) and higher
+ are not yet exposed despite the presence of android-24. Those platforms still
+ have the Android 5.0 (API level 21) headers and libraries, which is consistent
+ with NDK r11.
+ </li>
+
+ <li>The RenderScript tools are not present, which is consistent with
+ NDK r11.
+ (<a href="https://github.com/android-ndk/ndk/issues/7">NDK Issue 7</a>)
+ </li>
+
+ <li>In <code>NdkCameraMetadataTags.h</code> header file, the camera metadata
+ tag enum value <code>ACAMERA_STATISTICS_LENS_SHADING_CORRECTION_MAP</code>
+ was listed by accident and will be removed in next release. Use
+ the <code>ACAMERA_STATISTICS_LENS_SHADING_MAP</code> value instead.
+ </li>
+
+</ul>
+
+</dl>
diff --git a/docs/html/ndk/downloads/revision_history.jd b/docs/html/ndk/downloads/revision_history.jd
index c5a0d4895489..211b64e5be4b 100644
--- a/docs/html/ndk/downloads/revision_history.jd
+++ b/docs/html/ndk/downloads/revision_history.jd
@@ -10,6 +10,44 @@ took place in each new version.</p>
<p>
<a href="#" onclick="return toggleContent(this)"> <img
src="/assets/images/styles/disclosure_down.png" class="toggle-content-img" alt=""
+ >Android NDK, Revision 11c</a> <em>(March 2016)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+
+<dl>
+ <dd>
+ <ul>
+ <li>Changes
+ <ul>
+ <li>Applied additional fixes to the {@code ndk-gdb.py} script.
+ </li>
+ <li>Added an optional package name argument to the {@code ndk-gdb}
+ command {@code --attach} option.
+ (<a href="https://github.com/android-ndk/ndk/issues/13">Issue 13</a>)
+ </li>
+ <li>Fixed invalid toolchain paths for 32-bit Windows platform.
+ (<a href="https://github.com/android-ndk/ndk/issues/45">Issue 45</a>)
+ </li>
+ <li>Fixed the relative path for the {@code ndk-which} command.
+ (<a href="https://github.com/android-ndk/ndk/issues/29">Issue 29</a>)
+ </li>
+ <li>Fixed use of cygpath for the libgcc compiler.
+ (Android <a href="http://b.android.com/195486">Issue 195486</a>)
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </dd>
+</dl>
+
+ </div>
+</div>
+
+<div class="toggle-content closed">
+<a name="11b"></a>
+ <p>
+ <a href="#" onclick="return toggleContent(this)"> <img
+ src="/assets/images/styles/disclosure_down.png" class="toggle-content-img" alt=""
>Android NDK, Revision 11b</a> <em>(March 2016)</em>
</p>
<div class="toggle-content-toggleme">
diff --git a/docs/html/ndk/guides/setup.jd b/docs/html/ndk/guides/setup.jd
index 1459bfefffa4..d3ace07a1c4b 100644
--- a/docs/html/ndk/guides/setup.jd
+++ b/docs/html/ndk/guides/setup.jd
@@ -34,8 +34,7 @@ information on that topic, see the
<p>To install and configure the NDK, follow these steps:</p>
<ol type="1">
<li>Get and install the <a href="{@docRoot}studio/index.html">Android SDK</a>.</li>
-<li><a href="{@docRoot}ndk/downloads/index.html">Download</a> and
-<a href="{@docRoot}ndk/downloads/index.html#extract">extract</a> the NDK,
+<li><a href="{@docRoot}ndk/downloads/index.html">Download</a> the NDK,
making sure to download the correct version for your development platform. You may place the
unzipped directory anywhere on your local drive.</li>
<li>Update your {@code PATH} environment variable with the location of the directory that
diff --git a/docs/html/preview/features/picture-in-picture.jd b/docs/html/preview/features/picture-in-picture.jd
index c089feb17670..03a17682a0a4 100644
--- a/docs/html/preview/features/picture-in-picture.jd
+++ b/docs/html/preview/features/picture-in-picture.jd
@@ -220,7 +220,11 @@ in any area that can be obscured by the PIP window.</p>
<p>When an activity is in PIP mode, by default it doesn't get input focus. To
receive input events while in PIP mode, use
-<code>MediaSession.setMediaButtonReceiver()</code>.</p>
+{@link android.media.session.MediaSession#setCallback
+MediaSession.setCallback()}. For more information on using
+{@link android.media.session.MediaSession#setCallback setCallback()} see
+<a href="{@docRoot}training/tv/playback/now-playing.html">Displaying
+a Now Playing Card</a>.</p>
<p>When your app is in PIP mode, video playback in the PIP window can cause
audio interference with another app, such as a music player app or voice search
@@ -228,4 +232,4 @@ app. To avoid this, request audio focus when you start playing the video,
and handle audio focus change notifications, as described in
<a href="{@docRoot}training/managing-audio/audio-focus.html">Managing Audio
Focus</a>. If you receive notification of audio focus loss when in PIP mode,
-pause or stop video playback.</p> \ No newline at end of file
+pause or stop video playback.</p>
diff --git a/docs/html/sdk/sdk_vars.cs b/docs/html/sdk/sdk_vars.cs
index 32fdb0aec360..80da297c9bf7 100644
--- a/docs/html/sdk/sdk_vars.cs
+++ b/docs/html/sdk/sdk_vars.cs
@@ -1,18 +1,19 @@
<?cs
-set:ndk.mac64_download='android-ndk-r11c-darwin-x86_64.zip' ?><?cs
-set:ndk.mac64_bytes='772428792' ?><?cs
-set:ndk.mac64_checksum='4ce8e7ed8dfe08c5fe58aedf7f46be2a97564696' ?><?cs
+set:ndk.mac64_download='android-ndk-r12-darwin-x86_64.zip' ?><?cs
+set:ndk.mac64_bytes='734014148' ?><?cs
+set:ndk.mac64_checksum='708d4025142924f7097a9f44edf0a35965706737' ?><?cs
-set:ndk.linux64_download='android-ndk-r11c-linux-x86_64.zip' ?><?cs
-set:ndk.linux64_bytes='794135138' ?><?cs
-set:ndk.linux64_checksum='de5ce9bddeee16fb6af2b9117e9566352aa7e279' ?><?cs
+set:ndk.linux64_download='android-ndk-r12-linux-x86_64.zip' ?><?cs
+set:ndk.linux64_bytes='755431993' ?><?cs
+set:ndk.linux64_checksum='b7e02dc733692447366a2002ad17e87714528b39' ?><?cs
-set:ndk.win64_download='android-ndk-r11c-windows-x86_64.zip' ?><?cs
-set:ndk.win64_bytes='771407642' ?><?cs
-set:ndk.win64_checksum='3d89deb97b3191c7e5555f1313ad35059479f071' ?><?cs
-set:ndk.win32_download='android-ndk-r11c-windows-x86.zip' ?><?cs
-set:ndk.win32_bytes='728899082' ?><?cs
-set:ndk.win32_checksum='ff939bde6cd374eecbd2c3b2ad218697f9a5038c'
+set:ndk.win64_download='android-ndk-r12-windows-x86.zip' ?><?cs
+set:ndk.win64_bytes='706332762' ?><?cs
+set:ndk.win64_checksum='37fcd7acf6012d0068a57c1524edf24b0fef69c9' ?><?cs
+
+set:ndk.win32_download='android-ndk-r12-windows-x86_64.zip' ?><?cs
+set:ndk.win32_bytes='749444245' ?><?cs
+set:ndk.win32_checksum='80d64a77aab52df867ac55cec1e976663dd3326f'
?>
<?cs
def:size_in_mb(bytes)
diff --git a/docs/html/topic/libraries/data-binding/index.jd b/docs/html/topic/libraries/data-binding/index.jd
index ca8784ebfcfb..293de51ea000 100644
--- a/docs/html/topic/libraries/data-binding/index.jd
+++ b/docs/html/topic/libraries/data-binding/index.jd
@@ -18,7 +18,7 @@ page.tags="databinding", "layouts"
<a href="#data_binding_layout_files">Data Binding Layout Files</a>
<ol>
<li>
- <a href="#writing_expressions">Writing your first data binding
+ <a href="#writing_expressions">Writing your first set of data binding
expressions</a>
</li>
@@ -29,9 +29,16 @@ page.tags="databinding", "layouts"
<li>
<a href="#binding_data">Binding Data</a>
</li>
-
<li>
- <a href="#binding_events">Binding Events</a>
+ <a href="#event_handling">Event Handling</a>
+ <ol>
+ <li>
+ <a href="#method_references">Method References</a>
+ </li>
+ <li>
+ <a href="#listener_bindings">Listener Bindings</a>
+ </li>
+ </ol>
</li>
</ol>
</li>
@@ -147,27 +154,34 @@ page.tags="databinding", "layouts"
application logic and layouts.
</p>
-<p>The Data Binding Library offers both flexibility and broad compatibility
-&mdash; it's a support library, so you can use it with all Android platform
-versions back to <strong>Android 2.1</strong> (API level 7+).</p>
+<p>
+ The Data Binding Library offers both flexibility and broad compatibility —
+ it's a support library, so you can use it with all Android platform versions
+ back to <strong>Android 2.1</strong> (API level 7+).
+</p>
-<p>To use data binding, Android Plugin for Gradle <strong>1.5.0-alpha1</strong>
-or higher is required.</p>
+<p>
+ To use data binding, Android Plugin for Gradle <strong>1.5.0-alpha1</strong>
+ or higher is required.
+</p>
<h2 id="build_environment">
Build Environment
</h2>
-<p>To get started with Data Binding, download the library from the Support
-repository in the Android SDK manager. </p>
-
<p>
-To configure your app to use data binding, add the <code>dataBinding</code> element to your
-<code>build.gradle</code> file in the app module.
+ To get started with Data Binding, download the library from the Support
+ repository in the Android SDK manager.
</p>
- <p>Use the following code snippet to configure data binding: </p>
+<p>
+ To configure your app to use data binding, add the <code>dataBinding</code>
+ element to your <code>build.gradle</code> file in the app module.
+</p>
+<p>
+ Use the following code snippet to configure data binding:
+</p>
<pre>
android {
....
@@ -176,13 +190,17 @@ android {
}
}
</pre>
+<p>
+ If you have an app module that depends on a library which uses data binding,
+ your app module must configure data binding in its <code>build.gradle</code>
+ file as well.
+</p>
-<p>If you have an app module that depends on a library which uses data binding, your app module
- must configure data binding in its <code>build.gradle</code> file as well.</p>
-
-<p>Also, make sure you are using a compatible version of Android Studio.
-<strong>Android Studio 1.3</strong> and later provides support for data binding as described in
-<a href="#studio_support">Android Studio Support for Data Binding</a>.
+<p>
+ Also, make sure you are using a compatible version of Android Studio.
+ <strong>Android Studio 1.3</strong> and later provides support for data
+ binding as described in <a href="#studio_support">Android Studio Support for
+ Data Binding</a>.
</p>
<h2 id="data_binding_layout_files">
@@ -190,7 +208,7 @@ android {
</h2>
<h3 id="writing_expressions">
- Writing your first data binding expressions
+ Writing your first set of data binding expressions
</h3>
<p>
@@ -223,20 +241,19 @@ android {
The user <strong>variable</strong> within <strong>data</strong> describes a
property that may be used within this layout.
</p>
-
<pre>
&lt;<strong>variable name="user" type="com.example.User"</strong>/&gt;
</pre>
<p>
Expressions within the layout are written in the attribute properties using
- the “<code>&commat;{}</code>” syntax. Here, the TextView’s text is set to the
- firstName property of user:
+ the “<code>&amp;commat;{}</code>” syntax. Here, the TextView’s text is set to
+ the firstName property of user:
</p>
<pre>
&lt;TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="&commat;{user.firstName}"/&gt;
+ android:text="&amp;commat;{user.firstName}"/&gt;
</pre>
<h3 id="data_object">
Data Object
@@ -261,7 +278,6 @@ public class User {
to have data that is read once and never changes thereafter. It is also
possible to use a JavaBeans objects:
</p>
-
<pre>
public class User {
private final String firstName;
@@ -280,11 +296,12 @@ public class User {
</pre>
<p>
From the perspective of data binding, these two classes are equivalent. The
- expression <strong><code>&commat;{user.firstName}</code></strong> used for
- the TextView’s <strong><code>android:text</code></strong> attribute will
+ expression <strong><code>&amp;commat;{user.firstName}</code></strong> used
+ for the TextView’s <strong><code>android:text</code></strong> attribute will
access the <strong><code>firstName</code></strong> field in the former class
- and the <code>getFirstName()</code> method in the latter class. Alternatively, it
- will also be resolved to <code>firstName()</code> if that method exists.
+ and the <code>getFirstName()</code> method in the latter class.
+ Alternatively, it will also be resolved to <code>firstName()</code> if that
+ method exists.
</p>
<h3 id="binding_data">
@@ -328,16 +345,38 @@ ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, fal
//or
ListItemBinding binding = DataBindingUtil.<em>inflate</em>(layoutInflater, R.layout.<em><strong>list_item</strong></em>, viewGroup, <strong>false</strong>);
</pre>
-
-<h3 id="binding_events">
- Binding Events
-</h3>
+<h3 id="event_handling">Event Handling</h3>
<p>
- Events may be bound to handler methods directly, similar to the way
- <strong><code>android:onClick</code></strong> can be assigned to a method in the Activity.
- Event attribute names are governed by the name of the listener method with a few exceptions.
- For example, {@link android.view.View.OnLongClickListener} has a method {@link android.view.View.OnLongClickListener#onLongClick onLongClick()},
- so the attribute for this event is <code>android:onLongClick</code>.
+Data Binding allows you to write expressions handling events that are dispatched from the views (e.g. onClick).
+Event attribute names are governed by the name of the listener method with a few exceptions.
+For example, {@link android.view.View.OnLongClickListener} has a method {@link android.view.View.OnLongClickListener#onLongClick onLongClick()},
+so the attribute for this event is <code>android:onLongClick</code>.
+There are two ways to handle an event.
+</p>
+<ul>
+ <li>
+ <a href="#method_references">Method References</a>: In your expressions, you can reference methods that conform to the signature of the listener method. When an expression evaluates to a method reference, Data Binding wraps the method reference and owner object in a listener, and sets that listener on the target view. If the expression evaluates to null, Data Binding does not create a listener and sets a null listener instead.
+ </li>
+ <li>
+ <a href="#listener_bindings">Listener Bindings</a>: These are lambda expressions that are evaluated when the event happens.
+Data Binding always creates a listener, which it sets on the view. When the event is dispatched, the listener evaluates the lambda expression.
+ </li>
+</ul>
+<h4 id="method_references">
+ Method References
+</h4>
+<p>
+ Events can be bound to handler methods directly, similar to the way
+ <strong><code>android:onClick</code></strong> can be assigned to a method in an Activity.
+ One major advantage compared to the {@code View#onClick} attribute is that the expression
+ is processed at compile time, so if the method does not exist or its signature is not
+ correct, you receive a compile time error.</p>
+<p>
+ The major difference between Method References and Listener Bindings is that
+ the actual listener implementation is created when the data is bound, not
+ when the event is triggered. If you prefer to evaluate the expression when
+ the event happens, you should use <a href="#listener_bindings">listener
+ binding</a>.
</p>
<p>
To assign an event to its handler, use a normal binding expression, with the value
@@ -345,7 +384,6 @@ ListItemBinding binding = DataBindingUtil.<em>inflate</em>(layoutInflater, R.lay
</p>
<pre>public class MyHandlers {
public void onClickFriend(View view) { ... }
- public void onClickEnemy(View view) { ... }
}
</pre>
<p>
@@ -365,14 +403,121 @@ ListItemBinding binding = DataBindingUtil.<em>inflate</em>(layoutInflater, R.lay
&lt;TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="&commat;{user.firstName}"
- android:onClick="&commat;{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/&gt;
- &lt;TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="&commat;{user.lastName}"
- android:onClick="&commat;{user.isFriend ? handlers.onClickFriend : handlers.onClickEnemy}"/&gt;
+ android:onClick="&commat;{handlers::onClickFriend}"/&gt;
&lt;/LinearLayout&gt;
&lt;/layout&gt;
</pre>
+<p>
+Note that the signature of the method in the expression must exactly match the signature of the method in the
+Listener object.
+</p>
+<h4 id="listener_bindings">
+ Listener Bindings
+</h4>
+<p>
+ Listener Bindings are binding expressions that run when an event happens.
+ They are similar to method references, but they let you run arbitrary data
+ binding expressions. This feature is available with Android Gradle Plugin for Gradle
+ version 2.0 and later.
+</p>
+<p>
+ In method references, the parameters of the method must
+ match the parameters of the event listener. In Listener Bindings, only your
+ return value must match the expected return value of the listener (unless it
+ is expecting void).
+ For example, you can have a presenter class that has the following method:
+</p>
+<pre>
+public class Presenter {
+ public void onSaveClick(Task task){}
+}
+</pre>
+ Then you can bind the click event to your class as follows:
+<pre>
+ &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+ &lt;layout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
+ &lt;data&gt;
+ &lt;variable name=&quot;task&quot; type=&quot;com.android.example.Task&quot; /&gt;
+ &lt;variable name=&quot;presenter&quot; type=&quot;com.android.example.Presenter&quot; /&gt;
+ &lt;/data&gt;
+ &lt;LinearLayout android:layout_width=&quot;match_parent&quot; android:layout_height=&quot;match_parent&quot;&gt;
+ &lt;Button android:layout_width=&quot;wrap_content&quot; android:layout_height=&quot;wrap_content&quot;
+ android:onClick=&quot;@{() -&gt; presenter.onSaveClick(task)}&quot; /&gt;
+ &lt;/LinearLayout&gt;
+ &lt;/layout&gt;
+</pre>
+<p>
+ Listeners are represented by lambda expressions that are allowed only as root
+ elements of your expressions. When a callback is used in an expression, Data
+ Binding automatically creates the necessary listener and registers for the
+ event. When the view fires the event, Data Binding evaluates the given
+ expression. As in regular binding expressions, you still get the null and
+ thread safety of Data Binding while these listener expressions are being
+ evaluated.
+</p>
+<p>
+ Note that in the example above, we haven't defined the {@code view} parameter
+ that is passed into {@link
+ android.view.View.OnClickListener#onClick(android.view.View view)}. Listener
+ bindings provide two choices for listener parameters: you can either ignore
+ all parameters to the method or name all of them. If you prefer to name the
+ parameters, you can use them in your expression. For example, the expression
+ above could be written as:
+</p>
+<pre>
+ android:onClick=&quot;@{(view) -&gt; presenter.onSaveClick(task)}&quot;
+</pre>
+Or if you wanted to use the parameter in the expression, it could work as follows:
+<pre>
+public class Presenter {
+ public void onSaveClick(View view, Task task){}
+}
+</pre>
+<pre>
+ android:onClick=&quot;@{(theView) -&gt; presenter.onSaveClick(theView, task)}&quot;
+</pre>
+You can use a lambda expression with more than one parameter:
+<pre>
+public class Presenter {
+ public void onCompletedChanged(Task task, boolean completed){}
+}
+</pre>
+<pre>
+ &lt;CheckBox android:layout_width=&quot;wrap_content&quot; android:layout_height=&quot;wrap_content&quot;
+ android:onCheckedChanged=&quot;@{(cb, isChecked) -&gt; presenter.completeChanged(task, isChecked)}&quot; /&gt;
+</pre>
+<p>
+ If the event you are listening to returns a value whose type is not {@code
+ void}, your expressions must return the same type of value as well. For
+ example, if you want to listen for the long click event, your expression
+ should return {@code boolean}.
+</p>
+<pre>
+public class Presenter {
+ public boolean onLongClick(View view, Task task){}
+}
+</pre>
+<pre>
+ android:onLongClick=&quot;@{(theView) -&gt; presenter.onLongClick(theView, task)}&quot;
+</pre>
+<p>
+If the expression cannot be evaluated due to {@code null} objects, Data Binding returns
+the default Java value for that type. For example, {@code null} for reference types, {@code 0} for {@code int},
+{@code false} for {@code boolean}, etc.
+</p>
+<p>
+If you need to use an expression with a predicate (e.g. ternary), you can use
+{@code void} as a symbol.
+</p>
+<pre>
+ android:onClick=&quot;@{(v) -&gt; v.isVisible() ? doSomething() : void}&quot;
+</pre>
+
+<h5>Avoid Complex Listeners</h5>
+Listener expressions are very powerful and can make your code very easy to read.
+On the other hand, listeners containing complex expressions make your layouts hard to read and unmaintainable.
+These expressions should be as simple as passing available data from your UI to your callback method. You should implement
+any business logic inside the callback method that you invoked from the listener expression.
<p>
Some specialized click event handlers exist and they need an attribute other than
diff --git a/docs/html/training/articles/user-data-ids.jd b/docs/html/training/articles/user-data-ids.jd
index 5a4648b72829..91021669b649 100644
--- a/docs/html/training/articles/user-data-ids.jd
+++ b/docs/html/training/articles/user-data-ids.jd
@@ -189,15 +189,15 @@ page.article=true
<div style="padding:.5em 2em;">
<div style="border-left:4px solid #999;padding:0 1em;font-style:italic;">
-<p>...upon reset, a new advertising
+<p>...if reset, a new advertising
identifier must not be connected to a previous advertising identifier or data
derived from a previous advertising identifier without the explicit consent
- of the user</span></p>
+ of the user.</span></p>
</div>
</div>
<p>
- <em><strong>Always respect the associated Interest Based Advertising
+ <em><strong>Always respect the associated Personalized Ads
flag</strong></em>. Advertising IDs are configurable in that users can limit
the amount of tracking associated with the ID. Always use the <code><a href=
"https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html#isLimitAdTrackingEnabled()">
@@ -210,10 +210,10 @@ page.article=true
<div style="padding:.5em 2em;">
<div style="border-left:4px solid #999;padding:0 1em;font-style:italic;">
-<p>...you must abide by a user’s ‘opt out of
- interest-based advertising’ setting. If a user has enabled this setting, you
+<p>...you must abide by a user’s ‘Opt out of interest-based advertising’ or 'Opt
+ out of Ads Personalization' setting. If a user has enabled this setting, you
may not use the advertising identifier for creating user profiles for
- advertising purposes or for targeting users with interest-based advertising.
+ advertising purposes or for targeting users with personalized advertising.
Allowed activities include contextual advertising, frequency capping,
conversion tracking, reporting and security and fraud detection.</span></p>
</div>
@@ -286,7 +286,8 @@ page.article=true
<code>account_id</code> column in both tables, which would be a violation of
the <a href=
"https://play.google.com/about/developer-content-policy.html">Google Play
- Developer Content Policy</a>.
+ Developer Content Policy</a>, if you did not get explicit permission from
+ your users.
</p>
<p>
diff --git a/docs/html/training/auto/audio/index.jd b/docs/html/training/auto/audio/index.jd
index aa20e3a29f9b..3a1b1e883494 100644
--- a/docs/html/training/auto/audio/index.jd
+++ b/docs/html/training/auto/audio/index.jd
@@ -21,6 +21,7 @@ page.image=auto/images/assets/icons/media_app_playback.png
<li><a href="#config_manifest">Configure Your Manifest</a></li>
<li><a href="#isconnected">Determine if Your App is Connected</a></li>
<li><a href="#alarm">Handle Alarms</a></li>
+ <li><a href="#mediaadv">Handle Media Advertisements</a></li>
<li><a href="#implement_browser">Build a Browser Service</a></li>
<li><a href="#implement_callback">Implement Play Controls</a></li>
<li><a href="#support_voice">Support Voice Actions</a></li>
@@ -261,7 +262,7 @@ following things:
<ul>
<li>Disable the alarm.</li>
<li>Play the alarm over
-<a href="{@docRoot}reference/android/media/AudioManager.html">STREAM_ALARM</a>,
+<a href="{@docRoot}reference/android/media/AudioManager.html#STREAM_ALARM">STREAM_ALARM</a>,
and provide a UI on the phone screen to disable the alarm.</li>
</ul>
@@ -279,6 +280,33 @@ The following code snippet checks whether an app is running in car mode:
}
</pre>
+<h2 id="mediaadv">Handle Media Advertisements</h2>
+<p>By default, Android Auto displays a notification when
+the media metadata changes during an audio playback session. When a media
+app switches from playing music to running an advertisement, it is distracting
+(and unnecessary) to display a notification to the user. To prevent Android Auto
+from displaying a notification in this case, you must set the media metadata
+key {@code android.media.metadata.ADVERTISEMENT} to 1, as shown in the code
+snippet below:
+
+<pre>
+
+&#64;Override
+public static final String EXTRA_METADATA_ADVERTISEMENT =
+ "android.media.metadata.ADVERTISEMENT";
+
+public void onPlayFromMediaId(String mediaId, Bundle extras) {
+ MediaMetadata.Builder builder = new MediaMetadata.Builder();
+ // ...
+ if (isAd(mediaId)) {
+ builder.putLong(EXTRA_METADATA_ADVERTISEMENT, 1);
+ }
+ // ...
+ mediaSession.setMetadata(builder.build());
+}
+
+</pre>
+
<h2 id="implement_browser">Build a Browser Service</h2>
<p>Auto devices interact with your app by contacting its implementation of a
diff --git a/docs/html/training/material/animations.jd b/docs/html/training/material/animations.jd
index 9c78545b99b6..96cc5a1d9c46 100644
--- a/docs/html/training/material/animations.jd
+++ b/docs/html/training/material/animations.jd
@@ -415,12 +415,16 @@ android.animation.StateListAnimator} as an XML resource:</p>
&lt;/selector>
</pre>
-<p>To attach custom view state animations to a view, define an animator using the
-<code>selector</code> element in an XML resource file as in this example, and assign it to your
-view with the <code>android:stateListAnimator</code> attribute. To assign a state list animator
-to a view in your code, use the {@link android.animation.AnimatorInflater#loadStateListAnimator
-AnimationInflater.loadStateListAnimator()} method, and assign the animator to your view with the
-{@link android.view.View#setStateListAnimator View.setStateListAnimator()} method.</p>
+<p>
+ To attach custom view state animations to a view, define an animator using
+ the <code>selector</code> element in an XML resource file as in this example,
+ and assign it to your view with the <code>android:stateListAnimator</code>
+ attribute. To assign a state list animator to a view in your code, use the
+ {@link android.animation.AnimatorInflater#loadStateListAnimator
+ AnimatorInflater.loadStateListAnimator()} method, and assign the animator to
+ your view with the {@link android.view.View#setStateListAnimator
+ View.setStateListAnimator()} method.
+</p>
<p>When your theme extends the material theme, buttons have a Z animation by default. To avoid this
behavior in your buttons, set the <code>android:stateListAnimator</code> attribute to
diff --git a/docs/html/training/testing/start/index.jd b/docs/html/training/testing/start/index.jd
index 707ba9d8f65a..aa0473f6d09f 100644
--- a/docs/html/training/testing/start/index.jd
+++ b/docs/html/training/testing/start/index.jd
@@ -9,51 +9,20 @@ page.image=images/tools/studio-main-screen.png
<div id="tb">
<h2>
- Dependencies and prerequisites
- </h2>
-
- <ul>
- <li>
- <a href="{@docRoot}tools/studio/index.html">Android Studio 2.0</a>, or
- later.
- </li>
-
- <li>The Android Support Repository (available from the <a href=
- "{@docRoot}tools/help/sdk-manager.html">SDK Manager</a>)
- </li>
- </ul>
-
- <h2>
- This lesson teaches you to
+ In this document
</h2>
<ol>
- <li>
- <a href="#config-local-tests">Configure Your Project for Local Unit
- Tests</a>
- </li>
-
- <li>
- <a href="#config-instrumented-tests">Configure Your Project for
- Instrumented Tests</a>
- </li>
-
- <li>
- <a href="#build">Build and Run Your Tests</a>
+ <li><a href="#test-types">Test Types</a></li>
+ <li><a href="#test-apis">Test APIs</a>
<ol>
- <li>
- <a href="#run-local-tests">Run Local Unit Tests</a>
- </li>
-
- <li>
- <a href="#run-instrumented-tests">Run Instrumented Tests</a>
- </li>
-
- <li>
- <a href="#run-ctl">Run Instrumented Tests with Cloud Test Lab</a>
- </li>
+ <li><a href="#junit">JUnit</a></li>
+ <li><a href="#support-library">Android Testing Support Library</a></li>
+ <li><a href="#assertion">Assertion classes</a></li>
+ <li><a href="#monkeyrunner">Monkey and monkeyrunner</a></li>
</ol>
</li>
+ <li><a href="#build">Guides for Building Android Tests</a>
</ol>
<h2>
@@ -61,10 +30,6 @@ page.image=images/tools/studio-main-screen.png
</h2>
<ul>
- <li>
- <a href="{@docRoot}tools/testing/testing_android.html">Testing
- Concepts</a>
- </li>
<li>
<a href="https://github.com/googlesamples/android-testing" class=
@@ -80,484 +45,356 @@ page.image=images/tools/studio-main-screen.png
</div>
<p>
- Writing and running tests are important parts of the Android app development
- cycle. Well-written tests can help you catch bugs early in development and
- give you confidence in your code. Using Android Studio, you can run local
- unit tests or instrumented tests on a variety of physical or virtual Android
- devices. You can then analyze the results and make changes to your code
- without leaving the development environment.
+ Android tests are based on <a href="http://junit.org/" class=
+ "external-link">JUnit</a>, and you can run them either as local
+ unit tests on the JVM or as instrumented tests on an Android device.
+ This page provides an introduction to the concepts and
+ tools for building Android tests.
</p>
-<p>
- <em>Local unit tests</em> are tests that run on your local machine, without
- needing access to the Android framework or an Android device. To learn how to
- develop local units tests, see <a href=
- "{@docRoot}training/testing/unit-testing/local-unit-tests.html">Building
- Local Unit Tests</a>.
-</p>
-<p>
- <em>Instrumented tests</em> are tests that run on an Android device or
- emulator. These tests have access to {@link android.app.Instrumentation}
- information, such as the {@link android.content.Context} for the app under
- test. Instrumented tests can be used for unit, user interface (UI), or app
- component integration testing. To learn how to develop instrumented tests for
- your specific needs, see these additional topics:
-</p>
+<h2 id="test-types">Test Types</h2>
+
+
+<p>When using Android Studio to write any of your tests, your test code must go
+into one of two different code directories (source sets). For each module in
+your project, Android Studio includes both source sets, corresponding to the
+following test types:</p>
+
+<dl>
+<dt><b>Local unit tests</b></dt>
+<dd>Located at <code><var>module-name</var>/src/test/java/</code>.
+<p>These tests run on the local JVM
+and do not have access to functional Android framework APIs.</p>
+<p>To get started, see <a
+href="/training/testing/unit-testing/local-unit-tests.html">Building Local
+Unit Tests</a>.</p>
+</dd>
+
+<dt><b>Instrumented tests</b></dt>
+<dd>Located at <code><var>module-name</var>/src/androidTest/java/</code>.
+<p>These are all tests that must run on an Android hardware device or
+an Android emulator.</p>
+
+<p>Instrumented tests are built into an APK that runs on the device alongside
+your app under test. The system runs your test APK and your app under tests in
+the same process, so your tests can invoke methods and modify fields in the
+app, and automate user interaction with your app.</p>
+
+<p>For information about how to create instrumented tests, see the
+following topics:</p>
<ul>
<li>
<a href=
- "{@docRoot}training/testing/unit-testing/instrumented-unit-tests.html">Building
- Instrumented Unit Tests</a> - Build more complex unit tests that have
- Android dependencies which cannot be easily filled by using mock objects.
+ "{@docRoot}training/testing/unit-testing/instrumented-unit-tests.html"
+ >Building Instrumented Unit Tests</a>: Build complex unit tests with
+ Android dependencies that cannot be satisfied with mock objects.
</li>
<li>
<a href="{@docRoot}training/testing/ui-testing/index.html">Automating User
- Interface Tests</a> - Create tests to verify that the user interface
+ Interface Tests</a>: Create tests to verify that the user interface
behaves correctly for user interactions within a single app or for
interactions across multiple apps.
</li>
<li>
<a href="{@docRoot}training/testing/integration-testing/index.html">Testing
- App Component Integrations</a> - Verify the behavior of components that
+ App Component Integrations</a>: Verify the behavior of components that
users do not directly interact with, such as a <a href=
"{@docRoot}guide/components/services.html">Service</a> or a <a href=
- "guide/topics/providers/content-providers.html">Content Provider</a>.
+ "{@docRoot}guide/topics/providers/content-providers.html">Content Provider</a>.
</li>
</ul>
-<p>
- This lesson teaches you how to build and run your tests using using Android
- Studio. If you are not using Android Studio, you can learn how to
- <a href="{@docRoot}tools/testing/testing_otheride.html">run your tests from
- the command-line</a>.
-</p>
-
-<h3 id="config-local-tests">
- Configure Your Project for Local Unit Tests
-</h3>
+</dd>
+</dl>
-<p>
- In your Android Studio project, you must store the source files for local
- unit tests under a specific source directory ({@code src/test/java}). This
- improves project organization by grouping your unit tests together into a
- single source set.
-</p>
+<img src="/images/testing/test-types_2x.png" alt="" width="798" />
-<p>
- As with production code, you can create local unit tests for a <a href=
- "{@docRoot}tools/building/configuring-gradle.html#workBuildVariants">specific
- flavor or build type</a>. Keep your unit tests in a test source tree location
- that corresponds to your production source tree, such as:
-</p>
+<p>However, the <em>local unit tests</em> and <em>instrumented tests</em>
+described above are just terms that help distinguish the tests that run on your
+local JVM from the tests that run on the Android platform (on a hardware device
+or emulator). The real testing types that you should understand when building a
+complete test suite are described in the following table.</p>
<table>
-<tr>
-<th>Path to Production Class</th>
-<th>Path to Local Unit Test Class</th>
-</tr>
-<tr>
-<td>{@code src/main/java/Foo.java}</td>
-<td>{@code src/test/java/FooTest.java}</td>
-</tr>
-<tr>
-<td>{@code src/debug/java/Foo.java}</td>
-<td>{@code src/testDebug/java/FooTest.java}</td>
-</tr>
-<tr>
-<td>{@code src/myFlavor/java/Foo.java}</td>
-<td>{@code src/testMyFlavor/java/FooTest.java}</td>
-</tr>
+ <tr>
+ <th>
+ Type
+ </th>
+ <th>
+ Subtype
+ </th>
+ <th>
+ Description
+ </th>
+ </tr>
+
+ <tr>
+ <td rowspan="3">
+ Unit tests
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ Local Unit Tests
+ </td>
+ <td>
+ Unit tests that run locally on the Java Virtual Machine (JVM). Use these
+tests to minimize execution time when your tests have no Android framework
+dependencies or when you can mock the Android framework dependencies.
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ Instrumented unit tests
+ </td>
+ <td>
+ Unit tests that run on an Android device or emulator. These tests have
+access to <code><a href=
+"/reference/android/app/Instrumentation.html">Instrumentation</a></code>
+information, such as the <code><a href=
+"/reference/android/content/Context.html">Context</a></code> of the app you are
+testing. Use these tests when your tests have Android dependencies that mock
+objects cannot satisfy.
+ </td>
+ </tr>
+
+ <tr>
+ <td style="white-space:nowrap" rowspan="3">
+ Integration Tests
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ Components within your app only
+ </td>
+ <td>
+ This type of test verifies that the target app behaves as expected when
+a user performs a specific action or enters a specific input in its activities.
+For example, it allows you to check that the target app returns the correct UI
+output in response to user interactions in the app’s activities. UI testing
+frameworks like <a href=
+ "/tools/testing-support-library/index.html#Espresso">Espresso</a> allow
+you to programmatically simulate user actions and test complex intra-app user
+interactions.
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ Cross-app Components
+ </td>
+ <td>
+ This type of test verifies the correct behavior of interactions between
+different user apps or between user apps and system apps. For example, you might
+want to test that your app behaves correctly when the user performs an action
+in the Android Settings menu. UI testing frameworks that support cross-app
+interactions, such as <a
+href="/topic/libraries/testing-support-library/index.html#UIAutomator"
+>UI Automator</a>, allow you to create tests for such scenarios.
+ </td>
+ </tr>
</table>
-<p>
- You'll need to configure the testing dependencies for your project to use the
- standard APIs provided by the JUnit 4 framework. If your test needs to
- interact with Android dependencies, include the <a href=
- "https://github.com/mockito/mockito" class="external-link">Mockito</a>
- library to simplify your local unit tests. To learn more about using mock
- objects in your local unit tests, see <a href=
- "{@docRoot}training/testing/unit-testing/local-unit-tests.html#mocking-dependencies">
- Mocking Android dependencies</a>.
-</p>
-
-<p>
- In your app's top-level {@code build.gradle} file, you need to specify these
- libraries as dependencies:
-</p>
-
-<pre>
-dependencies {
- // Required -- JUnit 4 framework
- testCompile 'junit:junit:4.12'
- // Optional -- Mockito framework
- testCompile 'org.mockito:mockito-core:1.10.19'
-}
-</pre>
-<h3 id="config-instrumented-tests">
- Configure Your Project for Instrumented Tests
-</h3>
-
-<p>
- In your Android Studio project, you must place the source code for your
- instrumentated tests under a specific directory
- (<code>src/androidTest/java</code>).
-</p>
-
-<p>
- <a href="{@docRoot}tools/testing-support-library/index.html#setup">Download
- the Android Testing Support Library Setup</a>, which provides APIs that allow
- you to quickly build and run instrumented test code for your apps. The
- Testing Support Library includes a JUnit 4 test runner (<a href=
- "{@docRoot}tools/testing-support-library/index.html#AndroidJUnitRunner">AndroidJUnitRunner</a>
- ) and APIs for functional UI tests (<a href=
- "{@docRoot}tools/testing-support-library/index.html#Espresso">Espresso</a>
- and <a href=
- "{@docRoot}tools/testing-support-library/index.html#UIAutomator">UI
- Automator</a>).
-</p>
-
-<p>
- You'll need to configure the Android testing dependencies for your project to
- use the test runner and the rules APIs provided by the Testing Support
- Library. To simplify your test development, we also recommend that you
- include the <a href="https://github.com/hamcrest" class=
- "external-link">Hamcrest</a> library, which lets you create more flexible
- assertions using the Hamcrest matcher APIs.
-</p>
-<p>
- In your app's top-level {@code build.gradle} file, you need to specify these
- libraries as dependencies:
-</p>
-<pre>
-dependencies {
- androidTestCompile 'com.android.support:support-annotations:23.0.1'
- androidTestCompile 'com.android.support.test:runner:0.4.1'
- androidTestCompile 'com.android.support.test:rules:0.4.1'
- // Optional -- Hamcrest library
- androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
- // Optional -- UI testing with Espresso
- androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
- // Optional -- UI testing with UI Automator
- androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.1'
-}
-</pre>
-<p>
- To use JUnit 4 test classes, make sure to specify <a href=
- "{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code
- AndroidJUnitRunner}</a> as the default test instrumentation runner in your
- project by including the following setting in your app's module-level {@code build.gradle}
- file:
-</p>
+<h2 id="test-apis">Test APIs</h2>
-<pre>
-android {
- defaultConfig {
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
- }
-}
-</pre>
+<p>The following are common APIs used for testing apps on Android.</p>
-<h3 id="testartifacts">Work With Test Artifacts</h3>
-<p>Android Studio has two types of test artifacts: Android Instrumentation Tests
-and Unit Tests. Previously, you could work with just one test artifact at a
-time. Now, both test artifacts are enabled.
-The advantage of enabling both test artifacts is that any changes you make to
-the underlying code affect
-them both. For example, if you rename a class that both test artifacts access,
-both will know about the class name refactoring.</p>
-
-<p>The figure shows what your project looks like with both test
-artifacts enabled. Notice the shading of both test artifacts.</p>
-
-<!-- Commenting out for now, but leaving it in case we need to add it back.
-<img src="{@docRoot}images/training/testartifactseparate.png" style="float:left;width:250px;margin-right:20px" /> -->
-<img src="{@docRoot}images/training/testartifactcombined.png" style="float:left;width:250px" />
-<!-- Commenting out for now, but leaving it in case we need to add it back.
-<p>
-By default, both test artifacts are enabled in Android Studio. To enable just
-one, deselect <strong>Enable all test artifacts</strong> in your preferences:
-</p>
-<ol>
-<li>Select
-<strong>Android Studio</strong> > <strong>Preferences</strong> > <strong>Build,
-Execution, Deployment</strong> > <strong>Build Tools</strong> >
-<strong>Gradle</strong> > <strong>Experimental</strong>.</li>
-<li>Deselect the test artifacts option.</li>
-<li>Click <strong>OK</strong>.</li>
-</ol>
--->
+<h3 id="junit">JUnit</h3>
-<h2 id="build">Build and Run Your Tests</h2>
+<p>You should write your unit or integration test class as a <a href=
+"http://junit.org/" class="external-link">JUnit 4</a> test class. The framework
+offers a convenient way to perform common setup, teardown, and assertion
+operations in your test.</p>
+<p>A basic JUnit 4 test class is a Java class that contains one or more test
+methods. A test method begins with the <code>@Test</code> annotation and
+contains the code to exercise and verify a single functionality (that is, a
+logical unit) in the component that you want to test.</p>
-<p>
- Android Studio provides all the tools you need to build, run, and analyze
- your tests within the development environment. You can also run instrumented
- tests on multiple device configurations, simultaneously, using <a href=
- "https://developers.google.com/cloud-test-lab/">Cloud Test Lab</a>
- integration.
-</p>
+<p>The following snippet shows an example JUnit 4 integration test that uses the
+<a href="/topic/libraries/testing-support-library/index.html#Espresso">Espresso
+APIs</a> to perform a click action on a UI element, then checks to see if
+an expected string is displayed.</p>
-<p class="note">
- <strong>Note:</strong> While running or debugging instrumented tests,
- Android Studio does not inject the additional methods required for <a href=
- "{@docRoot}tools/building/building-studio.html#instant-run">Instant Run</a>
- and turns the feature off.
-</p>
-
-<h3 id="run-local-tests">
- Run Local Unit Tests
-</h3>
-
-<p>
- To run your local unit tests:
-</p>
-
-<ol>
-
- <li>In the <em>Project</em> window, right click on the project and
- synchronize your project.
- </li>
-
- <!--
-<li>If you enabled one test artifact only, open the
-<strong>Build Variants</strong> window by clicking the left-hand tab, then
-change the test artifact to <em>Unit Tests</em>.
-</li>
--->
-
- <li>In the <em>Project</em> window, navigate to your unit test class or
- method, then right-click it and select <strong>Run</strong> <img src=
- "{@docRoot}images/tools/as-run.png" alt="" style=
- "vertical-align:bottom;margin:0;">.
- <ul>
- <li>To run all tests in the unit test directory, right-click on the
- directory and select <strong>Run tests</strong> <img src=
- "{@docRoot}images/tools/as-run.png" alt="" style=
- "vertical-align:bottom;margin:0;">.
- </li>
- </ul>
- </li>
+<pre>
+&#64;RunWith(AndroidJUnit4.class)
+&#64;LargeTest
+public class MainActivityInstrumentationTest {
-</ol>
+ &#64;Rule
+ public ActivityTestRule mActivityRule = new ActivityTestRule<>(
+ MainActivity.class);
-<p>
- The Android Plugin for Gradle compiles the local unit test code located in
- the default directory ({@code src/test/java}), builds a test app, and
- executes it locally using the default test runner class. Android Studio then
- displays the results in the <em>Run</em> window.
-</p>
+ &#64;Test
+ public void sayHello(){
+ onView(withText("Say hello!")).perform(click());
-<h3 id="run-instrumented-tests">
- Run Instrumented Tests
-</h3>
+ onView(withId(R.id.textView)).check(matches(withText("Hello, World!")));
+ }
+}
+</pre>
-<p>
- To run your instrumented tests:
-</p>
+<p>In your JUnit 4 test class, you can call out sections in your test code for
+special processing by using the following annotations:</p>
<ul>
- <!--
-<li>If you enabled one test artifact only, open the
-<strong>Build Variants</strong> window by clicking the left-hand tab, then set
-the test artifact to <em>Android Instrumentation Tests</em>.
-</li>
--->
-
- <li>In the <em>Project</em> window, navigate to your instrumented test class
- or method, then right-click and run it using the Android Test configuration.
- To run all tests in the instrumented test directory, right-click the
- directory and select <strong>Run tests</strong> <img src=
- "{@docRoot}images/tools/as-run.png" alt="" style=
- "vertical-align:bottom;margin:0;">.
- </li>
+<li><code>@Before</code>: Use this annotation to specify a block of code that
+contains test setup operations. The test class invokes this code block before
+each test. You can have multiple <code>@Before</code> methods but the order in
+which the test class calls these methods is not guaranteed.</li>
+
+<li><code>@After</code>: This annotation specifies a block of code that
+contains test tear-down operations. The test class calls this code block after
+every test method. You can define multiple <code>@After</code> operations in
+your test code. Use this annotation to release any resources from memory.</li>
+
+<li><code>@Test</code>: Use this annotation to mark a test method. A single
+test class can contain multiple test methods, each prefixed with this
+annotation.</li>
+
+<li><code>@Rule</code>: Rules allow you to flexibly add or redefine the
+behavior of each test method in a reusable way. In Android testing, use this
+annotation together with one of the test rule classes that the Android Testing
+Support Library provides, such as <a href=
+"/reference/android/support/test/rule/ActivityTestRule.html"><code>ActivityTestRule</code></a>
+or <a href=
+"/reference/android/support/test/rule/ServiceTestRule.html"><code>ServiceTestRule</code></a>.</li>
+
+<li><code>@BeforeClass</code>: Use this annotation to specify static methods
+for each test class to invoke only once. This testing step is useful for
+expensive operations such as connecting to a database.</li>
+
+<li><code>@AfterClass</code>: Use this annotation to specify static methods for
+the test class to invoke only after all tests in the class have run. This
+testing step is useful for releasing any resources allocated in the
+<code>@BeforeClass</code> block.</li>
+
+<li><code>@Test(timeout=)</code>: Some annotations support the ability to pass
+in elements for which you can set values. For example, you can specify a
+timeout period for the test. If the test starts but does not complete within
+the given timeout period, it automatically fails. You must specify the timeout
+period in milliseconds, for example: <code>@Test(timeout=5000)</code>.</li>
</ul>
-<p>
- The <a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plugin
- for Gradle</a> compiles the instrumented test code located in the default
- directory ({@code src/androidTest/java}), builds a test APK and production
- APK, installs both APKs on the connected device or emulator, and runs the
- tests. Android Studio then displays the results of the instrumented test execution in the
- <em>Run</em> window.
-</p>
-
-<h3 id="run-ctl">Run Instrumented Tests with Cloud Test Lab</h3>
-
-<p>
- Using <a href="https://developers.google.com/cloud-test-lab/">Cloud Test
- Lab</a>, you can simultaneously test your app on many popular Android
- devices, across multiple languages, screen orientations, and versions of the
- Android platform. These tests run on actual physical devices in remote Google
- data centers. You can also <a href=
- "https://developers.google.com/cloud-test-lab/test-screenshots">configure
- your instrumented tests to take screenshots</a> while Cloud Test Lab runs its
- tests. You can <a href=
- "https://developers.google.com/cloud-test-lab/command-line">deploy tests to
- Cloud Test Lab from the command line</a>, or from Android Studio's integrated
- testing tools.
-</p>
-
-<p>
- Android Studio allows you to connect to your Google Cloud Platform account,
- configure your tests, deploy them to Cloud Test Lab, and analyze the results
- all within the development environment. Cloud Test Lab in Android Studio
- supports the following Android test frameworks: <a href=
- "{@docRoot}training/testing/ui-testing/espresso-testing.html">Espresso</a>,
- <a href="{@docRoot}tools/testing-support-library/index.html#UIAutomator">UI
- Automator 2.0</a>, or <a class="external-link" href=
- "https://github.com/robotiumtech/robotium">Robotium</a>. Test results provide
- test logs and include the details of any app failures.
-</p>
-
-<p>
- Before you can start using Cloud Test Lab, you need to:
-</p>
-
-<ol>
- <li>
- <a href="https://console.developers.google.com/freetrial">Create a
- Google Cloud Platform account</a> to use with active billing.
- </li>
+<p>For more annotations, see the documentation for <a
+href="http://junit.sourceforge.net/javadoc/org/junit/package-summary.html"
+class="external-link">JUnit annotations</a> and the <a
+href="/reference/android/support/annotation/package-summary.html">Android
+annotations</a>.</p>
- <li>
- <a href="https://support.google.com/cloud/answer/6251787">Create a Google
- Cloud project</a> for your app.
- </li>
+<p>Use the JUnit <code><a href=
+"/reference/junit/framework/Assert.html">Assert</a></code> class to verify the
+correctness of an object's state. The assert methods compare values you expect
+from a test to the actual results and throw an exception if the comparison
+fails. <a href="#AssertionClasses">Assertion classes</a> describes these
+methods in more detail.</p>
- <li>
- <a href="https://support.google.com/cloud/answer/6288653">Set up an active
- billing account</a> and associate it with the project you just created.
- </li>
-</ol>
+<h3 id="support-library">Android Testing Support Library</h3>
-<h4 id="configure-matrix">
-Configure a test matrix and run a test
-</h4>
+<p>The <a href="/topic/libraries/testing-support-library/index.html">Android
+Testing Support Library</a> provides a set of APIs that allow you
+to quickly build and run test code for your apps, including JUnit 4 and
+functional UI tests. The library includes the following instrumentation-based
+APIs that are useful when you want to automate your tests:</p>
-<p>
- Android Studio provides integrated tools that allow you to configure how you
- want to deploy your tests to Cloud Test Lab. After you have created a Google
- Cloud project with active billing, you can create a test configuration and
- run your tests:
-</p>
+<dt><a href="/topic/libraries/testing-support-library/index.html#AndroidJUnitRunner"
+>AndroidJUnitRunner</a></dt>
+<dd>A JUnit 4-compatible test runner for Android.</dd>
-<ol>
- <li>Click <strong>Run</strong> &gt; <strong>Edit Configurations</strong> from
- the main menu.
- </li>
+<dt><a href="/topic/libraries/testing-support-library/index.html#Espresso"
+>Espresso</a></dt>
+<dd>A UI testing framework; suitable for functional UI testing within an
+app.</dd>
- <li>Click <strong>Add New Configuration (+)</strong> and select
- <strong>Android Tests</strong>.
- </li>
-
- <li>In the Android Test configuration dialog:
- <ol type="a">
- <li>Enter or select the details of your test, such as the test name, module
- type, test type, and test class.
- </li>
-
- <li>From the <em>Target</em> drop-down menu under <em>Deployment Target
- Options</em>, select <strong>Cloud Test Lab Device Matrix</strong>.
- </li>
-
- <li>If you are not logged in, click <strong>Connect to Google Cloud
- Platform</strong> and allow Android Studio access to your account.
- </li>
+<dt><a href="/topic/libraries/testing-support-library/index.html#UIAutomator"
+>UI Automator</a></dt>
+<dd>A UI testing framework suitable for cross-app functional UI testing between
+both system and installed apps.</dd>
- <li>Next to <em>Cloud Project</em>, click the <img src=
- "{@docRoot}images/tools/as-wrench.png" alt="wrench and nut" style=
- "vertical-align:bottom;margin:0;"> button and select your Google Cloud
- Platform project from the list.
- </li>
- </ol>
- </li>
- <li>Create and configure a test matrix:
- <ol type="a">
- <li>Next to the <em>Matrix Configuration</em> drop-down list, click <strong>
- Open Dialog</strong> <img src="{@docRoot}images/tools/as-launchavdm.png"
- alt="ellipses button" style="vertical-align:bottom;margin:0;">.
- </li>
+<h3 id="assertion">Assertion classes</h3>
- <li>Click <strong>Add New Configuration (+)</strong>.
- </li>
+<p>Because Android Testing Support Library APIs extend JUnit, you can use
+assertion methods to display the results of tests. An assertion method compares
+an actual value returned by a test to an expected value, and throws an
+AssertionException if the comparison test fails. Using assertions is more
+convenient than logging, and provides better test performance.</p>
- <li>In the <strong>Name</strong> field, enter a name for your new
- configuration.
- </li>
+<p>To simplify test development, you should use the <a href=
+"https://github.com/hamcrest" class="external-link">Hamcrest library</a>, which
+lets you create more flexible tests using the Hamcrest matcher APIs.</p>
- <li>Select the device(s), Android version(s), locale(s) and screen
- orientation(s) that you want to test your app with. Cloud Test Lab will test
- your app against every combination of your selections when generating test
- results.
- </li>
- <li>Click <strong>OK</strong> to save your configuration.
- </li>
- </ol>
- </li>
- <li>Click <strong>OK</strong> in the <em>Run/Debug Configurations</em> dialog
- to exit.
- </li>
+<h3 id="monkeyrunner">Monkey and monkeyrunner</h3>
- <li>Run your tests by clicking <strong>Run</strong> <img src=
- "{@docRoot}images/tools/as-run.png" alt="" style=
- "vertical-align:bottom;margin:0;">.
- </li>
-</ol>
+<p>The Android SDK includes two tools for functional-level app testing:</p>
-<img src="{@docRoot}images/training/ctl-config.png" alt="">
-<p class="img-caption">
- <strong>Figure 1.</strong> Creating a test configuration for Cloud Test
- Lab.
-</p>
+<dl>
+<dt>Monkey</dt>
+<dd>This is a command-line tool that sends pseudo-random streams of keystrokes,
+touches, and gestures to a device. You run it with the <a href=
+"/studio/command-line/adb.html">Android Debug Bridge (adb)</a> tool, and use it
+to stress-test your app, report back errors any that are encountered, or repeat
+a stream of events by running the tool multiple times with the same random
+number seed.</dd>
-<h4 id="ctl-results">
- Analyzing test results
-</h4>
-<p>
- When Cloud Test Lab completes running your tests, the <em>Run</em> window will
- open to show the results, as shown in figure 2. You may need to click
- <strong>Show Passed</strong> <img src="{@docRoot}images/tools/as-ok.png" alt=
- "" style="vertical-align:bottom;margin:0;"> to see all your executed tests.
-</p>
+<dt>monkeyrunner</dt>
+<dd>This tool is an API and execution environment for test programs written in
+Python. The API includes functions for connecting to a device, installing and
+uninstalling packages, taking screenshots, comparing two images, and running a
+test package against an app. Using the API, you can write a wide range of
+large, powerful, and complex tests. You run programs that use the API with the
+<code>monkeyrunner</code> command-line tool.</dd>
+</dl>
-<img src="{@docRoot}images/training/ctl-test-results.png" alt="">
-<p class="img-caption">
- <strong>Figure 2.</strong> Viewing the results of instrumented tests using
- Cloud Test Lab.
-</p>
-<p>
- You can also analyze your tests on the web by following the link displayed at
- the beginning of the test execution log in the <em>Run</em> window, as shown
- in figure 3.
-</p>
-<img src="{@docRoot}images/training/ctl-exec-log.png" alt="">
+<h2 id="build">Guides for Building Android Tests</h2>
-<p class="img-caption">
- <strong>Figure 3.</strong> Click the link to view detailed test results on
- the web.
+<p>The following documents provide more detail about how to build and run
+a variety of test types:
</p>
-<p>
- To learn more about interpreting web results, see <a href=
- "https://developers.google.com/cloud-test-lab/analyzing-results">Analyzing
- Cloud Test Lab Web Results</a>.
-</p> \ No newline at end of file
+<dl>
+ <dt><a href="/training/testing/unit-testing/local-unit-tests.html"
+ >Building Local Unit Tests</a></dt>
+ <dd>Build unit tests that have no dependencies or only simple dependencies
+ that you can mock, which run on your local JVM.</dd>
+ <dt><a href=
+ "/training/testing/unit-testing/instrumented-unit-tests.html"
+ >Building Instrumented Unit Tests</a></dt>
+ <dd>Build complex unit tests with
+ Android dependencies that cannot be satisfied with mock objects,
+ which run on a hardware device or emulator.</dd>
+ <dt><a href="/training/testing/ui-testing/index.html">Automating User
+ Interface Tests</a></dt>
+ <dd>Create tests to verify that the user interface
+ behaves correctly for user interactions within a single app or for
+ interactions across multiple apps.</dd>
+ <dt><a href="/training/testing/integration-testing/index.html">Testing App
+ Compontent Integrations</a></dt>
+ <dd>Verify the behavior of components that
+ users do not directly interact with, such as a service or a content
+ provider.</dd>
+ <dt><a href="/training/testing/performance.html">Testing Display
+ Performance</a></dt>
+ <dd>Write tests that measure your app's UI performance to ensure
+ a consistently smooth user experience.</dd>
+</dl> \ No newline at end of file
diff --git a/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd b/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd
index 38321eed93b3..f65766d825a9 100644
--- a/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd
+++ b/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd
@@ -7,21 +7,20 @@ trainingnavtop=true
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
- <h2>Dependencies and Prerequisites</h2>
-
- <ul>
- <li>Android 2.2 (API level 8) or higher</li>
- <li><a href="{@docRoot}tools/testing-support-library/index.html">
- Android Testing Support Library</a></li>
- <li><a href="{@docRoot}tools/studio/index.html">Android Studio (latest version)</a>.</li>
- </ul>
-
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#setup">Set Up Your Testing Environment</a></li>
- <li><a href="#build">Create a Instrumented Unit Test Class</a></li>
- <li><a href="#run">Run Instrumented Unit Tests</a></li>
+ <li><a href="#build">Create a Instrumented Unit Test Class</a>
+ <ol>
+ <li><a href="#test-suites">Create a test suite</a></li>
+ </ol>
+ </li>
+ <li><a href="#run">Run Instrumented Unit Tests</a>
+ <ol>
+ <li><a href="#run-ctl">Run your tests with Firebase Test Lab</a></li>
+ </ol>
+ </li>
</ol>
<h2>Try it out</h2>
@@ -36,25 +35,88 @@ class="external-link">Unit and UI Testing in Android Studio (codelab)</a></li>
</div>
</div>
+<p>Instrumented unit tests are tests that run on physical devices and
+emulators, and they can take advantage of the Android framework APIs and
+supporting APIs, such as the Android Testing Support Library. You should create
+instrumented unit tests if your tests need access to instrumentation
+information (such as the target app's {@link android.content.Context}) or if
+they require the real implementation of an Android framework component (such as
+a {@link android.os.Parcelable} or {@link android.content.SharedPreferences}
+object).</p>
+
+<p>Using instrumented unit tests also helps to reduce the effort required to
+write and maintain mock code. You are still free to use a mocking framework, if
+you choose, to simulate any dependency relationships.</p>
+
+
+<h2 id="setup">Set Up Your Testing Environment</h2>
+
+<p>In your Android Studio project, you must store the source files for
+instrumented tests at
+<code><var>module-name</var>/src/androidTests/java/</code>. This directory
+already exists when you create a new project.</p>
+
+<p>Before you begin, you should
+ <a href="{@docRoot}tools/testing-support-library/index.html#setup">download
+ the Android Testing Support Library Setup</a>, which provides APIs that allow
+ you to quickly build and run instrumented test code for your apps. The
+ Testing Support Library includes a JUnit 4 test runner (<a href=
+ "{@docRoot}tools/testing-support-library/index.html#AndroidJUnitRunner">AndroidJUnitRunner</a>
+ ) and APIs for functional UI tests (<a href=
+ "{@docRoot}tools/testing-support-library/index.html#Espresso">Espresso</a>
+ and <a href=
+ "{@docRoot}tools/testing-support-library/index.html#UIAutomator">UI
+ Automator</a>).
+</p>
+
+<p>You also need to configure the Android testing dependencies for your project
+to use the test runner and the rules APIs provided by the Testing Support
+Library. To simplify your test development, you should also include the
+<a href="https://github.com/hamcrest" class="external-link">Hamcrest</a>
+library, which lets you create more flexible assertions using the Hamcrest
+matcher APIs.</p>
+
<p>
-Instrumented unit tests are unit tests that run on physical devices and emulators, instead of
-the Java Virtual Machine (JVM) on your local machine. You should create instrumented unit tests
-if your tests need access to instrumentation information (such as the target app's
-{@link android.content.Context}) or if they require the real implementation of an Android framework
-component (such as a {@link android.os.Parcelable} or {@link android.content.SharedPreferences}
-object). Using instrumented unit tests also helps to reduce the effort required to write and
-maintain mock code. You are still free to use a mocking framework, if you choose, to simulate any
-dependency relationships. Instrumented unit tests can take advantage of the Android framework APIs
-and supporting APIs, such as the Android Testing Support Library.
+ In your app's top-level {@code build.gradle} file, you need to specify these
+ libraries as dependencies:
</p>
-<h2 id="setup">Set Up Your Testing Environment</h2>
-<p>Before building your instrumented unit test, make sure to configure your test source code
-location and project dependencies, as described in
-<a href="{@docRoot}training/testing/start/index.html#config-instrumented-tests">
-Getting Started with Testing</a>.</p>
+<pre>
+dependencies {
+ androidTestCompile 'com.android.support:support-annotations:24.0.0'
+ androidTestCompile 'com.android.support.test:runner:0.5'
+ androidTestCompile 'com.android.support.test:rules:0.5'
+ // Optional -- Hamcrest library
+ androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
+ // Optional -- UI testing with Espresso
+ androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
+ // Optional -- UI testing with UI Automator
+ androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
+}
+</pre>
+
+
+<p>
+ To use JUnit 4 test classes, make sure to specify <a href=
+ "{@docRoot}reference/android/support/test/runner/AndroidJUnitRunner.html">{@code
+ AndroidJUnitRunner}</a> as the default test instrumentation runner in your
+ project by including the following setting in your app's module-level {@code build.gradle}
+ file:
+</p>
+
+<pre>
+android {
+ defaultConfig {
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+}
+</pre>
+
+
+
<h2 id="build">Create an Instrumented Unit Test Class</h2>
+
<p>
Your instrumented unit test class should be written as a JUnit 4 test class. To learn more about
creating JUnit 4 test classes and using JUnit 4 assertions and annotations, see
@@ -119,7 +181,7 @@ public class LogHistoryAndroidUnitTest {
}
</pre>
-<h3 id="test-suites">Creating a test suite</h3>
+<h3 id="test-suites">Create a test suite</h3>
<p>
To organize the execution of your instrumented unit tests, you can group a collection of test
classes in a <em>test suite</em> class and run these tests together. Test suites can be nested;
@@ -162,9 +224,198 @@ import org.junit.runners.Suite;
public class UnitTestSuite {}
</pre>
+
<h2 id="run">Run Instrumented Unit Tests</h2>
+
+<p>To run your instrumented tests, follow these steps:</p>
+
+<ol>
+ <li>Be sure your project is synchronized with Gradle by clicking
+ <b>Sync Project</b> <img src="/images/tools/sync-project.png" alt=""
+ class="inline-icon"> in the toolbar.</li>
+
+ <li>Run your test in one of the following ways:
+ <ul>
+ <li>To run a single test, open the <b>Project</b> window, and then
+ right-click a test and click <strong>Run</strong> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.</li>
+ <li>To test all methods in a class, right-click a class or method in the
+test file and click <b>Run</b> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.
+ <li>To run all tests in a directory, right-click on the
+ directory and select <strong>Run tests</strong> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.
+ </li>
+ </ul>
+ </li>
+
+</ol>
+
+<p>
+ The <a href="{@docRoot}tools/building/plugin-for-gradle.html">Android Plugin
+ for Gradle</a> compiles the instrumented test code located in the default
+ directory ({@code src/androidTest/java/}), builds a test APK and production
+ APK, installs both APKs on the connected device or emulator, and runs the
+ tests. Android Studio then displays the results of the instrumented test execution in the
+ <em>Run</em> window.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> While running or debugging instrumented tests,
+ Android Studio does not inject the additional methods required for <a href=
+ "{@docRoot}tools/building/building-studio.html#instant-run">Instant Run</a>
+ and turns the feature off.
+</p>
+
+
+<h3 id="run-ctl">Run your tests with Firebase Test Lab</h3>
+
+<p>Using <a href="https://firebase.google.com/docs/test-lab/">Firebase Test
+Lab</a>, you can simultaneously test your app on many popular Android devices
+and configurations such as locale, orientation, screen size, and platform
+version. These tests run on actual physical devices in remote Google data
+centers. You can deploy to Firebase Test Lab directly from Android Studio or
+from the command line. Test results provide test logs and include the details
+of any app failures.</p>
+
+<p>
+ Before you can start using Firebase Test Lab, you need to:
+</p>
+
+<ol>
+ <li>
+ <a href="https://console.developers.google.com/freetrial">Create a
+ Google Cloud Platform account</a> to use with active billing.
+ </li>
+
+ <li>
+ <a href="https://support.google.com/cloud/answer/6251787">Create a Google
+ Cloud project</a> for your app.
+ </li>
+
+ <li>
+ <a href="https://support.google.com/cloud/answer/6288653">Set up an active
+ billing account</a> and associate it with the project you just created.
+ </li>
+</ol>
+
+
+<h4 id="configure-matrix">
+Configure a test matrix and run a test
+</h4>
+
+<p>
+ Android Studio provides integrated tools that allow you to configure how you
+ want to deploy your tests to Firebase Test Lab. After you have created a Google
+ Cloud project with active billing, you can create a test configuration and
+ run your tests:
+</p>
+
+<ol>
+ <li>Click <strong>Run</strong> &gt; <strong>Edit Configurations</strong> from
+ the main menu.
+ </li>
+
+ <li>Click <strong>Add New Configuration (+)</strong> and select
+ <strong>Android Tests</strong>.
+ </li>
+
+ <li>In the Android Test configuration dialog:
+ <ol type="a">
+ <li>Enter or select the details of your test, such as the test name, module
+ type, test type, and test class.
+ </li>
+
+ <li>From the <em>Target</em> drop-down menu under <em>Deployment Target
+ Options</em>, select <strong>Cloud Test Lab Device Matrix</strong>.
+ </li>
+
+ <li>If you are not logged in, click <strong>Connect to Google Cloud
+ Platform</strong> and allow Android Studio access to your account.
+ </li>
+
+ <li>Next to <em>Cloud Project</em>, click the <img src=
+ "{@docRoot}images/tools/as-wrench.png" alt="wrench and nut" style=
+ "vertical-align:bottom;margin:0;"> button and select your Google Cloud
+ Platform project from the list.
+ </li>
+ </ol>
+ </li>
+
+ <li>Create and configure a test matrix:
+ <ol type="a">
+ <li>Next to the <em>Matrix Configuration</em> drop-down list, click <strong>
+ Open Dialog</strong> <img src="{@docRoot}images/tools/as-launchavdm.png"
+ alt="ellipses button" style="vertical-align:bottom;margin:0;">.
+ </li>
+
+ <li>Click <strong>Add New Configuration (+)</strong>.
+ </li>
+
+ <li>In the <strong>Name</strong> field, enter a name for your new
+ configuration.
+ </li>
+
+ <li>Select the device(s), Android version(s), locale(s) and screen
+ orientation(s) that you want to test your app with. Firebase Test Lab will
+ test your app against every combination of your selections when generating
+ test results.
+ </li>
+
+ <li>Click <strong>OK</strong> to save your configuration.
+ </li>
+ </ol>
+ </li>
+
+ <li>Click <strong>OK</strong> in the <em>Run/Debug Configurations</em> dialog
+ to exit.
+ </li>
+
+ <li>Run your tests by clicking <strong>Run</strong> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" style=
+ "vertical-align:bottom;margin:0;">.
+ </li>
+</ol>
+
+<img src="{@docRoot}images/training/ctl-config.png" alt="">
+<p class="img-caption">
+ <strong>Figure 1.</strong> Creating a test configuration for Firebase Test
+ Lab.
+</p>
+
+<h4 id="ctl-results">
+ Analyzing test results
+</h4>
+
+<p>
+ When Firebase Test Lab completes running your tests, the <em>Run</em> window
+ will open to show the results, as shown in figure 2. You may need to click
+ <strong>Show Passed</strong> <img src="{@docRoot}images/tools/as-ok.png" alt=
+ "" style="vertical-align:bottom;margin:0;"> to see all your executed tests.
+</p>
+
+<img src="{@docRoot}images/training/ctl-test-results.png" alt="">
+
+<p class="img-caption">
+ <strong>Figure 2.</strong> Viewing the results of instrumented tests using
+ Firebase Test Lab.
+</p>
+
+<p>
+ You can also analyze your tests on the web by following the link displayed at
+ the beginning of the test execution log in the <em>Run</em> window, as shown
+ in figure 3.
+</p>
+
+<img src="{@docRoot}images/training/ctl-exec-log.png" alt="">
+
+<p class="img-caption">
+ <strong>Figure 3.</strong> Click the link to view detailed test results on
+ the web.
+</p>
+
<p>
-To run your test, follow the steps for running instrumented tests
-described in <a href="{@docRoot}training/testing/start/index.html#run-instrumented-tests">
-Getting Started with Testing</a>.
+ To learn more about interpreting web results, see <a href=
+ "https://firebase.google.com/docs/test-lab/analyzing-results">Analyze
+ Firebase Test Lab for Android Results</a>.
</p> \ No newline at end of file
diff --git a/docs/html/training/testing/unit-testing/local-unit-tests.jd b/docs/html/training/testing/unit-testing/local-unit-tests.jd
index 893d957fcc41..25b62fa2e393 100644
--- a/docs/html/training/testing/unit-testing/local-unit-tests.jd
+++ b/docs/html/training/testing/unit-testing/local-unit-tests.jd
@@ -7,17 +7,16 @@ trainingnavtop=true
<!-- This is the training bar -->
<div id="tb-wrapper">
<div id="tb">
- <h2>Dependencies and Prerequisites</h2>
-
- <ul>
- <li><a href="{@docRoot}tools/studio/index.html">Android Studio (latest version)</a>.</li>
- </ul>
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#setup">Set Up Your Testing Environment</a></li>
- <li><a href="#build">Create a Local Unit Test Class</a></li>
+ <li><a href="#build">Create a Local Unit Test Class</a>
+ <ol>
+ <li><a href="#mocking-dependencies">Mock Android dependencies</a></li>
+ </ol>
+ </li>
<li><a href="#run">Run Local Unit Tests</a></li>
</ol>
@@ -42,13 +41,35 @@ test is greatly reduced. With this approach, you normally use a mocking framewor
dependency relationships.</p>
<h2 id="setup">Set Up Your Testing Environment</h2>
-<p>Before building your local unit test, make sure to configure your test source code location and
-project dependencies, as described in
-<a href="{@docRoot}training/testing/start/index.html#config-local-tests">
-Getting Started with Testing</a>.</p>
+
+<p>In your Android Studio project, you must store the source files for local
+unit tests at <code><var>module-name</var>/src/test/java/</code>. This directory
+already exists when you create a new project.</p>
+
+<p>You also need to configure the testing dependencies for your project to use
+the standard APIs provided by the JUnit 4 framework. If your test needs to
+interact with Android dependencies, include the <a href=
+"https://github.com/mockito/mockito" class="external-link">Mockito</a> library
+to simplify your local unit tests. To learn more about using mock objects in
+your local unit tests, see <a href=
+"{@docRoot}training/testing/unit-testing/local-unit-tests.html#mocking-dependencies">
+Mocking Android dependencies</a>.</p>
+
+<p>In your app's top-level {@code build.gradle} file, you need to specify these
+libraries as dependencies:</p>
+
+<pre>
+dependencies {
+ // Required -- JUnit 4 framework
+ testCompile 'junit:junit:4.12'
+ // Optional -- Mockito framework
+ testCompile 'org.mockito:mockito-core:1.10.19'
+}
+</pre>
<h2 id="build">Create a Local Unit Test Class</h2>
+
<p>Your local unit test class should be written as a JUnit 4 test class.
<a href="http://junit.org/" class="external-link">JUnit</a> is the most popular
and widely-used unit testing framework for Java. The latest version of this framework, JUnit 4,
@@ -90,7 +111,7 @@ can use <a href="https://github.com/hamcrest" class="external-link">
Hamcrest matchers</a> (such as the {@code is()} and {@code equalTo()} methods) to match the
returned result against the expected result.</p>
-<h3 id="mocking-dependencies">Mocking Android dependencies</h3>
+<h3 id="mocking-dependencies">Mock Android dependencies</h3>
<p>
By default, the <a href="{@docRoot}tools/building/plugin-for-gradle.html">
Android Plug-in for Gradle</a> executes your local unit tests against a modified
@@ -174,10 +195,37 @@ class="external-link">Mockito API reference</a> and the
class="external-link">sample code</a>.
</p>
+
<h2 id="run">Run Local Unit Tests</h2>
+
+<p>To run your local unit tests, follow these steps:</p>
+
+<ol>
+
+ <li>Be sure your project is synchronized with Gradle by clicking
+ <b>Sync Project</b> <img src="/images/tools/sync-project.png" alt=""
+ class="inline-icon"> in the toolbar.</li>
+
+ <li>Run your test in one of the following ways:
+ <ul>
+ <li>To run a single test, open the <b>Project</b> window, and then
+ right-click a test and click <strong>Run</strong> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.</li>
+ <li>To test all methods in a class, right-click a class or method in the
+test file and click <b>Run</b> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.
+ <li>To run all tests in a directory, right-click on the
+ directory and select <strong>Run tests</strong> <img src=
+ "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon">.
+ </li>
+ </ul>
+ </li>
+
+</ol>
+
<p>
-To run your tests, follow the steps for running local unit tests
-described in <a href="{@docRoot}training/testing/start/index.html#run-local-tests">
-Getting Started with Testing</a>.
+ The Android Plugin for Gradle compiles the local unit test code located in
+ the default directory ({@code src/test/java/}), builds a test app, and
+ executes it locally using the default test runner class. Android Studio then
+ displays the results in the <b>Run</b> window.
</p>
-
diff --git a/docs/html/wear/preview/api-overview.jd b/docs/html/wear/preview/api-overview.jd
index 543313af1a39..11331a777d62 100644
--- a/docs/html/wear/preview/api-overview.jd
+++ b/docs/html/wear/preview/api-overview.jd
@@ -4,9 +4,6 @@ page.tags="wear"
page.image=images/cards/card-n-apis_2x.png
@jd:body
-
-
-
<div id="qv-wrapper">
<div id="qv">
<h2>Key developer features</h2>
@@ -298,36 +295,35 @@ Multiple Network Connections</a>
authentication capabilities will be more powerful; apps will have new ways to
authenticate.</p>
- <h4> Authentication tokens can be passed over the Wearable Data Layer </h4>
-
-<p>For Android-paired watches (only), the phone will securely transfer authentication
- data to a watch app via the
- <a href="{@docRoot}training/wearables/data-layer/index.html">
- Wearable Data Layer API</a>. The data can be transferred as
- Messages or Data Items. </p>
-
-<p>If your watch app needs to determine if your phone app is installed, you can
-advertise a capability on the phone app and retrieve the capability on the watch.
- For more information, see following sections of
- <a href="{@docRoot}training/wearables/data-layer/messages.html">
- Sending and Receiving Messages</a>:
- <ul>
- <li>Advertise Capabilities</li>
- <li>Retrieve the Nodes with the Required Capabilities</li>
- </ul>
<h4>Users can enter a username and password on a watch</h4>
-<p>Google Keyboard will be standard on Android Wear, allowing for direct text entry.
- This feature will work as expected with standard
- <a href="{@docRoot}reference/android/widget/EditText.html">
- EditText widgets</a>. For passwords, the {@code textPassword} attribute will be
- used.
+<p>Google Keyboard will be standard on Android Wear, allowing for direct text
+entry. This feature will work as expected with standard
+<a href="{@docRoot}reference/android/widget/EditText.html">EditText widgets</a>.
+For passwords, the {@code textPassword} attribute will be used.</p>
<h4>Utilizing Account Manager</h4>
-Android Wear will include the <a href="{@docRoot}reference/android/accounts/AccountManager.html">
+
+<p>Android Wear will include the
+<a href="{@docRoot}reference/android/accounts/AccountManager.html">
AccountManager</a>, which will be accessible for syncing and storing account
- data, as it is on an Android phone.
-</p>
+data, as it is on an Android phone.</p>
+<h4>Authentication tokens can be passed over the Wearable Data Layer</h4>
+<p>For Android-paired watches (only), a phone securely
+transfers authentication credentials to a watch app via the
+<a href="{@docRoot}training/wearables/data-layer/index.html">
+Wearable Data Layer API</a>. The credentials can be transferred as
+messages or data items.</p>
+<p>If your watch app needs to determine if your phone app is installed, you can
+advertise a capability on the phone app and retrieve the capability on the
+watch. For more information, see the following sections of
+<a href="{@docRoot}training/wearables/data-layer/messages.html">
+Sending and Receiving Messages</a>:</p>
+
+<ul>
+ <li>Advertise Capabilities</li>
+ <li>Retrieve the Nodes with the Required Capabilities</li>
+</ul>
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index c6977746f64e..d5143dae7851 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -75,6 +75,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
private long mEnterAnimationEnd;
private long mExitAnimationEnd;
+ /** Callback that blocks invalidation. Used for drawable initialization. */
+ private BlockInvalidateCallback mBlockInvalidateCallback;
+
// overrides from Drawable
@Override
@@ -500,11 +503,14 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
* @param d The drawable to initialize.
*/
private void initializeDrawableForDisplay(Drawable d) {
+ if (mBlockInvalidateCallback == null) {
+ mBlockInvalidateCallback = new BlockInvalidateCallback();
+ }
+
// Temporary fix for suspending callbacks during initialization. We
// don't want any of these setters causing an invalidate() since that
// may call back into DrawableContainer.
- final Callback cb = d.getCallback();
- d.setCallback(null);
+ d.setCallback(mBlockInvalidateCallback.wrap(d.getCallback()));
try {
if (mDrawableContainerState.mEnterFadeDuration <= 0 && mHasAlpha) {
@@ -537,7 +543,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
hotspotBounds.right, hotspotBounds.bottom);
}
} finally {
- d.setCallback(cb);
+ d.setCallback(mBlockInvalidateCallback.unwrap());
}
}
@@ -1215,4 +1221,41 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
mLastIndex = -1;
mLastDrawable = null;
}
+
+ /**
+ * Callback that blocks drawable invalidation.
+ */
+ private static class BlockInvalidateCallback implements Drawable.Callback {
+ private Drawable.Callback mCallback;
+
+ public BlockInvalidateCallback wrap(Drawable.Callback callback) {
+ mCallback = callback;
+ return this;
+ }
+
+ public Drawable.Callback unwrap() {
+ final Drawable.Callback callback = mCallback;
+ mCallback = null;
+ return callback;
+ }
+
+ @Override
+ public void invalidateDrawable(@NonNull Drawable who) {
+ // Ignore invalidation.
+ }
+
+ @Override
+ public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
+ if (mCallback != null) {
+ mCallback.scheduleDrawable(who, what, when);
+ }
+ }
+
+ @Override
+ public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
+ if (mCallback != null) {
+ mCallback.unscheduleDrawable(who, what);
+ }
+ }
+ }
}
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index bcc354c5b736..3dbd2a96b00a 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -699,7 +699,7 @@ public class GradientDrawable extends Drawable {
float rad = mStrokePaint.getStrokeWidth();
canvas.saveLayer(mRect.left - rad, mRect.top - rad,
mRect.right + rad, mRect.bottom + rad,
- mLayerPaint, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
+ mLayerPaint);
// don't perform the filter in our individual paints
// since the layer will do it for us
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index a8c87370e18b..c34f474762f0 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -243,7 +243,9 @@ public class VectorDrawable extends Drawable {
* constructors to set the state and initialize local properties.
*/
private VectorDrawable(@NonNull VectorDrawableState state, @Nullable Resources res) {
- mVectorState = state;
+ // Constant state sharing is disabled until we fix onStateChanged()
+ // affecting the shared bitmap.
+ mVectorState = new VectorDrawableState(state);
updateLocalState(res);
}
diff --git a/libs/hwui/AnimationContext.cpp b/libs/hwui/AnimationContext.cpp
index 097be08faaad..5759ccd85464 100644
--- a/libs/hwui/AnimationContext.cpp
+++ b/libs/hwui/AnimationContext.cpp
@@ -63,7 +63,7 @@ void AnimationContext::startFrame(TreeInfo::TraversalMode mode) {
mCurrentFrameAnimations.mNextHandle = head;
head->mPreviousHandle = &mCurrentFrameAnimations;
}
- mFrameTimeMs = mClock.computeFrameTimeMs();
+ mFrameTimeMs = ns2ms(mClock.latestVsync());
}
void AnimationContext::runRemainingAnimations(TreeInfo& info) {
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index b8a5ce6686b4..37d9d0e749e6 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -946,6 +946,7 @@ void FrameBuilder::deferBeginUnclippedLayerOp(const BeginUnclippedLayerOp& op) {
Rect dstRect(op.unmappedBounds);
boundsTransform.mapRect(dstRect);
+ dstRect.roundOut();
dstRect.doIntersect(mCanvasState.currentSnapshot()->getRenderTargetClip());
if (dstRect.isEmpty()) {
diff --git a/libs/hwui/LayerUpdateQueue.cpp b/libs/hwui/LayerUpdateQueue.cpp
index db5f676d09dc..95f5cfb33474 100644
--- a/libs/hwui/LayerUpdateQueue.cpp
+++ b/libs/hwui/LayerUpdateQueue.cpp
@@ -26,6 +26,7 @@ void LayerUpdateQueue::clear() {
}
void LayerUpdateQueue::enqueueLayerWithDamage(RenderNode* renderNode, Rect damage) {
+ damage.roundOut();
damage.doIntersect(0, 0, renderNode->getWidth(), renderNode->getHeight());
if (!damage.isEmpty()) {
for (Entry& entry : mEntries) {
diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp
index e416e0c0061d..796c73b9c3e7 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.cpp
+++ b/libs/hwui/PropertyValuesAnimatorSet.cpp
@@ -29,7 +29,6 @@ void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* proper
PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder,
interpolator, startDelay, duration, repeatCount);
mAnimators.emplace_back(animator);
- setListener(new PropertyAnimatorSetListener(this));
// Check whether any child animator is infinite after adding it them to the set.
if (repeatCount == -1) {
@@ -42,6 +41,7 @@ PropertyValuesAnimatorSet::PropertyValuesAnimatorSet()
setStartValue(0);
mLastFraction = 0.0f;
setInterpolator(new LinearInterpolator());
+ setListener(new PropertyAnimatorSetListener(this));
}
void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) {
@@ -115,7 +115,7 @@ void PropertyValuesAnimatorSet::init() {
std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) {
return a->getTotalDuration() < b->getTotalDuration();
});
- mDuration = mAnimators[mAnimators.size() - 1]->getTotalDuration();
+ mDuration = mAnimators.empty() ? 0 : mAnimators[mAnimators.size() - 1]->getTotalDuration();
mInitialized = true;
}
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index b35c92612a42..cbefccb955de 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -127,7 +127,8 @@ int RecordingCanvas::saveLayer(float left, float top, float right, float bottom,
// operations will be able to store and restore the current clip and transform info, and
// quick rejection will be correct (for display lists)
- const Rect unmappedBounds(left, top, right, bottom);
+ Rect unmappedBounds(left, top, right, bottom);
+ unmappedBounds.roundOut();
// determine clipped bounds relative to previous viewport.
Rect visibleBounds = unmappedBounds;
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index f80be5ec9ae9..47fef6da355c 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -232,7 +232,7 @@ public:
// the frameNumber to appropriately batch/synchronize these transactions.
// There is no other filtering/batching to ensure that only the "final"
// state called once per frame.
- class ANDROID_API PositionListener {
+ class ANDROID_API PositionListener : public VirtualLightRefBase {
public:
virtual ~PositionListener() {}
// Called when the RenderNode's position changes
@@ -247,7 +247,7 @@ public:
// before the RenderNode is used for drawing.
// RenderNode takes ownership of the pointer
ANDROID_API void setPositionListener(PositionListener* listener) {
- mPositionListener.reset(listener);
+ mPositionListener = listener;
}
// This is only modified in MODE_FULL, so it can be safely accessed
@@ -366,7 +366,7 @@ private:
// mDisplayList, not mStagingDisplayList.
uint32_t mParentCount;
- std::unique_ptr<PositionListener> mPositionListener;
+ sp<PositionListener> mPositionListener;
}; // class RenderNode
} /* namespace uirenderer */
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index d4956bed25e8..ceef9c788fc1 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -784,6 +784,7 @@ void CanvasContext::enqueueFrameWork(std::function<void()>&& func) {
}
sp<FuncTask> task(new FuncTask());
task->func = func;
+ mFrameFences.push_back(task);
mFrameWorkProcessor->add(task);
}
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index f846d6a44473..6c2575f699bb 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -43,10 +43,6 @@ nsecs_t TimeLord::computeFrameTimeNanos() {
return mFrameTimeNanos;
}
-nsecs_t TimeLord::computeFrameTimeMs() {
- return nanoseconds_to_milliseconds(computeFrameTimeNanos());
-}
-
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
index 5464399234fb..68a0f7f971b9 100644
--- a/libs/hwui/renderthread/TimeLord.h
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -34,7 +34,6 @@ public:
// returns true if the vsync is newer, false if it was rejected for staleness
bool vsyncReceived(nsecs_t vsync);
nsecs_t latestVsync() { return mFrameTimeNanos; }
- nsecs_t computeFrameTimeMs();
nsecs_t computeFrameTimeNanos();
private:
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index af1fbd8254f9..af54e079daab 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -1007,6 +1007,40 @@ RENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_simple) {
EXPECT_EQ(4, renderer.getIndex());
}
+RENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_round) {
+ class SaveLayerUnclippedRoundTestRenderer : public TestRendererBase {
+ public:
+ void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(0, mIndex++);
+ EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds)
+ << "Bounds rect should round out";
+ }
+ void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {}
+ void onRectOp(const RectOp& op, const BakedOpState& state) override {}
+ void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(1, mIndex++);
+ EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds)
+ << "Bounds rect should round out";
+ }
+ };
+
+ auto node = TestUtils::createNode(0, 0, 200, 200,
+ [](RenderProperties& props, RecordingCanvas& canvas) {
+ canvas.saveLayerAlpha(10.95f, 10.5f, 189.75f, 189.25f, // values should all round out
+ 128, (SaveFlags::Flags)(0));
+ canvas.drawRect(0, 0, 200, 200, SkPaint());
+ canvas.restore();
+ });
+
+ FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
+ sLightGeometry, Caches::getInstance());
+ frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
+
+ SaveLayerUnclippedRoundTestRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(2, renderer.getIndex());
+}
+
RENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_mergedClears) {
class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase {
public:
diff --git a/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
index 8b0e91c77396..4db1cb935902 100644
--- a/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
+++ b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
@@ -39,17 +39,21 @@ static sp<RenderNode> createSyncedNode(uint32_t width, uint32_t height) {
TEST(LayerUpdateQueue, enqueueSimple) {
sp<RenderNode> a = createSyncedNode(100, 100);
sp<RenderNode> b = createSyncedNode(200, 200);
+ sp<RenderNode> c = createSyncedNode(200, 200);
LayerUpdateQueue queue;
queue.enqueueLayerWithDamage(a.get(), Rect(25, 25, 75, 75));
queue.enqueueLayerWithDamage(b.get(), Rect(100, 100, 300, 300));
+ queue.enqueueLayerWithDamage(c.get(), Rect(.5, .5, .5, .5));
- EXPECT_EQ(2u, queue.entries().size());
+ EXPECT_EQ(3u, 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
+ EXPECT_EQ(c.get(), queue.entries()[2].renderNode);
+ EXPECT_EQ(Rect(0, 0, 1, 1), queue.entries()[2].damage); // rounded out
}
TEST(LayerUpdateQueue, enqueueUnion) {
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 18171de250d0..9cd504ec0af7 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -340,6 +340,36 @@ TEST(RecordingCanvas, saveLayer_simple) {
EXPECT_EQ(3, count);
}
+TEST(RecordingCanvas, saveLayer_rounding) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 100, [](RecordingCanvas& canvas) {
+ canvas.saveLayerAlpha(10.25f, 10.75f, 89.25f, 89.75f, 128, SaveFlags::ClipToLayer);
+ canvas.drawRect(20, 20, 80, 80, SkPaint());
+ canvas.restore();
+ });
+ int count = 0;
+ playbackOps(*dl, [&count](const RecordedOp& op) {
+ Matrix4 expectedMatrix;
+ switch(count++) {
+ case 0:
+ EXPECT_EQ(RecordedOpId::BeginLayerOp, op.opId);
+ EXPECT_EQ(Rect(10, 10, 90, 90), op.unmappedBounds) << "Expect bounds rounded out";
+ break;
+ case 1:
+ EXPECT_EQ(RecordedOpId::RectOp, op.opId);
+ expectedMatrix.loadTranslate(-10, -10, 0);
+ EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix) << "Expect rounded offset";
+ break;
+ case 2:
+ EXPECT_EQ(RecordedOpId::EndLayerOp, op.opId);
+ // Don't bother asserting recording state data - it's not used
+ break;
+ default:
+ ADD_FAILURE();
+ }
+ });
+ EXPECT_EQ(3, count);
+}
+
TEST(RecordingCanvas, saveLayer_missingRestore) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.saveLayerAlpha(0, 0, 200, 200, 128, SaveFlags::ClipToLayer);
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 8efd5991a401..39184f1af878 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -467,11 +467,11 @@ public class AudioRecord implements AudioRouting
* <p>
* If the audio source is not set with {@link #setAudioSource(int)},
* {@link MediaRecorder.AudioSource#DEFAULT} is used.
- * <br>If the audio format is not specified or is incomplete, its sample rate will be the
- * default output sample rate of the device (see
- * {@link AudioManager#PROPERTY_OUTPUT_SAMPLE_RATE}), its channel configuration will be
+ * <br>If the audio format is not specified or is incomplete, its channel configuration will be
* {@link AudioFormat#CHANNEL_IN_MONO}, and the encoding will be
* {@link AudioFormat#ENCODING_PCM_16BIT}.
+ * The sample rate will depend on the device actually selected for capture and can be queried
+ * with {@link #getSampleRate()} method.
* <br>If the buffer size is not specified with {@link #setBufferSizeInBytes(int)},
* the minimum buffer size for the source is used.
*/
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 9a816683f30a..12d5eade36d2 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -619,11 +619,11 @@ public class AudioTrack extends PlayerBase
* <p>
* If the audio attributes are not set with {@link #setAudioAttributes(AudioAttributes)},
* attributes comprising {@link AudioAttributes#USAGE_MEDIA} will be used.
- * <br>If the audio format is not specified or is incomplete, its sample rate will be the
- * default output sample rate of the device (see
- * {@link AudioManager#PROPERTY_OUTPUT_SAMPLE_RATE}), its channel configuration will be
+ * <br>If the audio format is not specified or is incomplete, its channel configuration will be
* {@link AudioFormat#CHANNEL_OUT_STEREO} and the encoding will be
* {@link AudioFormat#ENCODING_PCM_16BIT}.
+ * The sample rate will depend on the device actually selected for playback and can be queried
+ * with {@link #getSampleRate()} method.
* <br>If the buffer size is not specified with {@link #setBufferSizeInBytes(int)},
* and the mode is {@link AudioTrack#MODE_STREAM}, the minimum buffer size is used.
* <br>If the transfer mode is not specified with {@link #setTransferMode(int)},
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 5b0845c5d42b..542dcedb007c 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -125,6 +125,77 @@ import java.util.Map;
All video codecs support flexible YUV 4:2:0 buffers since {@link
android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
+ <h4>Accessing Raw Video ByteBuffers on Older Devices</h4>
+ <p>
+ Prior to {@link android.os.Build.VERSION_CODES#LOLLIPOP} and {@link Image} support, you need to
+ use the {@link MediaFormat#KEY_STRIDE} and {@link MediaFormat#KEY_SLICE_HEIGHT} output format
+ values to understand the layout of the raw output buffers.
+ <p class=note>
+ Note that on some devices the slice-height is advertised as 0. This could mean either that the
+ slice-height is the same as the frame height, or that the slice-height is the frame height
+ aligned to some value (usually a power of 2). Unfortunately, there is no way to tell the actual
+ slice height in this case. Furthermore, the vertical stride of the {@code U} plane in planar
+ formats is also not specified or defined, though usually it is half of the slice height.
+ <p>
+ The {@link MediaFormat#KEY_WIDTH} and {@link MediaFormat#KEY_HEIGHT} keys specify the size of the
+ video frames; however, for most encondings the video (picture) only occupies a portion of the
+ video frame. This is represented by the 'crop rectangle'.
+ <p>
+ You need to use the following keys to get the crop rectangle of raw output images from the
+ {@linkplain #getOutputFormat output format}. If these keys are not present, the video occupies the
+ entire video frame.The crop rectangle is understood in the context of the output frame
+ <em>before</em> applying any {@linkplain MediaFormat#KEY_ROTATION rotation}.
+ <table style="width: 0%">
+ <thead>
+ <tr>
+ <th>Format Key</th>
+ <th>Type</th>
+ <th>Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{@code "crop-left"}</td>
+ <td>Integer</td>
+ <td>The left-coordinate (x) of the crop rectangle</td>
+ </tr><tr>
+ <td>{@code "crop-top"}</td>
+ <td>Integer</td>
+ <td>The top-coordinate (y) of the crop rectangle</td>
+ </tr><tr>
+ <td>{@code "crop-right"}</td>
+ <td>Integer</td>
+ <td>The right-coordinate (x) <strong>MINUS 1</strong> of the crop rectangle</td>
+ </tr><tr>
+ <td>{@code "crop-bottom"}</td>
+ <td>Integer</td>
+ <td>The bottom-coordinate (y) <strong>MINUS 1</strong> of the crop rectangle</td>
+ </tr><tr>
+ <td colspan=3>
+ The right and bottom coordinates can be understood as the coordinates of the right-most
+ valid column/bottom-most valid row of the cropped output image.
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <p>
+ The size of the video frame (before rotation) can be calculated as such:
+ <pre class=prettyprint>
+ MediaFormat format = decoder.getOutputFormat(&hellip;);
+ int width = format.getInteger(MediaFormat.KEY_WIDTH);
+ if (format.containsKey("crop-left") && format.containsKey("crop-right")) {
+ width = format.getInteger("crop-right") + 1 - format.getInteger("crop-left");
+ }
+ int height = format.getInteger(MediaFormat.KEY_HEIGHT);
+ if (format.containsKey("crop-top") && format.containsKey("crop-bottom")) {
+ height = format.getInteger("crop-bottom") + 1 - format.getInteger("crop-top");
+ }
+ </pre>
+ <p class=note>
+ Also note that the meaning of {@link BufferInfo#offset BufferInfo.offset} was not consistent across
+ devices. On some devices the offset pointed to the top-left pixel of the crop rectangle, while on
+ most devices it pointed to the top-left pixel of the entire frame.
+
<h3>States</h3>
<p>
During its life a codec conceptually exists in one of three states: Stopped, Executing or
@@ -226,8 +297,8 @@ import java.util.Map;
Codec-specific data in the format is automatically submitted to the codec upon {@link #start};
you <strong>MUST NOT</strong> submit this data explicitly. If the format did not contain codec
specific data, you can choose to submit it using the specified number of buffers in the correct
- order, according to the format requirements. Alternately, you can concatenate all codec-specific
- data and submit it as a single codec-config buffer.
+ order, according to the format requirements. In case of H.264 AVC, you can also concatenate all
+ codec-specific data and submit it as a single codec-config buffer.
<p>
Android uses the following codec-specific data buffers. These are also required to be set in
the track format for proper {@link MediaMuxer} track configuration. Each parameter set and the
@@ -284,6 +355,13 @@ import java.util.Map;
<td class=NA>Not Used</td>
<td class=NA>Not Used</td>
</tr>
+ <tr>
+ <td>VP9</td>
+ <td>VP9 <a href="http://wiki.webmproject.org/vp9-codecprivate">CodecPrivate</a> Data
+ (optional)</td>
+ <td class=NA>Not Used</td>
+ <td class=NA>Not Used</td>
+ </tr>
</tbody>
</table>
@@ -535,6 +613,32 @@ import java.util.Map;
Also since {@link android.os.Build.VERSION_CODES#M}, you can change the output Surface
dynamically using {@link #setOutputSurface setOutputSurface}.
+ <h4>Transformations When Rendering onto Surface</h4>
+
+ If the codec is configured into Surface mode, any crop rectangle, {@linkplain
+ MediaFormat#KEY_ROTATION rotation} and {@linkplain #setVideoScalingMode video scaling
+ mode} will be automatically applied with one exception:
+ <p class=note>
+ Prior to the {@link android.os.Build.VERSION_CODES#M} release, software decoders may not
+ have applied the rotation when being rendered onto a Surface. Unfortunately, there is no way to
+ identify software decoders, or if they apply the rotation other than by trying it out.
+ <p>
+ There are also some caveats.
+ <p class=note>
+ Note that the pixel aspect ratio is not considered when displaying the output onto the
+ Surface. This means that if you are using {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT} mode, you
+ must position the output Surface so that it has the proper final display aspect ratio. Conversely,
+ you can only use {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING} mode for content with
+ square pixels (pixel aspect ratio or 1:1).
+ <p class=note>
+ Note also that as of {@link android.os.Build.VERSION_CODES#N} release, {@link
+ #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING} mode may not work correctly for videos rotated
+ by 90 or 270 degrees.
+ <p class=note>
+ When setting the video scaling mode, note that it must be reset after each time the output
+ buffers change. Since the {@link #INFO_OUTPUT_BUFFERS_CHANGED} event is deprecated, you can
+ do this after each time the output format changes.
+
<h4>Using an Input Surface</h4>
<p>
When using an input Surface, there are no accessible input buffers, as buffers are automatically
@@ -2984,7 +3088,13 @@ final public class MediaCodec {
/**
* The content is scaled, maintaining its aspect ratio, the whole
- * surface area is used, content may be cropped
+ * surface area is used, content may be cropped.
+ * <p class=note>
+ * This mode is only suitable for content with 1:1 pixel aspect ratio as you cannot
+ * configure the pixel aspect ratio for a {@link Surface}.
+ * <p class=note>
+ * As of {@link android.os.Build.VERSION_CODES#N} release, this mode may not work if
+ * the video is {@linkplain MediaFormat#KEY_ROTATION rotated} by 90 or 270 degrees.
*/
public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2;
@@ -2999,10 +3109,15 @@ final public class MediaCodec {
/**
* If a surface has been specified in a previous call to {@link #configure}
* specifies the scaling mode to use. The default is "scale to fit".
- * <p class=note>The scaling mode may be reset to the <strong>default</strong> each time an
+ * <p class=note>
+ * The scaling mode may be reset to the <strong>default</strong> each time an
* {@link #INFO_OUTPUT_BUFFERS_CHANGED} event is received from the codec; therefore, the client
* must call this method after every buffer change event (and before the first output buffer is
- * released for rendering) to ensure consistent scaling mode.</p>
+ * released for rendering) to ensure consistent scaling mode.
+ * <p class=note>
+ * Since the {@link #INFO_OUTPUT_BUFFERS_CHANGED} event is deprecated, this can also be done
+ * after each {@link #INFO_OUTPUT_FORMAT_CHANGED} event.
+ *
* @throws IllegalArgumentException if mode is not recognized.
* @throws IllegalStateException if in the Released state.
*/
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 45d0cc025a16..0bfeaed36282 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -541,6 +541,72 @@ public final class MediaCodecInfo {
* frame rate}. Use
* <code class=prettyprint>format.setString(MediaFormat.KEY_FRAME_RATE, null)</code>
* to clear any existing frame rate setting in the format.
+ * <p>
+ *
+ * The following table summarizes the format keys considered by this method.
+ *
+ * <table style="width: 0%">
+ * <thead>
+ * <tr>
+ * <th rowspan=3>OS Version(s)</th>
+ * <td colspan=3>{@code MediaFormat} keys considered for</th>
+ * </tr><tr>
+ * <th>Audio Codecs</th>
+ * <th>Video Codecs</th>
+ * <th>Encoders</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP}</th>
+ * <td rowspan=3>{@link MediaFormat#KEY_MIME}<sup>*</sup>,<br>
+ * {@link MediaFormat#KEY_SAMPLE_RATE},<br>
+ * {@link MediaFormat#KEY_CHANNEL_COUNT},</td>
+ * <td>{@link MediaFormat#KEY_MIME}<sup>*</sup>,<br>
+ * {@link CodecCapabilities#FEATURE_AdaptivePlayback}<sup>D</sup>,<br>
+ * {@link CodecCapabilities#FEATURE_SecurePlayback}<sup>D</sup>,<br>
+ * {@link CodecCapabilities#FEATURE_TunneledPlayback}<sup>D</sup>,<br>
+ * {@link MediaFormat#KEY_WIDTH},<br>
+ * {@link MediaFormat#KEY_HEIGHT},<br>
+ * <strong>no</strong> {@code KEY_FRAME_RATE}</td>
+ * <td rowspan=4>{@link MediaFormat#KEY_BITRATE_MODE},<br>
+ * {@link MediaFormat#KEY_PROFILE}
+ * (and/or {@link MediaFormat#KEY_AAC_PROFILE}<sup>~</sup>),<br>
+ * <!-- {link MediaFormat#KEY_QUALITY},<br> -->
+ * {@link MediaFormat#KEY_COMPLEXITY}
+ * (and/or {@link MediaFormat#KEY_FLAC_COMPRESSION_LEVEL}<sup>~</sup>)</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}</th>
+ * <td rowspan=2>as above, plus<br>
+ * {@link MediaFormat#KEY_FRAME_RATE}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#M}</th>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#N}</th>
+ * <td>as above, plus<br>
+ * {@link MediaFormat#KEY_PROFILE},<br>
+ * <!-- {link MediaFormat#KEY_MAX_BIT_RATE},<br> -->
+ * {@link MediaFormat#KEY_BIT_RATE}</td>
+ * <td>as above, plus<br>
+ * {@link MediaFormat#KEY_PROFILE},<br>
+ * {@link MediaFormat#KEY_LEVEL}<sup>+</sup>,<br>
+ * <!-- {link MediaFormat#KEY_MAX_BIT_RATE},<br> -->
+ * {@link MediaFormat#KEY_BIT_RATE},<br>
+ * {@link CodecCapabilities#FEATURE_IntraRefresh}<sup>E</sup></td>
+ * </tr>
+ * <tr>
+ * <td colspan=4>
+ * <p class=note><strong>Notes:</strong><br>
+ * *: must be specified; otherwise, method returns {@code false}.<br>
+ * +: method does not verify that the format parameters are supported
+ * by the specified level.<br>
+ * D: decoders only<br>
+ * E: encoders only<br>
+ * ~: if both keys are provided values must match
+ * </td>
+ * </tr>
+ * </tbody>
+ * </table>
*
* @param format media format with optional feature directives.
* @throws IllegalArgumentException if format is not a valid media format.
@@ -1372,16 +1438,33 @@ public final class MediaCodecInfo {
* May return {@code null}, if the codec did not publish any measurement
* data.
* <p>
- * This is a performance estimate provided by the device manufacturer
- * based on full-speed decoding and encoding measurements in various configurations
+ * This is a performance estimate provided by the device manufacturer based on statistical
+ * sampling of full-speed decoding and encoding measurements in various configurations
* of common video sizes supported by the codec. As such it should only be used to
* compare individual codecs on the device. The value is not suitable for comparing
* different devices or even different android releases for the same device.
* <p>
- * The returned range corresponds to the fastest frame rates achieved in the tested
- * configurations. It is interpolated from the nearest frame size(s) tested. Codec
- * performance is severely impacted by other activity on the device, and can vary
- * significantly.
+ * <em>On {@link android.os.Build.VERSION_CODES#M} release</em> the returned range
+ * corresponds to the fastest frame rates achieved in the tested configurations. As
+ * such, it should not be used to gauge guaranteed or even average codec performance
+ * on the device.
+ * <p>
+ * <em>On {@link android.os.Build.VERSION_CODES#N} release</em> the returned range
+ * corresponds closer to sustained performance <em>in tested configurations</em>.
+ * One can expect to achieve sustained performance higher than the lower limit more than
+ * 50% of the time, and higher than half of the lower limit at least 90% of the time
+ * <em>in tested configurations</em>.
+ * Conversely, one can expect performance lower than twice the upper limit at least
+ * 90% of the time.
+ * <p class=note>
+ * Tested configurations use a single active codec. For use cases where multiple
+ * codecs are active, applications can expect lower and in most cases significantly lower
+ * performance.
+ * <p class=note>
+ * The returned range value is interpolated from the nearest frame size(s) tested.
+ * Codec performance is severely impacted by other activity on the device as well
+ * as environmental factors (such as battery level, temperature or power source), and can
+ * vary significantly even in a steady environment.
* <p class=note>
* Use this method in cases where only codec performance matters, e.g. to evaluate if
* a codec has any chance of meeting a performance target. Codecs are listed
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index 42ce5110f134..3cb4cbe99a4b 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -201,6 +201,9 @@ final public class MediaCodecList {
* <code class=prettyprint>format.setString(MediaFormat.KEY_FRAME_RATE, null)</code>
* to clear any existing frame rate setting in the format.
*
+ * @see MediaCodecList.CodecCapabilities.isFormatSupported for format keys
+ * considered per android versions when evaluating suitable codecs.
+ *
* @param format A decoder media format with optional feature directives.
* @throws IllegalArgumentException if format is not a valid media format.
* @throws NullPointerException if format is null.
@@ -222,6 +225,9 @@ final public class MediaCodecList {
* <code class=prettyprint>format.setString(MediaFormat.KEY_FRAME_RATE, null)</code>
* to clear any existing frame rate setting in the format.
*
+ * @see MediaCodecList.CodecCapabilities.isFormatSupported for format keys
+ * considered per android versions when evaluating suitable codecs.
+ *
* @param format An encoder media format with optional feature directives.
* @throws IllegalArgumentException if format is not a valid media format.
* @throws NullPointerException if format is null.
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 24a400e48189..6f5199b6959c 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -333,7 +333,113 @@ final public class MediaExtractor {
/**
* Get the track format at the specified index.
+ *
* More detail on the representation can be found at {@link android.media.MediaCodec}
+ * <p>
+ * The following table summarizes support for format keys across android releases:
+ *
+ * <table style="width: 0%">
+ * <thead>
+ * <tr>
+ * <th rowspan=2>OS Version(s)</th>
+ * <td colspan=3>{@code MediaFormat} keys used for</th>
+ * </tr><tr>
+ * <th>All Tracks</th>
+ * <th>Audio Tracks</th>
+ * <th>Video Tracks</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>{@link android.os.Build.VERSION_CODES#JELLY_BEAN}</td>
+ * <td rowspan=8>{@link MediaFormat#KEY_MIME},<br>
+ * {@link MediaFormat#KEY_DURATION},<br>
+ * {@link MediaFormat#KEY_MAX_INPUT_SIZE}</td>
+ * <td rowspan=5>{@link MediaFormat#KEY_SAMPLE_RATE},<br>
+ * {@link MediaFormat#KEY_CHANNEL_COUNT},<br>
+ * {@link MediaFormat#KEY_CHANNEL_MASK},<br>
+ * gapless playback information<sup>.mp3, .mp4</sup>,<br>
+ * {@link MediaFormat#KEY_IS_ADTS}<sup>AAC if streaming</sup>,<br>
+ * codec-specific data<sup>AAC, Vorbis</sup></td>
+ * <td rowspan=2>{@link MediaFormat#KEY_WIDTH},<br>
+ * {@link MediaFormat#KEY_HEIGHT},<br>
+ * codec-specific data<sup>AVC, MPEG4</sup></td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}</td>
+ * <td rowspan=3>as above, plus<br>
+ * Pixel aspect ratio information<sup>AVC, *</sup></td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#KITKAT}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#KITKAT_WATCH}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP}</td>
+ * <td rowspan=2>as above, plus<br>
+ * {@link MediaFormat#KEY_BIT_RATE}<sup>AAC</sup>,<br>
+ * codec-specific data<sup>Opus</sup></td>
+ * <td rowspan=2>as above, plus<br>
+ * {@link MediaFormat#KEY_ROTATION}<sup>.mp4</sup>,<br>
+ * {@link MediaFormat#KEY_BIT_RATE}<sup>MPEG4</sup>,<br>
+ * codec-specific data<sup>HEVC</sup></td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#M}</td>
+ * <td>as above, plus<br>
+ * gapless playback information<sup>Opus</sup></td>
+ * <td>as above, plus<br>
+ * {@link MediaFormat#KEY_FRAME_RATE} (integer)</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#N}</td>
+ * <td>as above, plus<br>
+ * {@link MediaFormat#KEY_TRACK_ID},<br>
+ * <!-- {link MediaFormat#KEY_MAX_BIT_RATE}<sup>#, .mp4</sup>,<br> -->
+ * {@link MediaFormat#KEY_BIT_RATE}<sup>#, .mp4</sup></td>
+ * <td>as above, plus<br>
+ * {@link MediaFormat#KEY_PCM_ENCODING},<br>
+ * {@link MediaFormat#KEY_PROFILE}<sup>AAC</sup></td>
+ * <td>as above, plus<br>
+ * {@link MediaFormat#KEY_HDR_STATIC_INFO}<sup>#, .webm</sup>,<br>
+ * {@link MediaFormat#KEY_COLOR_STANDARD}<sup>#</sup>,<br>
+ * {@link MediaFormat#KEY_COLOR_TRANSFER}<sup>#</sup>,<br>
+ * {@link MediaFormat#KEY_COLOR_RANGE}<sup>#</sup>,<br>
+ * {@link MediaFormat#KEY_PROFILE}<sup>MPEG2, H.263, MPEG4, AVC, HEVC, VP9</sup>,<br>
+ * {@link MediaFormat#KEY_LEVEL}<sup>H.263, MPEG4, AVC, HEVC, VP9</sup>,<br>
+ * codec-specific data<sup>VP9</sup></td>
+ * </tr>
+ * <tr>
+ * <td colspan=4>
+ * <p class=note><strong>Notes:</strong><br>
+ * #: container-specified value only.<br>
+ * .mp4, .webm&hellip;: for listed containers<br>
+ * MPEG4, AAC&hellip;: for listed codecs
+ * </td>
+ * </tr><tr>
+ * <td colspan=4>
+ * <p class=note>Note that that level information contained in the container many times
+ * does not match the level of the actual bitstream. You may want to clear the level using
+ * {@code MediaFormat.setString(KEY_LEVEL, null)} before using the track format to find a
+ * decoder that can play back a particular track.
+ * </td>
+ * </tr><tr>
+ * <td colspan=4>
+ * <p class=note><strong>*Pixel (sample) aspect ratio</strong> is returned in the following
+ * keys. The display width can be calculated for example as:
+ * <p align=center>
+ * display-width = display-height * crop-width / crop-height * sar-width / sar-height
+ * </td>
+ * </tr><tr>
+ * <th>Format Key</th><th>Value Type</th><th colspan=2>Description</th>
+ * </tr><tr>
+ * <td>{@code "sar-width"}</td><td>Integer</td><td colspan=2>Pixel aspect ratio width</td>
+ * </tr><tr>
+ * <td>{@code "sar-height"}</td><td>Integer</td><td colspan=2>Pixel aspect ratio height</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
*/
@NonNull
public MediaFormat getTrackFormat(int index) {
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 33e39575fdac..d7a18d97874d 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -295,17 +295,19 @@ public final class MediaFormat {
* Stride (or row increment) is the difference between the index of a pixel
* and that of the pixel directly underneath. For YUV 420 formats, the
* stride corresponds to the Y plane; the stride of the U and V planes can
- * be calculated based on the color format.
+ * be calculated based on the color format, though it is generally undefined
+ * and depends on the device and release.
* The associated value is an integer, representing number of bytes.
*/
public static final String KEY_STRIDE = "stride";
/**
* A key describing the plane height of a multi-planar (YUV) video bytebuffer layout.
- * Slice height (or plane height) is the number of rows that must be skipped to get
- * from the top of the Y plane to the top of the U plane in the bytebuffer. In essence
+ * Slice height (or plane height/vertical stride) is the number of rows that must be skipped
+ * to get from the top of the Y plane to the top of the U plane in the bytebuffer. In essence
* the offset of the U plane is sliceHeight * stride. The height of the U/V planes
- * can be calculated based on the color format.
+ * can be calculated based on the color format, though it is generally undefined
+ * and depends on the device and release.
* The associated value is an integer, representing number of rows.
*/
public static final String KEY_SLICE_HEIGHT = "slice-height";
@@ -552,7 +554,9 @@ public final class MediaFormat {
/**
* A key describing the desired clockwise rotation on an output surface.
* This key is only used when the codec is configured using an output surface.
- * The associated value is an integer, representing degrees.
+ * The associated value is an integer, representing degrees. Supported values
+ * are 0, 90, 180 or 270. This is an optional field; if not specified, rotation
+ * defaults to 0.
*
* @see MediaCodecInfo.CodecCapabilities#profileLevels
*/
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index 7117fbdbf122..e481aa141d6b 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -266,6 +266,121 @@ final public class MediaMuxer {
/**
* Adds a track with the specified format.
+ * <p>
+ * The following table summarizes support for specific format keys across android releases.
+ * Keys marked with '+:' are required.
+ *
+ * <table style="width: 0%">
+ * <thead>
+ * <tr>
+ * <th rowspan=2>OS Version(s)</th>
+ * <td colspan=3>{@code MediaFormat} keys used for</th>
+ * </tr><tr>
+ * <th>All Tracks</th>
+ * <th>Audio Tracks</th>
+ * <th>Video Tracks</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>{@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}</td>
+ * <td rowspan=7>+: {@link MediaFormat#KEY_MIME}</td>
+ * <td rowspan=3>+: {@link MediaFormat#KEY_SAMPLE_RATE},<br>
+ * +: {@link MediaFormat#KEY_CHANNEL_COUNT},<br>
+ * +: <strong>codec-specific data<sup>AAC</sup></strong></td>
+ * <td rowspan=5>+: {@link MediaFormat#KEY_WIDTH},<br>
+ * +: {@link MediaFormat#KEY_HEIGHT},<br>
+ * no {@code KEY_ROTATION},
+ * use {@link #setOrientationHint setOrientationHint()}<sup>.mp4</sup>,<br>
+ * +: <strong>codec-specific data<sup>AVC, MPEG4</sup></strong></td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#KITKAT}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#KITKAT_WATCH}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP}</td>
+ * <td rowspan=4>as above, plus<br>
+ * +: <strong>codec-specific data<sup>Vorbis & .webm</sup></strong></td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#M}</td>
+ * <td>as above, plus<br>
+ * {@link MediaFormat#KEY_BIT_RATE}<sup>AAC</sup></td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#N}</td>
+ * <td>as above, plus<br>
+ * <!-- {link MediaFormat#KEY_MAX_BIT_RATE}<sup>AAC, MPEG4</sup>,<br> -->
+ * {@link MediaFormat#KEY_BIT_RATE}<sup>MPEG4</sup>,<br>
+ * {@link MediaFormat#KEY_HDR_STATIC_INFO}<sup>#, .webm</sup>,<br>
+ * {@link MediaFormat#KEY_COLOR_STANDARD}<sup>#</sup>,<br>
+ * {@link MediaFormat#KEY_COLOR_TRANSFER}<sup>#</sup>,<br>
+ * {@link MediaFormat#KEY_COLOR_RANGE}<sup>#</sup>,<br>
+ * +: <strong>codec-specific data<sup>HEVC</sup></strong>,<br>
+ * codec-specific data<sup>VP9</sup></td>
+ * </tr>
+ * <tr>
+ * <td colspan=4>
+ * <p class=note><strong>Notes:</strong><br>
+ * #: storing into container metadata.<br>
+ * .mp4, .webm&hellip;: for listed containers<br>
+ * MPEG4, AAC&hellip;: for listed codecs
+ * </td>
+ * </tr><tr>
+ * <td colspan=4>
+ * <p class=note>Note that the codec-specific data for the track must be specified using
+ * this method. Furthermore, codec-specific data must not be passed/specified via the
+ * {@link #writeSampleData writeSampleData()} call.
+ * </td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
+ * <p>
+ * The following table summarizes codec support for containers across android releases:
+ *
+ * <table style="width: 0%">
+ * <thead>
+ * <tr>
+ * <th rowspan=2>OS Version(s)</th>
+ * <td colspan=3>Codec support</th>
+ * </tr><tr>
+ * <th>{@linkplain OutputFormat#MUXER_OUTPUT_MPEG_4 MP4}</th>
+ * <th>{@linkplain OutputFormat#MUXER_OUTPUT_WEBM WEBM}</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>{@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}</td>
+ * <td rowspan=6>{@link MediaFormat#MIMETYPE_AUDIO_AAC AAC},<br>
+ * {@link MediaFormat#MIMETYPE_AUDIO_AMR_NB NB-AMR},<br>
+ * {@link MediaFormat#MIMETYPE_AUDIO_AMR_WB WB-AMR},<br>
+ * {@link MediaFormat#MIMETYPE_VIDEO_H263 H.263},<br>
+ * {@link MediaFormat#MIMETYPE_VIDEO_MPEG4 MPEG-4},<br>
+ * {@link MediaFormat#MIMETYPE_VIDEO_AVC AVC} (H.264)</td>
+ * <td rowspan=3>Not supported</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#KITKAT}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#KITKAT_WATCH}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP}</td>
+ * <td rowspan=3>{@link MediaFormat#MIMETYPE_AUDIO_VORBIS Vorbis},<br>
+ * {@link MediaFormat#MIMETYPE_VIDEO_VP8 VP8}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#M}</td>
+ * </tr><tr>
+ * <td>{@link android.os.Build.VERSION_CODES#N}</td>
+ * <td>as above, plus<br>
+ * {@link MediaFormat#MIMETYPE_VIDEO_HEVC HEVC} (H.265)</td>
+ * <td>as above, plus<br>
+ * {@link MediaFormat#MIMETYPE_VIDEO_VP9 VP9}</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ *
* @param format The media format for the track. This must not be an empty
* MediaFormat.
* @return The track index for this newly added track, and it should be used
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 4d40e6ba99ab..8d4a1510715a 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -476,10 +476,10 @@ import java.lang.ref.WeakReference;
* <td>This method can be called in any state and calling it does not change
* the object state. </p></td></tr>
* <tr><td>setPlaybackParams</p></td>
- * <td>any </p></td>
- * <td>{} </p></td>
- * <td>This method can be called in any state and calling it does not change
- * the object state. </p></td></tr>
+ * <td>{Initialized, Prepared, Started, Paused, PlaybackCompleted, Error}</p></td>
+ * <td>{Idle, Stopped} </p></td>
+ * <td>This method will change state in some cases, depending on when it's called.
+ * </p></td></tr>
* <tr><td>setScreenOnWhilePlaying</></td>
* <td>any </p></td>
* <td>{} </p></td>
@@ -1449,12 +1449,18 @@ public class MediaPlayer extends PlayerBase
}
/**
- * Sets playback rate using {@link PlaybackParams}.
+ * Sets playback rate using {@link PlaybackParams}. The object sets its internal
+ * PlaybackParams to the input, except that the object remembers previous speed
+ * when input speed is zero. This allows the object to resume at previous speed
+ * when start() is called. Calling it before the object is prepared does not change
+ * the object state. After the object is prepared, calling it with zero speed is
+ * equivalent to calling pause(). After the object is prepared, calling it with
+ * non-zero speed is equivalent to calling start().
*
* @param params the playback params.
*
* @throws IllegalStateException if the internal player engine has not been
- * initialized.
+ * initialized or has been released.
* @throws IllegalArgumentException if params is not supported.
*/
public native void setPlaybackParams(@NonNull PlaybackParams params);
diff --git a/packages/CtsShim/CtsShim.apk b/packages/CtsShim/CtsShim.apk
index 7a27a438fcc6..27289037dd8b 100644
--- a/packages/CtsShim/CtsShim.apk
+++ b/packages/CtsShim/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/CtsShimPriv.apk b/packages/CtsShim/CtsShimPriv.apk
index 63e86883589b..9a8e75c28b05 100644
--- a/packages/CtsShim/CtsShimPriv.apk
+++ b/packages/CtsShim/CtsShimPriv.apk
Binary files differ
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 9d4b50c60bfb..1922773c9cb8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -215,9 +215,12 @@ public abstract class BaseActivity extends Activity
includeState(state);
// Advanced roots are shown by default without menu option if forced by config or intent.
- state.showAdvanced = Shared.shouldShowDeviceRoot(this, intent);
+ boolean forceAdvanced = Shared.shouldShowDeviceRoot(this, intent);
+ boolean chosenAdvanced = LocalPreferences.getShowDeviceRoot(this, state.action);
+ state.showAdvanced = forceAdvanced || chosenAdvanced;
+
// Menu option is shown for whitelisted intents if advanced roots are not shown by default.
- state.showAdvancedOption = !state.showAdvanced && (
+ state.showAdvancedOption = !forceAdvanced && (
Shared.shouldShowFancyFeatures(this)
|| state.action == ACTION_OPEN
|| state.action == ACTION_CREATE
@@ -483,6 +486,7 @@ public abstract class BaseActivity extends Activity
Metrics.logUserAction(this,
display ? Metrics.USER_ACTION_SHOW_ADVANCED : Metrics.USER_ACTION_HIDE_ADVANCED);
+ LocalPreferences.setShowDeviceRoot(this, mState.action, display);
mState.showAdvanced = display;
RootsFragment.get(getFragmentManager()).onDisplayStateChanged();
invalidateOptionsMenu();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index 2315664f0d8a..d2e9885edf14 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -18,9 +18,6 @@ package com.android.documentsui;
import static com.android.documentsui.State.MODE_UNKNOWN;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.content.Context;
@@ -28,11 +25,16 @@ import android.content.SharedPreferences;
import android.os.UserHandle;
import android.preference.PreferenceManager;
+import com.android.documentsui.State.ActionType;
import com.android.documentsui.State.ViewMode;
import com.android.documentsui.model.RootInfo;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
public class LocalPreferences {
private static final String KEY_FILE_SIZE = "fileSize";
+ private static final String INCLUDE_DEVICE_ROOT = "includeDeviceRoot-";
private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-";
public static boolean getDisplayFileSize(Context context) {
@@ -48,9 +50,17 @@ public class LocalPreferences {
getPrefs(context).edit().putBoolean(KEY_FILE_SIZE, display).apply();
}
+ public static boolean getShowDeviceRoot(Context context, @ActionType int action) {
+ return getPrefs(context).getBoolean(INCLUDE_DEVICE_ROOT + action, false);
+ }
+
+ public static void setShowDeviceRoot(
+ Context context, @ActionType int action, boolean display) {
+ getPrefs(context).edit().putBoolean(INCLUDE_DEVICE_ROOT + action, display).apply();
+ }
+
public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) {
assert(viewMode != MODE_UNKNOWN);
-
getPrefs(context).edit().putInt(createKey(root), viewMode).apply();
}
diff --git a/packages/EasterEgg/Android.mk b/packages/EasterEgg/Android.mk
new file mode 100644
index 000000000000..df081f4091d9
--- /dev/null
+++ b/packages/EasterEgg/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-v4 \
+ android-support-v13 \
+ android-support-v7-recyclerview \
+ android-support-v7-preference \
+ android-support-v7-appcompat \
+ android-support-v14-preference \
+ jsr305
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := EasterEgg
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/EasterEgg/AndroidManifest.xml b/packages/EasterEgg/AndroidManifest.xml
new file mode 100644
index 000000000000..50e8b5ca7d2b
--- /dev/null
+++ b/packages/EasterEgg/AndroidManifest.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.egg"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="24" />
+
+ <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application android:label="@string/app_name" android:icon="@drawable/icon">
+ <!-- Long press the QS tile to get here -->
+ <activity android:name=".neko.NekoLand"
+ android:theme="@android:style/Theme.Material.NoActionBar"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
+ </intent-filter>
+ </activity>
+
+ <!-- This is where the magic happens -->
+ <service
+ android:name=".neko.NekoService"
+ android:enabled="true"
+ android:permission="android.permission.BIND_JOB_SERVICE"
+ android:exported="true" >
+ </service>
+
+ <!-- Used to show over lock screen -->
+ <activity android:name=".neko.NekoLockedActivity"
+ android:excludeFromRecents="true"
+ android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar"
+ android:showOnLockScreen="true" />
+
+ <!-- Used to enable easter egg -->
+ <activity android:name=".neko.NekoActivationActivity"
+ android:excludeFromRecents="true"
+ android:theme="@android:style/Theme.NoDisplay"
+ >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="com.android.internal.category.PLATLOGO" />
+ </intent-filter>
+ </activity>
+
+ <!-- The quick settings tile, disabled by default -->
+ <service
+ android:name=".neko.NekoTile"
+ android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
+ android:icon="@drawable/stat_icon"
+ android:enabled="false"
+ android:label="@string/default_tile_name">
+ <intent-filter>
+ <action android:name="android.service.quicksettings.action.QS_TILE" />
+ </intent-filter>
+ </service>
+ </application>
+</manifest>
diff --git a/packages/EasterEgg/res/drawable/back.xml b/packages/EasterEgg/res/drawable/back.xml
new file mode 100644
index 000000000000..b55d65cdf76d
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/back.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="back" android:fillColor="#FF000000" android:pathData="M37.1,22c-1.1,0 -1.9,0.8 -1.9,1.9v5.6c0,1.1 0.8,1.9 1.9,1.9H39v-1.9v-5.6V22H37.1z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/belly.xml b/packages/EasterEgg/res/drawable/belly.xml
new file mode 100644
index 000000000000..8b0e9afac463
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/belly.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="belly" android:fillColor="#FF000000" android:pathData="M20.5,25c-3.6,0 -6.5,2.9 -6.5,6.5V38h13v-6.5C27,27.9 24.1,25 20.5,25z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/body.xml b/packages/EasterEgg/res/drawable/body.xml
new file mode 100644
index 000000000000..86087209eff5
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/body.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="body" android:fillColor="#FF000000" android:pathData="M9,20h30v18h-30z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/bowtie.xml b/packages/EasterEgg/res/drawable/bowtie.xml
new file mode 100644
index 000000000000..33fa9216712f
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/bowtie.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="bowtie" android:fillColor="#FF000000" android:pathData="M29,16.8l-10,5l0,-5l10,5z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/cap.xml b/packages/EasterEgg/res/drawable/cap.xml
new file mode 100644
index 000000000000..d8b4cc58a261
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/cap.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="cap" android:fillColor="#FF000000" android:pathData="M27.2,3.8c-1,-0.2 -2.1,-0.3 -3.2,-0.3s-2.1,0.1 -3.2,0.3c0.2,1.3 1.5,2.2 3.2,2.2C25.6,6.1 26.9,5.1 27.2,3.8z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/collar.xml b/packages/EasterEgg/res/drawable/collar.xml
new file mode 100644
index 000000000000..6c0d90a9bf22
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/collar.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="collar" android:fillColor="#FF000000" android:pathData="M9,18.4h30v1.6h-30z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/face_spot.xml b/packages/EasterEgg/res/drawable/face_spot.xml
new file mode 100644
index 000000000000..a89fb4fdaadd
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/face_spot.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="face_spot" android:fillColor="#FF000000" android:pathData="M19.5,15.2a4.5,3.2 0,1 0,9 0a4.5,3.2 0,1 0,-9 0z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/food_bits.xml b/packages/EasterEgg/res/drawable/food_bits.xml
new file mode 100644
index 000000000000..1b2bb6f36947
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/food_bits.xml
@@ -0,0 +1,33 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M19.1,34l-3.5,1.3c-1,0.4,-2.2,-0.1,-2.6,-1.1l-1.2,-3c-0.4,-1,0.1,-2.2,1.1,-2.6l3.5,-1.3c1,-0.4,2.2,0.1,2.6,1.1l1.2,3 C20.6,32.4,20.1,33.6,19.1,34z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M25.2,28.1L22.9,28c-0.8,0,-1.5,-0.7,-1.4,-1.6l0.1,-2c0,-0.8,0.7,-1.5,1.6,-1.4l2.4,0.1c0.8,0,1.5,0.7,1.4,1.6l-0.1,2 C26.8,27.5,26.1,28.1,25.2,28.1z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M18.7,23.1L16.5,23c-0.5,0,-0.9,-0.4,-0.8,-0.9l0.1,-2.2c0,-0.5,0.4,-0.9,0.9,-0.8l2.2,0.1c0.5,0,0.9,0.4,0.8,0.9 l-0.1,2.2C19.6,22.8,19.2,23.1,18.7,23.1z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M32.2,35.3l-3.6,-1.8c-1,-0.5,-1.4,-1.7,-0.9,-2.7l1.6,-3.1c0.5,-1,1.7,-1.4,2.7,-0.9l3.6,1.8c1,0.5,1.4,1.7,0.9,2.7 l-1.6,3.1C34.4,35.4,33.2,35.7,32.2,35.3z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/food_chicken.xml b/packages/EasterEgg/res/drawable/food_chicken.xml
new file mode 100644
index 000000000000..95b2fb55b796
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/food_chicken.xml
@@ -0,0 +1,39 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,12v14h10V11H9z M11.7,16.3c-0.7,0,-1.3,-0.6,-1.3,-1.3s0.6,-1.3,1.3,-1.3S13,14.3,13,15S12.4,16.3,11.7,16.3z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M5.7,20.1l1.6,-3.0l-1.6,-3.0l4.4,3.0z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M19.0,6.0l-2.3,2.3l-2.7,-2.6l-2.7,2.6l-2.3,-2.3l0.0,4.0l10.0,0.0z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M9,25c0,8.3,6.7,15,15,15s15,-6.7,15,-15H9z M29.9,31.5h-11v-1h12L29.9,31.5z M31.9,29.5h-13v-1h14L31.9,29.5z M33.9,27.5 h-15v-1h16L33.9,27.5z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M27.0,38.6h2.0v6.0h-2.0z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M17.4,44.6l-2.1999998,0.0l4.4000006,-6.0l2.1999989,0.0z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/food_dish.xml b/packages/EasterEgg/res/drawable/food_dish.xml
new file mode 100644
index 000000000000..3fff6a90fad2
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/food_dish.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M24,13.8C11.3,13.8,1,18.3,1,24c0,5.7,10.3,10.2,23,10.2S47,29.7,47,24C47,18.3,36.7,13.8,24,13.8z M33.7,26.6 c1.1,-0.6,1.8,-1.3,1.8,-2c0,-2.1,-5.2,-3.8,-11.7,-3.8s-11.7,1.7,-11.7,3.8c0,0.6,0.4,1.2,1.2,1.7c-1.7,-0.8,-2.8,-1.7,-2.8,-2.8 c0,-2.5,6,-4.5,13.4,-4.5s13.4,2,13.4,4.5C37.4,24.7,36,25.8,33.7,26.6z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/food_donut.xml b/packages/EasterEgg/res/drawable/food_donut.xml
new file mode 100644
index 000000000000..eaf831ea560c
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/food_donut.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M24,4.5c-10.5,0,-19,8.5,-19,19s8.5,19,19,19s19,-8.5,19,-19S34.5,4.5,24,4.5z M35.2,15.5l1.6,-1.1 c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1c0.2,0.3,0.1,0.6,-0.1,0.8l-1.6,1.1c-0.3,0.2,-0.6,0.1,-0.8,-0.1l-0.1,-0.1 C34.9,16.1,35,15.7,35.2,15.5z M32.7,10.7c0,-0.3,0.3,-0.5,0.6,-0.5l0.1,0c0.3,0,0.5,0.3,0.5,0.6l-0.2,2c0,0.3,-0.3,0.5,-0.6,0.5l-0.1,0 c-0.3,0,-0.5,-0.3,-0.5,-0.6L32.7,10.7z M31.7,15.1l1.5,-0.2c0.2,0,0.5,0.1,0.5,0.4l0,0.1c0,0.2,-0.1,0.5,-0.4,0.5l-1.5,0.2 c-0.2,0,-0.5,-0.1,-0.5,-0.4l0,-0.1C31.3,15.4,31.5,15.2,31.7,15.1z M28.8,10.6l1.6,-1.1c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1 c0.2,0.3,0.1,0.6,-0.1,0.8l-1.6,1.1c-0.3,0.2,-0.6,0.1,-0.8,-0.1l-0.1,-0.1C28.4,11.1,28.5,10.8,28.8,10.6z M25.8,6 c0,-0.3,0.3,-0.5,0.6,-0.5l0.1,0c0.3,0,0.5,0.3,0.5,0.6l-0.2,2c0,0.3,-0.3,0.5,-0.6,0.5l-0.1,0c-0.3,0,-0.5,-0.3,-0.5,-0.6L25.8,6z M20.7,6.5l1.9,-0.7c0.3,-0.1,0.6,0,0.7,0.3l0,0.1c0.1,0.3,0,0.6,-0.3,0.7l-1.9,0.7c-0.3,0.1,-0.6,0,-0.7,-0.3l0,-0.1 C20.3,6.9,20.4,6.6,20.7,6.5z M19.9,10.9l1.5,-0.2c0.2,0,0.5,0.1,0.5,0.4l0,0.1c0,0.2,-0.1,0.5,-0.4,0.5l-1.5,0.2 c-0.2,0,-0.5,-0.1,-0.5,-0.4l0,-0.1C19.5,11.1,19.7,10.9,19.9,10.9z M16,10.9L16,10.9c0.2,-0.3,0.4,-0.4,0.6,-0.3l1.3,0.7 c0.2,0.1,0.3,0.4,0.2,0.6L18,12c-0.1,0.2,-0.4,0.3,-0.6,0.2l-1.3,-0.7C15.9,11.4,15.8,11.1,16,10.9z M15.8,18.5c0.2,0,0.4,0.1,0.5,0.4 l0,0.1c0,0.2,-0.1,0.4,-0.4,0.5l-1.5,0.2c-0.2,0,-0.4,-0.1,-0.5,-0.4l0,-0.1c0,-0.2,0.1,-0.4,0.4,-0.5L15.8,18.5z M14,21.8l-1.6,1.1 c-0.3,0.2,-0.6,0.1,-0.8,-0.1l-0.1,-0.1c-0.2,-0.3,-0.1,-0.6,0.1,-0.8l1.6,-1.1c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1 C14.3,21.3,14.3,21.6,14,21.8z M12.4,12L12.4,12c0.3,-0.2,0.5,-0.2,0.7,-0.1l1,1.1c0.2,0.2,0.2,0.4,0,0.6L14,13.7 c-0.2,0.2,-0.4,0.2,-0.6,0l-1,-1.1C12.2,12.4,12.2,12.1,12.4,12z M8.3,24.5c0,0.3,-0.3,0.5,-0.6,0.5l-0.1,0c-0.3,0,-0.5,-0.3,-0.5,-0.6 l0.2,-2c0,-0.3,0.3,-0.5,0.6,-0.5l0.1,0c0.3,0,0.5,0.3,0.5,0.6L8.3,24.5z M8.5,16.2v-0.1c0,-0.3,0.2,-0.6,0.6,-0.6h2 c0.3,0,0.6,0.2,0.6,0.6v0.1c0,0.3,-0.2,0.6,-0.6,0.6H9C8.7,16.7,8.5,16.5,8.5,16.2z M10.3,20.7c-0.3,0.2,-0.6,0.1,-0.8,-0.1l-0.1,-0.1 c-0.2,-0.3,-0.1,-0.6,0.1,-0.8l1.6,-1.1c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1c0.2,0.3,0.1,0.6,-0.1,0.8L10.3,20.7z M11.3,28.3l0,-0.1 c-0.1,-0.3,0,-0.6,0.3,-0.7l1.9,-0.7c0.3,-0.1,0.6,0,0.7,0.3l0,0.1c0.1,0.3,0,0.6,-0.3,0.7L12,28.6C11.7,28.7,11.4,28.6,11.3,28.3z M14.4,33c0,0.2,-0.2,0.4,-0.4,0.4h-1.5c-0.2,0,-0.4,-0.2,-0.4,-0.4v-0.1c0,-0.2,0.2,-0.4,0.4,-0.4H14c0.2,0,0.4,0.2,0.4,0.4V33z M17.9,35.2 l-1.6,1.1c-0.3,0.2,-0.6,0.1,-0.8,-0.1l-0.1,-0.1c-0.2,-0.3,-0.1,-0.6,0.1,-0.8l1.6,-1.1c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1 C18.2,34.7,18.2,35.1,17.9,35.2z M20.7,33.8l-0.1,0.1c-0.1,0.3,-0.5,0.4,-0.8,0.2l-1.7,-1c-0.3,-0.1,-0.4,-0.5,-0.2,-0.8l0.1,-0.1 c0.1,-0.3,0.5,-0.4,0.8,-0.2l1.7,1C20.7,33.2,20.8,33.5,20.7,33.8z M17.5,23.5c0,-3.6,2.9,-6.5,6.5,-6.5s6.5,2.9,6.5,6.5 c0,3.6,-2.9,6.5,-6.5,6.5S17.5,27.1,17.5,23.5z M27.4,35.7l-1.9,0.7c-0.3,0.1,-0.6,0,-0.7,-0.3l0,-0.1c-0.1,-0.3,0,-0.6,0.3,-0.7l1.9,-0.7 c0.3,-0.1,0.6,0,0.7,0.3l0,0.1C27.9,35.3,27.7,35.6,27.4,35.7z M29.7,32.7l-1.4,0.5c-0.2,0.1,-0.5,0,-0.5,-0.3l0,-0.1 c-0.1,-0.2,0,-0.5,0.3,-0.5l1.4,-0.5c0.2,-0.1,0.5,0,0.5,0.3l0,0.1C30,32.3,29.9,32.6,29.7,32.7z M32.8,35.5l-0.1,0.1 c-0.1,0.3,-0.5,0.4,-0.8,0.2l-1.7,-1c-0.3,-0.1,-0.4,-0.5,-0.2,-0.8l0.1,-0.1c0.1,-0.3,0.5,-0.4,0.8,-0.2l1.7,1C32.8,34.9,32.9,35.2,32.8,35.5z M33.7,30.9c0,0.2,-0.2,0.4,-0.5,0.4l-0.1,0c-0.2,0,-0.4,-0.2,-0.4,-0.5l0.1,-1.5c0,-0.2,0.2,-0.4,0.5,-0.4l0.1,0c0.2,0,0.4,0.2,0.4,0.5 L33.7,30.9z M34.5,26.5l-1.3,0.9c-0.2,0.1,-0.5,0.1,-0.6,-0.1l-0.1,-0.1c-0.1,-0.2,-0.1,-0.5,0.1,-0.6l1.3,-0.9c0.2,-0.1,0.5,-0.1,0.6,0.1 l0.1,0.1C34.8,26.1,34.7,26.3,34.5,26.5z M35.6,20.6l-1.7,-1c-0.3,-0.1,-0.4,-0.5,-0.2,-0.8l0.1,-0.1c0.1,-0.3,0.5,-0.4,0.8,-0.2l1.7,1 c0.3,0.1,0.4,0.5,0.2,0.8l-0.1,0.1C36.2,20.6,35.8,20.7,35.6,20.6z M38.6,27.1l-1.6,1.1c-0.3,0.2,-0.6,0.1,-0.8,-0.1L36.1,28 c-0.2,-0.3,-0.1,-0.6,0.1,-0.8l1.6,-1.1c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1C38.9,26.6,38.8,27,38.6,27.1z M39,19.4l-1.5,0.2 c-0.2,0,-0.5,-0.1,-0.5,-0.4l0,-0.1c0,-0.2,0.1,-0.5,0.4,-0.5l1.5,-0.2c0.2,0,0.5,0.1,0.5,0.4l0,0.1C39.4,19.1,39.2,19.3,39,19.4z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/food_sysuituna.xml b/packages/EasterEgg/res/drawable/food_sysuituna.xml
new file mode 100644
index 000000000000..28cf4a2c7683
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/food_sysuituna.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M46,18.4l-5.8,4.6c-3.9,-3.2,-8.9,-5.6,-14.6,-6.3l1.2,-6l-7.3,5.9C12.5,17.2,6.4,20,2,24.3l7.2,1.4L2,27 c4.3,4.2,10.4,7.1,17.3,7.6l3.1,2.5L22,34.8c7.1,0,13.5,-2.5,18.2,-6.5l5.8,4.6l-1.4,-7.2L46,18.4z M14.3,24.8l-0.6,0.6l-1.1,-1.1 l-1.1,1.1l-0.6,-0.6l1.1,-1.1l-1.1,-1.1l0.6,-0.6l1.1,1.1l1.1,-1.1l0.6,0.6l-1.1,1.1L14.3,24.8z M18.8,29.1c0.7,-0.8,1.1,-2.2,1.1,-3.8 c0,-1.6,-0.4,-3,-1.1,-3.8c1.1,0.5,1.9,2,1.9,3.8S19.9,28.5,18.8,29.1z M20.7,29.1c0.7,-0.8,1.1,-2.2,1.1,-3.8c0,-1.6,-0.4,-3,-1.1,-3.8 c1.1,0.5,1.9,2,1.9,3.8S21.8,28.5,20.7,29.1z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/foot1.xml b/packages/EasterEgg/res/drawable/foot1.xml
new file mode 100644
index 000000000000..0d9085998a18
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/foot1.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="foot1" android:fillColor="#FF000000" android:pathData="M11.5,43m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/foot2.xml b/packages/EasterEgg/res/drawable/foot2.xml
new file mode 100644
index 000000000000..364ba0cd861c
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/foot2.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="foot2" android:fillColor="#FF000000" android:pathData="M18.5,43m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/foot3.xml b/packages/EasterEgg/res/drawable/foot3.xml
new file mode 100644
index 000000000000..e3a512a2568d
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/foot3.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="foot3" android:fillColor="#FF000000" android:pathData="M29.5,43m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/foot4.xml b/packages/EasterEgg/res/drawable/foot4.xml
new file mode 100644
index 000000000000..66b78fa26649
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/foot4.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="foot4" android:fillColor="#FF000000" android:pathData="M36.5,43m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/head.xml b/packages/EasterEgg/res/drawable/head.xml
new file mode 100644
index 000000000000..df600a8613cd
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/head.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="head" android:fillColor="#FF000000" android:pathData="M9,18.5c0,-8.3 6.8,-15 15,-15s15,6.7 15,15H9z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/ic_close.xml b/packages/EasterEgg/res/drawable/ic_close.xml
new file mode 100644
index 000000000000..60ea36b11fcc
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/ic_close.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/ic_share.xml b/packages/EasterEgg/res/drawable/ic_share.xml
new file mode 100644
index 000000000000..8cebc7ed46de
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/ic_share.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M18.0,16.08c-0.76,0.0 -1.4,0.3 -1.9,0.77L8.91,12.7c0.05,-0.2 0.09,-0.4 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.5,0.5 1.2,0.81 2.0,0.81 1.66,0.0 3.0,-1.34 3.0,-3.0s-1.34,-3.0 -3.0,-3.0 -3.0,1.34 -3.0,3.0c0.0,0.2 0.0,0.4 0.0,0.7L8.04,9.81C7.5,9.31 6.79,9.0 6.0,9.0c-1.66,0.0 -3.0,1.34 -3.0,3.0s1.34,3.0 3.0,3.0c0.79,0.0 1.5,-0.31 2.04,-0.81l7.12,4.16c0.0,0.21 0.0,0.43 0.0,0.65 0.0,1.61 1.31,2.92 2.92,2.92 1.61,0.0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/icon.xml b/packages/EasterEgg/res/drawable/icon.xml
new file mode 100644
index 000000000000..defa83a9b5c6
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/icon.xml
@@ -0,0 +1,37 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="512dp"
+ android:height="512dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF7E5BBF"
+ android:pathData="M32.0,12.5l0.0,28.0l12.0,-5.0l0.0,-28.0z"/>
+ <path
+ android:fillColor="#FF7E5BBF"
+ android:pathData="M4.0,40.5l12.0,-5.0l0.0,-11.0l-12.0,-12.0z"/>
+ <path
+ android:fillColor="#40000000"
+ android:pathData="M44.0,35.5l-12.0,-12.0l0.0,-4.0z"/>
+ <path
+ android:fillColor="#40000000"
+ android:pathData="M4.0,12.5l12.0,12.0l0.0,4.0z"/>
+ <path
+ android:fillColor="#FF55C4F5"
+ android:pathData="M32.0,23.5l-16.0,-16.0l-12.0,5.0l0.0,0.0l12.0,12.0l16.0,16.0l12.0,-5.0l0.0,0.0z"/>
+</vector>
+
diff --git a/packages/EasterEgg/res/drawable/left_ear.xml b/packages/EasterEgg/res/drawable/left_ear.xml
new file mode 100644
index 000000000000..2b98736df039
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/left_ear.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="left_ear" android:fillColor="#FF000000" android:pathData="M15.4,1l5.1000004,5.3l-6.3,2.8000002z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/left_ear_inside.xml b/packages/EasterEgg/res/drawable/left_ear_inside.xml
new file mode 100644
index 000000000000..1d947edc31e2
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/left_ear_inside.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="left_ear_inside" android:fillColor="#FF000000" android:pathData="M15.4,1l3.5,6.2l-4.7,1.9z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/left_eye.xml b/packages/EasterEgg/res/drawable/left_eye.xml
new file mode 100644
index 000000000000..4dde1b661393
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/left_eye.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="left_eye" android:fillColor="#FF000000" android:pathData="M20.5,11c0,1.7 -3,1.7 -3,0C17.5,9.3 20.5,9.3 20.5,11z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/leg1.xml b/packages/EasterEgg/res/drawable/leg1.xml
new file mode 100644
index 000000000000..625733318e72
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/leg1.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="leg1" android:fillColor="#FF000000" android:pathData="M9,38h5v5h-5z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/leg2.xml b/packages/EasterEgg/res/drawable/leg2.xml
new file mode 100644
index 000000000000..73352f69e80a
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/leg2.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="leg2" android:fillColor="#FF000000" android:pathData="M16,38h5v5h-5z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/leg2_shadow.xml b/packages/EasterEgg/res/drawable/leg2_shadow.xml
new file mode 100644
index 000000000000..77f4893194fe
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/leg2_shadow.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="leg2_shadow" android:fillColor="#FF000000" android:pathData="M16,38h5v1h-5z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/leg3.xml b/packages/EasterEgg/res/drawable/leg3.xml
new file mode 100644
index 000000000000..53dea5c2becf
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/leg3.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="leg3" android:fillColor="#FF000000" android:pathData="M27,38h5v5h-5z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/leg4.xml b/packages/EasterEgg/res/drawable/leg4.xml
new file mode 100644
index 000000000000..f2ce73e195a2
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/leg4.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="leg4" android:fillColor="#FF000000" android:pathData="M34,38h5v5h-5z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/mouth.xml b/packages/EasterEgg/res/drawable/mouth.xml
new file mode 100644
index 000000000000..ddcf2e82f976
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/mouth.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="mouth"
+ android:strokeColor="#FF000000"
+ android:strokeWidth="1.2"
+ android:strokeLineCap="round"
+ android:pathData="M29,14.3c-0.4,0.8 -1.3,1.4 -2.3,1.4c-1.4,0 -2.7,-1.3 -2.7,-2.7
+ M24,13c0,1.5 -1.2,2.7 -2.7,2.7c-1,0 -1.9,-0.5 -2.3,-1.4"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/nose.xml b/packages/EasterEgg/res/drawable/nose.xml
new file mode 100644
index 000000000000..d403cd1baadf
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/nose.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="nose" android:fillColor="#FF000000" android:pathData="M25.2,13c0,1.3 -2.3,1.3 -2.3,0S25.2,11.7 25.2,13z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/right_ear.xml b/packages/EasterEgg/res/drawable/right_ear.xml
new file mode 100644
index 000000000000..b9fb4d1c7470
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/right_ear.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="right_ear" android:fillColor="#FF000000" android:pathData="M32.6,1l-5.0999985,5.3l6.299999,2.8000002z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/right_ear_inside.xml b/packages/EasterEgg/res/drawable/right_ear_inside.xml
new file mode 100644
index 000000000000..86b6e3428d1f
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/right_ear_inside.xml
@@ -0,0 +1,23 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+
+ <path android:name="right_ear_inside" android:fillColor="#FF000000" android:pathData="M33.8,9.1l-4.7,-1.9l3.5,-6.2z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/right_eye.xml b/packages/EasterEgg/res/drawable/right_eye.xml
new file mode 100644
index 000000000000..a1871a62c25b
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/right_eye.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="right_eye" android:fillColor="#FF000000" android:pathData="M30.5,11c0,1.7 -3,1.7 -3,0C27.5,9.3 30.5,9.3 30.5,11z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/stat_icon.xml b/packages/EasterEgg/res/drawable/stat_icon.xml
new file mode 100644
index 000000000000..608cb2017c3f
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/stat_icon.xml
@@ -0,0 +1,30 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M12,2C6.5,2 2,6.5 2,12c0,5.5 4.5,10 10,10s10,-4.5 10,-10C22,6.5 17.5,2 12,2zM5.5,11c0,-1.6 3,-1.6 3,0C8.5,12.7 5.5,12.7 5.5,11zM17.5,14.6c-0.6,1 -1.7,1.7 -2.9,1.7c-1.1,0 -2,-0.6 -2.6,-1.4c-0.6,0.9 -1.6,1.4 -2.7,1.4c-1.3,0 -2.3,-0.7 -2.9,-1.8c-0.2,-0.3 0,-0.7 0.3,-0.8c0.3,-0.2 0.7,0 0.8,0.3c0.3,0.7 1,1.1 1.8,1.1c0.9,0 1.6,-0.5 1.9,-1.3c-0.2,-0.2 -0.4,-0.4 -0.4,-0.7c0,-1.3 2.3,-1.3 2.3,0c0,0.3 -0.2,0.6 -0.4,0.7c0.3,0.8 1.1,1.3 1.9,1.3c0.8,0 1.5,-0.6 1.8,-1.1c0.2,-0.3 0.6,-0.4 0.9,-0.2C17.6,13.9 17.7,14.3 17.5,14.6zM15.5,11c0,-1.6 3,-1.6 3,0C18.5,12.7 15.5,12.7 15.5,11z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M5.2,1.0l4.1000004,4.2l-5.0,2.1000004z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M18.8,1.0l-4.0999994,4.2l5.000001,2.1000004z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/tail.xml b/packages/EasterEgg/res/drawable/tail.xml
new file mode 100644
index 000000000000..0cca23c3e16c
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/tail.xml
@@ -0,0 +1,26 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="tail"
+ android:strokeColor="#FF000000"
+ android:strokeWidth="5"
+ android:strokeLineCap="round"
+ android:pathData="M35,35.5h5.9c2.1,0 3.8,-1.7 3.8,-3.8v-6.2"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/tail_cap.xml b/packages/EasterEgg/res/drawable/tail_cap.xml
new file mode 100644
index 000000000000..b82f6f9b478a
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/tail_cap.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="tail_cap" android:fillColor="#FF000000" android:pathData="M42.2,25.5c0,-1.4 1.1,-2.5 2.5,-2.5s2.5,1.1 2.5,2.5H42.2z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/tail_shadow.xml b/packages/EasterEgg/res/drawable/tail_shadow.xml
new file mode 100644
index 000000000000..bb1ff12b3afe
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/tail_shadow.xml
@@ -0,0 +1,22 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path android:name="tail_shadow" android:fillColor="#FF000000" android:pathData="M40,38l0,-5l-1,0l0,5z"/>
+</vector>
diff --git a/packages/EasterEgg/res/layout/cat_view.xml b/packages/EasterEgg/res/layout/cat_view.xml
new file mode 100644
index 000000000000..82ced2f240b5
--- /dev/null
+++ b/packages/EasterEgg/res/layout/cat_view.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the specific language governing
+ permissions and limitations under the License.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:gravity="center_horizontal"
+ android:clipToPadding="false">
+
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:scaleType="fitCenter" />
+
+ <LinearLayout
+ android:id="@+id/contextGroup"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="invisible"
+ android:layout_gravity="bottom">
+
+ <ImageView
+ android:id="@android:id/shareText"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:padding="8dp"
+ android:src="@drawable/ic_share"
+ android:scaleType="fitCenter"
+ android:background="#40000000"/>
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <ImageView
+ android:id="@android:id/closeButton"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:padding="4dp"
+ android:src="@drawable/ic_close"
+ android:scaleType="fitCenter"
+ android:background="#40000000"/>
+
+ </LinearLayout>
+
+ </FrameLayout>
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceListItem"
+ android:gravity="center"/>
+</LinearLayout>
+
diff --git a/packages/EasterEgg/res/layout/edit_text.xml b/packages/EasterEgg/res/layout/edit_text.xml
new file mode 100644
index 000000000000..9f7ac802bad4
--- /dev/null
+++ b/packages/EasterEgg/res/layout/edit_text.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the specific language governing
+ permissions and limitations under the License.
+ -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingStart="20dp"
+ android:paddingEnd="20dp">
+
+ <EditText
+ android:id="@android:id/edit"
+ android:maxLines="1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
+</FrameLayout> \ No newline at end of file
diff --git a/packages/EasterEgg/res/layout/food_layout.xml b/packages/EasterEgg/res/layout/food_layout.xml
new file mode 100644
index 000000000000..d0ca0c8899aa
--- /dev/null
+++ b/packages/EasterEgg/res/layout/food_layout.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ except in compliance with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the specific language governing
+ permissions and limitations under the License.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:paddingLeft="4dp" android:paddingRight="4dp"
+ android:paddingBottom="6dp" android:paddingTop="6dp">
+ <ImageView
+ android:layout_width="64dp"
+ android:layout_height="64dp"
+ android:id="@+id/icon"
+ android:tint="?android:attr/colorControlNormal"/>
+ <TextView android:layout_width="64dp" android:layout_height="wrap_content"
+ android:gravity="top|center_horizontal"
+ android:id="@+id/text" />
+</LinearLayout>
diff --git a/packages/EasterEgg/res/layout/neko_activity.xml b/packages/EasterEgg/res/layout/neko_activity.xml
new file mode 100644
index 000000000000..21a4600bae40
--- /dev/null
+++ b/packages/EasterEgg/res/layout/neko_activity.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/holder"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"/>
+</FrameLayout> \ No newline at end of file
diff --git a/packages/EasterEgg/res/values/strings.xml b/packages/EasterEgg/res/values/strings.xml
new file mode 100644
index 000000000000..a2440c7bc786
--- /dev/null
+++ b/packages/EasterEgg/res/values/strings.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <string name="app_name" translatable="false">Android Easter Egg</string>
+ <string name="notification_name" translatable="false">Android Neko</string>
+ <string name="default_tile_name" translatable="false">\????</string>
+ <string name="notification_title" translatable="false">A cat is here.</string>
+ <string name="default_cat_name" translatable="false">Cat #%s</string>
+ <string name="directory_name" translatable="false">Cats</string>
+ <string-array name="food_names" translatable="false">
+ <item>Empty dish</item>
+ <item>Bits</item>
+ <item>Fish</item>
+ <item>Chicken</item>
+ <item>Treat</item>
+ </string-array>
+ <array name="food_icons">
+ <item>@drawable/food_dish</item>
+ <item>@drawable/food_bits</item>
+ <item>@drawable/food_sysuituna</item>
+ <item>@drawable/food_chicken</item>
+ <item>@drawable/food_donut</item>
+ </array>
+ <integer-array name="food_intervals">
+ <item>0</item>
+ <item>15</item>
+ <item>30</item>
+ <item>60</item>
+ <item>120</item>
+ </integer-array>
+ <integer-array name="food_new_cat_prob">
+ <item>0</item>
+ <item>5</item>
+ <item>35</item>
+ <item>65</item>
+ <item>90</item>
+ </integer-array>
+</resources>
diff --git a/packages/EasterEgg/src/com/android/egg/neko/Cat.java b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
new file mode 100644
index 000000000000..864b20c73fbf
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.egg.neko;
+
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.*;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+import com.android.egg.R;
+
+public class Cat extends Drawable {
+ public static final long[] PURR = {0, 40, 20, 40, 20, 40, 20, 40, 20, 40, 20, 40};
+
+ private Random mNotSoRandom;
+ private Bitmap mBitmap;
+ private long mSeed;
+ private String mName;
+ private int mBodyColor;
+
+ private synchronized Random notSoRandom(long seed) {
+ if (mNotSoRandom == null) {
+ mNotSoRandom = new Random();
+ mNotSoRandom.setSeed(seed);
+ }
+ return mNotSoRandom;
+ }
+
+ public static final float frandrange(Random r, float a, float b) {
+ return (b-a)*r.nextFloat() + a;
+ }
+
+ public static final Object choose(Random r, Object...l) {
+ return l[r.nextInt(l.length)];
+ }
+
+ public static final int chooseP(Random r, int[] a) {
+ int pct = r.nextInt(1000);
+ final int stop = a.length-2;
+ int i=0;
+ while (i<stop) {
+ pct -= a[i];
+ if (pct < 0) break;
+ i+=2;
+ }
+ return a[i+1];
+ }
+
+ public static final int[] P_BODY_COLORS = {
+ 180, 0xFF212121, // black
+ 180, 0xFFFFFFFF, // white
+ 140, 0xFF616161, // gray
+ 140, 0xFF795548, // brown
+ 100, 0xFF90A4AE, // steel
+ 100, 0xFFFFF9C4, // buff
+ 100, 0xFFFF8F00, // orange
+ 5, 0xFF29B6F6, // blue..?
+ 5, 0xFFFFCDD2, // pink!?
+ 5, 0xFFCE93D8, // purple?!?!?
+ 4, 0xFF43A047, // yeah, why not green
+ 1, 0, // ?!?!?!
+ };
+
+ public static final int[] P_COLLAR_COLORS = {
+ 250, 0xFFFFFFFF,
+ 250, 0xFF000000,
+ 250, 0xFFF44336,
+ 50, 0xFF1976D2,
+ 50, 0xFFFDD835,
+ 50, 0xFFFB8C00,
+ 50, 0xFFF48FB1,
+ 50, 0xFF4CAF50,
+ };
+
+ public static final int[] P_BELLY_COLORS = {
+ 750, 0,
+ 250, 0xFFFFFFFF,
+ };
+
+ public static final int[] P_DARK_SPOT_COLORS = {
+ 700, 0,
+ 250, 0xFF212121,
+ 50, 0xFF6D4C41,
+ };
+
+ public static final int[] P_LIGHT_SPOT_COLORS = {
+ 700, 0,
+ 300, 0xFFFFFFFF,
+ };
+
+ private CatParts D;
+
+ public static void tint(int color, Drawable ... ds) {
+ for (Drawable d : ds) {
+ if (d != null) {
+ d.mutate().setTint(color);
+ }
+ }
+ }
+
+ public static boolean isDark(int color) {
+ final int r = (color & 0xFF0000) >> 16;
+ final int g = (color & 0x00FF00) >> 8;
+ final int b = color & 0x0000FF;
+ return (r + g + b) < 0x80;
+ }
+
+ public Cat(Context context, long seed) {
+ D = new CatParts(context);
+ mSeed = seed;
+
+ setName(context.getString(R.string.default_cat_name,
+ String.valueOf(mSeed).substring(0, 3)));
+
+ final Random nsr = notSoRandom(seed);
+
+ // body color
+ mBodyColor = chooseP(nsr, P_BODY_COLORS);
+ if (mBodyColor == 0) mBodyColor = Color.HSVToColor(new float[] {
+ nsr.nextFloat()*360f, frandrange(nsr,0.5f,1f), frandrange(nsr,0.5f, 1f)});
+
+ tint(mBodyColor, D.body, D.head, D.leg1, D.leg2, D.leg3, D.leg4, D.tail,
+ D.leftEar, D.rightEar, D.foot1, D.foot2, D.foot3, D.foot4, D.tailCap);
+ tint(0x20000000, D.leg2Shadow, D.tailShadow);
+ if (isDark(mBodyColor)) {
+ tint(0xFFFFFFFF, D.leftEye, D.rightEye, D.mouth, D.nose);
+ }
+ tint(isDark(mBodyColor) ? 0xFFEF9A9A : 0x20D50000, D.leftEarInside, D.rightEarInside);
+
+ tint(chooseP(nsr, P_BELLY_COLORS), D.belly);
+ tint(chooseP(nsr, P_BELLY_COLORS), D.back);
+ final int faceColor = chooseP(nsr, P_BELLY_COLORS);
+ tint(faceColor, D.faceSpot);
+ if (!isDark(faceColor)) {
+ tint(0xFF000000, D.mouth, D.nose);
+ }
+
+ if (nsr.nextFloat() < 0.25f) {
+ tint(0xFFFFFFFF, D.foot1, D.foot2, D.foot3, D.foot4);
+ } else {
+ if (nsr.nextFloat() < 0.25f) {
+ tint(0xFFFFFFFF, D.foot1, D.foot2);
+ } else if (nsr.nextFloat() < 0.25f) {
+ tint(0xFFFFFFFF, D.foot3, D.foot4);
+ } else if (nsr.nextFloat() < 0.1f) {
+ tint(0xFFFFFFFF, (Drawable) choose(nsr, D.foot1, D.foot2, D.foot3, D.foot4));
+ }
+ }
+
+ tint(nsr.nextFloat() < 0.333f ? 0xFFFFFFFF : mBodyColor, D.tailCap);
+
+ final int capColor = chooseP(nsr, isDark(mBodyColor) ? P_LIGHT_SPOT_COLORS : P_DARK_SPOT_COLORS);
+ tint(capColor, D.cap);
+ //tint(chooseP(nsr, isDark(bodyColor) ? P_LIGHT_SPOT_COLORS : P_DARK_SPOT_COLORS), D.nose);
+
+ final int collarColor = chooseP(nsr, P_COLLAR_COLORS);
+ tint(collarColor, D.collar);
+ tint((nsr.nextFloat() < 0.1f) ? collarColor : 0, D.bowtie);
+ }
+
+ public static Cat create(Context context) {
+ return new Cat(context, Math.abs(ThreadLocalRandom.current().nextInt()));
+ }
+
+ public Notification.Builder buildNotification(Context context) {
+ final Bundle extras = new Bundle();
+ extras.putString("android.substName", context.getString(R.string.notification_name));
+ final Intent intent = new Intent(Intent.ACTION_MAIN)
+ .setClass(context, NekoLand.class)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return new Notification.Builder(context)
+ .setSmallIcon(Icon.createWithResource(context, R.drawable.stat_icon))
+ .setLargeIcon(createLargeIcon(context))
+ .setColor(getBodyColor())
+ .setPriority(Notification.PRIORITY_LOW)
+ .setContentTitle(context.getString(R.string.notification_title))
+ .setShowWhen(true)
+ .setCategory(Notification.CATEGORY_STATUS)
+ .setContentText(getName())
+ .setContentIntent(PendingIntent.getActivity(context, 0, intent, 0))
+ .setAutoCancel(true)
+ .setVibrate(PURR)
+ .addExtras(extras);
+ }
+
+ public long getSeed() {
+ return mSeed;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final int w = Math.min(canvas.getWidth(), canvas.getHeight());
+ final int h = w;
+
+ if (mBitmap == null || mBitmap.getWidth() != w || mBitmap.getHeight() != h) {
+ mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ final Canvas bitCanvas = new Canvas(mBitmap);
+ slowDraw(bitCanvas, 0, 0, w, h);
+ }
+ canvas.drawBitmap(mBitmap, 0, 0, null);
+ }
+
+ private void slowDraw(Canvas canvas, int x, int y, int w, int h) {
+ for (int i = 0; i < D.drawingOrder.length; i++) {
+ final Drawable d = D.drawingOrder[i];
+ if (d != null) {
+ d.setBounds(x, y, x+w, y+h);
+ d.draw(canvas);
+ }
+ }
+
+ }
+
+ public Bitmap createBitmap(int w, int h) {
+ if (mBitmap != null && mBitmap.getWidth() == w && mBitmap.getHeight() == h) {
+ return mBitmap.copy(mBitmap.getConfig(), true);
+ }
+ Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ slowDraw(new Canvas(result), 0, 0, w, h);
+ return result;
+ }
+
+ public Icon createLargeIcon(Context context) {
+ final Resources res = context.getResources();
+ final int w = res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
+ final int h = res.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
+
+ Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(result);
+ final Paint pt = new Paint();
+ float[] hsv = new float[3];
+ Color.colorToHSV(mBodyColor, hsv);
+ hsv[2] = (hsv[2]>0.5f)
+ ? (hsv[2] - 0.25f)
+ : (hsv[2] + 0.25f);
+ pt.setColor(Color.HSVToColor(hsv));
+ float r = w/2;
+ canvas.drawCircle(r, r, r, pt);
+ int m = w/10;
+
+ slowDraw(canvas, m, m, w-m-m, h-m-m);
+
+ return Icon.createWithBitmap(result);
+ }
+
+ @Override
+ public void setAlpha(int i) {
+
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public void setName(String name) {
+ this.mName = name;
+ }
+
+ public int getBodyColor() {
+ return mBodyColor;
+ }
+
+ public static class CatParts {
+ public Drawable leftEar;
+ public Drawable rightEar;
+ public Drawable rightEarInside;
+ public Drawable leftEarInside;
+ public Drawable head;
+ public Drawable faceSpot;
+ public Drawable cap;
+ public Drawable mouth;
+ public Drawable body;
+ public Drawable foot1;
+ public Drawable leg1;
+ public Drawable foot2;
+ public Drawable leg2;
+ public Drawable foot3;
+ public Drawable leg3;
+ public Drawable foot4;
+ public Drawable leg4;
+ public Drawable tail;
+ public Drawable leg2Shadow;
+ public Drawable tailShadow;
+ public Drawable tailCap;
+ public Drawable belly;
+ public Drawable back;
+ public Drawable rightEye;
+ public Drawable leftEye;
+ public Drawable nose;
+ public Drawable bowtie;
+ public Drawable collar;
+ public Drawable[] drawingOrder;
+
+ public CatParts(Context context) {
+ body = context.getDrawable(R.drawable.body);
+ head = context.getDrawable(R.drawable.head);
+ leg1 = context.getDrawable(R.drawable.leg1);
+ leg2 = context.getDrawable(R.drawable.leg2);
+ leg3 = context.getDrawable(R.drawable.leg3);
+ leg4 = context.getDrawable(R.drawable.leg4);
+ tail = context.getDrawable(R.drawable.tail);
+ leftEar = context.getDrawable(R.drawable.left_ear);
+ rightEar = context.getDrawable(R.drawable.right_ear);
+ rightEarInside = context.getDrawable(R.drawable.right_ear_inside);
+ leftEarInside = context.getDrawable(R.drawable.left_ear_inside);
+ faceSpot = context.getDrawable(R.drawable.face_spot);
+ cap = context.getDrawable(R.drawable.cap);
+ mouth = context.getDrawable(R.drawable.mouth);
+ foot4 = context.getDrawable(R.drawable.foot4);
+ foot3 = context.getDrawable(R.drawable.foot3);
+ foot1 = context.getDrawable(R.drawable.foot1);
+ foot2 = context.getDrawable(R.drawable.foot2);
+ leg2Shadow = context.getDrawable(R.drawable.leg2_shadow);
+ tailShadow = context.getDrawable(R.drawable.tail_shadow);
+ tailCap = context.getDrawable(R.drawable.tail_cap);
+ belly = context.getDrawable(R.drawable.belly);
+ back = context.getDrawable(R.drawable.back);
+ rightEye = context.getDrawable(R.drawable.right_eye);
+ leftEye = context.getDrawable(R.drawable.left_eye);
+ nose = context.getDrawable(R.drawable.nose);
+ collar = context.getDrawable(R.drawable.collar);
+ bowtie = context.getDrawable(R.drawable.bowtie);
+ drawingOrder = getDrawingOrder();
+ }
+ private Drawable[] getDrawingOrder() {
+ return new Drawable[] {
+ collar,
+ leftEar, leftEarInside, rightEar, rightEarInside,
+ head,
+ faceSpot,
+ cap,
+ leftEye, rightEye,
+ nose, mouth,
+ tail, tailCap, tailShadow,
+ foot1, leg1,
+ foot2, leg2,
+ foot3, leg3,
+ foot4, leg4,
+ leg2Shadow,
+ body, belly,
+ bowtie
+ };
+ }
+ }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/Food.java b/packages/EasterEgg/src/com/android/egg/neko/Food.java
new file mode 100644
index 000000000000..5c0f12e2639f
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/neko/Food.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.egg.neko;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+
+import com.android.egg.R;
+
+public class Food {
+ private final int mType;
+
+ private static int[] sIcons;
+ private static String[] sNames;
+
+ public Food(int type) {
+ mType = type;
+ }
+
+ public Icon getIcon(Context context) {
+ if (sIcons == null) {
+ TypedArray icons = context.getResources().obtainTypedArray(R.array.food_icons);
+ sIcons = new int[icons.length()];
+ for (int i = 0; i < sIcons.length; i++) {
+ sIcons[i] = icons.getResourceId(i, 0);
+ }
+ icons.recycle();
+ }
+ return Icon.createWithResource(context, sIcons[mType]);
+ }
+
+ public String getName(Context context) {
+ if (sNames == null) {
+ sNames = context.getResources().getStringArray(R.array.food_names);
+ }
+ return sNames[mType];
+ }
+
+ public long getInterval(Context context) {
+ return context.getResources().getIntArray(R.array.food_intervals)[mType];
+ }
+
+ public int getType() {
+ return mType;
+ }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java b/packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java
new file mode 100644
index 000000000000..88a7968da16c
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.egg.neko;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.util.Log;
+import android.widget.Toast;
+
+public class NekoActivationActivity extends Activity {
+ private void toastUp(String s) {
+ Toast toast = Toast.makeText(this, s, Toast.LENGTH_SHORT);
+ toast.getView().setBackgroundDrawable(null);
+ toast.show();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ final PackageManager pm = getPackageManager();
+ final ComponentName cn = new ComponentName(this, NekoTile.class);
+ if (pm.getComponentEnabledSetting(cn) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+ if (NekoLand.DEBUG) {
+ Log.v("Neko", "Disabling tile.");
+ }
+ pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ toastUp("\uD83D\uDEAB");
+ } else {
+ if (NekoLand.DEBUG) {
+ Log.v("Neko", "Enabling tile.");
+ }
+ pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
+ toastUp("\uD83D\uDC31");
+ }
+ finish();
+ }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java b/packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java
new file mode 100644
index 000000000000..a2ffd3e21887
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.egg.neko;
+
+import android.support.annotation.NonNull;
+import android.app.Dialog;
+import android.content.Context;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.egg.R;
+
+import java.util.ArrayList;
+
+public class NekoDialog extends Dialog {
+
+ private final Adapter mAdapter;
+
+ public NekoDialog(@NonNull Context context) {
+ super(context, android.R.style.Theme_Material_Dialog_NoActionBar);
+ RecyclerView view = new RecyclerView(getContext());
+ mAdapter = new Adapter(getContext());
+ view.setLayoutManager(new GridLayoutManager(getContext(), 2));
+ view.setAdapter(mAdapter);
+ final float dp = context.getResources().getDisplayMetrics().density;
+ final int pad = (int)(16*dp);
+ view.setPadding(pad, pad, pad, pad);
+ setContentView(view);
+ }
+
+ private void onFoodSelected(Food food) {
+ PrefState prefs = new PrefState(getContext());
+ int currentState = prefs.getFoodState();
+ if (currentState == 0 && food.getType() != 0) {
+ NekoService.registerJob(getContext(), food.getInterval(getContext()));
+ }
+ prefs.setFoodState(food.getType());
+ dismiss();
+ }
+
+ private class Adapter extends RecyclerView.Adapter<Holder> {
+
+ private final Context mContext;
+ private final ArrayList<Food> mFoods = new ArrayList<>();
+
+ public Adapter(Context context) {
+ mContext = context;
+ int[] foods = context.getResources().getIntArray(R.array.food_names);
+ // skip food 0, you can't choose it
+ for (int i=1; i<foods.length; i++) {
+ mFoods.add(new Food(i));
+ }
+ }
+
+ @Override
+ public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new Holder(LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.food_layout, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(final Holder holder, int position) {
+ final Food food = mFoods.get(position);
+ ((ImageView) holder.itemView.findViewById(R.id.icon))
+ .setImageIcon(food.getIcon(mContext));
+ ((TextView) holder.itemView.findViewById(R.id.text))
+ .setText(food.getName(mContext));
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onFoodSelected(mFoods.get(holder.getAdapterPosition()));
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return mFoods.size();
+ }
+ }
+
+ public static class Holder extends RecyclerView.ViewHolder {
+
+ public Holder(View itemView) {
+ super(itemView);
+ }
+ }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
new file mode 100644
index 000000000000..e6a41774f3cb
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.egg.neko;
+
+import android.Manifest;
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.media.MediaScannerConnection;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.provider.MediaStore.Images;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnLongClickListener;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.egg.R;
+import com.android.egg.neko.PrefState.PrefsListener;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class NekoLand extends Activity implements PrefsListener {
+ public static boolean DEBUG = false;
+ public static boolean DEBUG_NOTIFICATIONS = false;
+
+ private static final int STORAGE_PERM_REQUEST = 123;
+
+ private static boolean CAT_GEN = false;
+ private PrefState mPrefs;
+ private CatAdapter mAdapter;
+ private Cat mPendingShareCat;
+
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.neko_activity);
+ final ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setLogo(Cat.create(this));
+ actionBar.setDisplayUseLogoEnabled(false);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mPrefs = new PrefState(this);
+ mPrefs.setListener(this);
+ final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.holder);
+ mAdapter = new CatAdapter();
+ recyclerView.setAdapter(mAdapter);
+ recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
+ updateCats();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mPrefs.setListener(null);
+ }
+
+ private void updateCats() {
+ Cat[] cats;
+ if (CAT_GEN) {
+ cats = new Cat[50];
+ for (int i = 0; i < cats.length; i++) {
+ cats[i] = Cat.create(this);
+ }
+ } else {
+ cats = mPrefs.getCats().toArray(new Cat[0]);
+ }
+ mAdapter.setCats(cats);
+ }
+
+ private void onCatClick(Cat cat) {
+ if (CAT_GEN) {
+ mPrefs.addCat(cat);
+ new AlertDialog.Builder(NekoLand.this)
+ .setTitle("Cat added")
+ .setPositiveButton(android.R.string.ok, null)
+ .show();
+ } else {
+ showNameDialog(cat);
+ }
+// noman.notify(1, cat.buildNotification(NekoLand.this).build());
+ }
+
+ private void onCatRemove(Cat cat) {
+ mPrefs.removeCat(cat);
+ }
+
+ private void showNameDialog(final Cat cat) {
+ Context context = new ContextThemeWrapper(this,
+ android.R.style.Theme_Material_Light_Dialog_NoActionBar);
+ // TODO: Move to XML, add correct margins.
+ View view = LayoutInflater.from(context).inflate(R.layout.edit_text, null);
+ final EditText text = (EditText) view.findViewById(android.R.id.edit);
+ text.setText(cat.getName());
+ text.setSelection(cat.getName().length());
+ Drawable catIcon = cat.createLargeIcon(this).loadDrawable(this);
+ new AlertDialog.Builder(context)
+ .setTitle(" ")
+ .setIcon(catIcon)
+ .setView(view)
+ .setPositiveButton(android.R.string.ok, new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ cat.setName(text.getText().toString().trim());
+ mPrefs.addCat(cat);
+ }
+ }).show();
+ }
+
+ @Override
+ public void onPrefsChanged() {
+ updateCats();
+ }
+
+ private class CatAdapter extends RecyclerView.Adapter<CatHolder> {
+
+ private Cat[] mCats;
+
+ public void setCats(Cat[] cats) {
+ mCats = cats;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public CatHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ return new CatHolder(LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.cat_view, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(final CatHolder holder, int position) {
+ Context context = holder.itemView.getContext();
+ holder.imageView.setImageIcon(mCats[position].createLargeIcon(context));
+ holder.textView.setText(mCats[position].getName());
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onCatClick(mCats[holder.getAdapterPosition()]);
+ }
+ });
+ holder.itemView.setOnLongClickListener(new OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ holder.contextGroup.removeCallbacks((Runnable) holder.contextGroup.getTag());
+ holder.contextGroup.setVisibility(View.VISIBLE);
+ Runnable hideAction = new Runnable() {
+ @Override
+ public void run() {
+ holder.contextGroup.setVisibility(View.INVISIBLE);
+ }
+ };
+ holder.contextGroup.setTag(hideAction);
+ holder.contextGroup.postDelayed(hideAction, 5000);
+ return true;
+ }
+ });
+ holder.delete.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ holder.contextGroup.setVisibility(View.INVISIBLE);
+ holder.contextGroup.removeCallbacks((Runnable) holder.contextGroup.getTag());
+ onCatRemove(mCats[holder.getAdapterPosition()]);
+ }
+ });
+ holder.share.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Cat cat = mCats[holder.getAdapterPosition()];
+ if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ != PackageManager.PERMISSION_GRANTED) {
+ mPendingShareCat = cat;
+ requestPermissions(
+ new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ STORAGE_PERM_REQUEST);
+ return;
+ }
+ shareCat(cat);
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return mCats.length;
+ }
+ }
+
+ private void shareCat(Cat cat) {
+ final File dir = new File(
+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
+ getString(R.string.directory_name));
+ if (!dir.exists() && !dir.mkdirs()) {
+ Log.e("NekoLand", "save: error: can't create Pictures directory");
+ return;
+ }
+ final File png = new File(dir, cat.getName().replaceAll("[/ #:]+", "_") + ".png");
+ Bitmap bitmap = cat.createBitmap(512, 512);
+ if (bitmap != null) {
+ try {
+ OutputStream os = new FileOutputStream(png);
+ bitmap.compress(Bitmap.CompressFormat.PNG, 0, os);
+ os.close();
+ MediaScannerConnection.scanFile(
+ this,
+ new String[] {png.toString()},
+ new String[] {"image/png"},
+ null);
+ Uri uri = Uri.fromFile(png);
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ intent.putExtra(Intent.EXTRA_SUBJECT, cat.getName());
+ intent.setType("image/png");
+ startActivity(Intent.createChooser(intent, null));
+ } catch (IOException e) {
+ Log.e("NekoLand", "save: error: " + e);
+ }
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode,
+ String permissions[], int[] grantResults) {
+ if (requestCode == STORAGE_PERM_REQUEST) {
+ if (mPendingShareCat != null) {
+ shareCat(mPendingShareCat);
+ mPendingShareCat = null;
+ }
+ }
+ }
+
+ private static class CatHolder extends RecyclerView.ViewHolder {
+ private final ImageView imageView;
+ private final TextView textView;
+ private final View contextGroup;
+ private final View delete;
+ private final View share;
+
+ public CatHolder(View itemView) {
+ super(itemView);
+ imageView = (ImageView) itemView.findViewById(android.R.id.icon);
+ textView = (TextView) itemView.findViewById(android.R.id.title);
+ contextGroup = itemView.findViewById(R.id.contextGroup);
+ delete = itemView.findViewById(android.R.id.closeButton);
+ share = itemView.findViewById(android.R.id.shareText);
+ }
+ }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLockedActivity.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLockedActivity.java
new file mode 100644
index 000000000000..5f01da879ebb
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoLockedActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.egg.neko;
+
+import android.support.annotation.Nullable;
+import android.app.Activity;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnDismissListener;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+public class NekoLockedActivity extends Activity implements OnDismissListener {
+
+ private NekoDialog mDialog;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
+
+ mDialog = new NekoDialog(this);
+ mDialog.setOnDismissListener(this);
+ mDialog.show();
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ finish();
+ }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
new file mode 100644
index 000000000000..1ee385136f47
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.egg.neko;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import java.util.List;
+import android.util.Log;
+
+import com.android.egg.R;
+
+import java.util.Random;
+
+public class NekoService extends JobService {
+
+ private static final String TAG = "NekoService";
+
+ public static int JOB_ID = 42;
+
+ public static int CAT_NOTIFICATION = 1;
+
+ public static float CAT_CAPTURE_PROB = 1.0f; // generous
+
+ public static long SECONDS = 1000;
+ public static long MINUTES = 60 * SECONDS;
+
+ public static long INTERVAL_FLEX = 5 * MINUTES;
+
+ public static float INTERVAL_JITTER_FRAC = 0.25f;
+
+ @Override
+ public boolean onStartJob(JobParameters params) {
+ Log.v(TAG, "Starting job: " + String.valueOf(params));
+
+ NotificationManager noman = getSystemService(NotificationManager.class);
+ if (NekoLand.DEBUG_NOTIFICATIONS) {
+ final Bundle extras = new Bundle();
+ extras.putString("android.substName", getString(R.string.notification_name));
+ final int size = getResources()
+ .getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
+ final Cat cat = Cat.create(this);
+ final Notification.Builder builder
+ = cat.buildNotification(this)
+ .setContentTitle("DEBUG")
+ .setContentText("Ran job: " + params);
+ noman.notify(1, builder.build());
+ }
+
+ final PrefState prefs = new PrefState(this);
+ int food = prefs.getFoodState();
+ if (food != 0) {
+ prefs.setFoodState(0); // nom
+ final Random rng = new Random();
+ if (rng.nextFloat() <= CAT_CAPTURE_PROB) {
+ Cat cat;
+ List<Cat> cats = prefs.getCats();
+ final int[] probs = getResources().getIntArray(R.array.food_new_cat_prob);
+ final float new_cat_prob = (float)((food < probs.length) ? probs[food] : 50) / 100f;
+
+ if (cats.size() == 0 || rng.nextFloat() <= new_cat_prob) {
+ cat = Cat.create(this);
+ prefs.addCat(cat);
+ Log.v(TAG, "A new cat is here: " + cat.getName());
+ } else {
+ cat = cats.get(rng.nextInt(cats.size()));
+ Log.v(TAG, "A cat has returned: " + cat.getName());
+ }
+
+ final Notification.Builder builder = cat.buildNotification(this);
+ noman.notify(CAT_NOTIFICATION, builder.build());
+ }
+ }
+ cancelJob(this);
+ return false;
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters jobParameters) {
+ return false;
+ }
+
+ public static void registerJob(Context context, long intervalMinutes) {
+ JobScheduler jss = context.getSystemService(JobScheduler.class);
+ jss.cancel(JOB_ID);
+ long interval = intervalMinutes * MINUTES;
+ long jitter = (long)(INTERVAL_JITTER_FRAC * interval);
+ interval += (long)(Math.random() * (2 * jitter)) - jitter;
+ final JobInfo jobInfo = new JobInfo.Builder(JOB_ID,
+ new ComponentName(context, NekoService.class))
+ .setPeriodic(interval, INTERVAL_FLEX)
+ .build();
+
+ Log.v(TAG, "A cat will visit in " + interval + "ms: " + String.valueOf(jobInfo));
+ jss.schedule(jobInfo);
+
+ if (NekoLand.DEBUG_NOTIFICATIONS) {
+ NotificationManager noman = context.getSystemService(NotificationManager.class);
+ noman.notify(500, new Notification.Builder(context)
+ .setSmallIcon(R.drawable.stat_icon)
+ .setContentTitle(String.format("Job scheduled in %d min", (interval / MINUTES)))
+ .setContentText(String.valueOf(jobInfo))
+ .setPriority(Notification.PRIORITY_MIN)
+ .setCategory(Notification.CATEGORY_SERVICE)
+ .setShowWhen(true)
+ .build());
+ }
+ }
+
+ public static void cancelJob(Context context) {
+ JobScheduler jss = context.getSystemService(JobScheduler.class);
+ Log.v(TAG, "Canceling job");
+ jss.cancel(JOB_ID);
+ }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java b/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java
new file mode 100644
index 000000000000..d5e143cade0f
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.egg.neko;
+
+import android.content.Intent;
+import android.service.quicksettings.Tile;
+import android.service.quicksettings.TileService;
+import android.util.Log;
+
+import com.android.egg.neko.PrefState.PrefsListener;
+
+public class NekoTile extends TileService implements PrefsListener {
+
+ private static final String TAG = "NekoTile";
+
+ private PrefState mPrefs;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mPrefs = new PrefState(this);
+ }
+
+ @Override
+ public void onStartListening() {
+ super.onStartListening();
+ mPrefs.setListener(this);
+ updateState();
+ }
+
+ @Override
+ public void onStopListening() {
+ super.onStopListening();
+ mPrefs.setListener(null);
+ }
+
+ @Override
+ public void onPrefsChanged() {
+ updateState();
+ }
+
+ private void updateState() {
+ Tile tile = getQsTile();
+ int foodState = mPrefs.getFoodState();
+ Food food = new Food(foodState);
+ tile.setIcon(food.getIcon(this));
+ tile.setLabel(food.getName(this));
+ tile.setState(foodState != 0 ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
+ tile.updateTile();
+ }
+
+ @Override
+ public void onClick() {
+ if (mPrefs.getFoodState() != 0) {
+ // there's already food loaded, let's empty it
+ mPrefs.setFoodState(0);
+ NekoService.cancelJob(this);
+ } else {
+ // time to feed the cats
+ if (isLocked()) {
+ if (isSecure()) {
+ Log.d(TAG, "startActivityAndCollapse");
+ Intent intent = new Intent(this, NekoLockedActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivityAndCollapse(intent);
+ } else {
+ unlockAndRun(new Runnable() {
+ @Override
+ public void run() {
+ showNekoDialog();
+ }
+ });
+ }
+ } else {
+ showNekoDialog();
+ }
+ }
+ }
+
+ private void showNekoDialog() {
+ Log.d(TAG, "showNekoDialog");
+ showDialog(new NekoDialog(this));
+ }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/PrefState.java b/packages/EasterEgg/src/com/android/egg/neko/PrefState.java
new file mode 100644
index 000000000000..5f54180bc2e0
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/neko/PrefState.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.egg.neko;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class PrefState implements OnSharedPreferenceChangeListener {
+
+ private static final String FILE_NAME = "mPrefs";
+
+ private static final String FOOD_STATE = "food";
+
+ private static final String CAT_KEY_PREFIX = "cat:";
+
+ private final Context mContext;
+ private final SharedPreferences mPrefs;
+ private PrefsListener mListener;
+
+ public PrefState(Context context) {
+ mContext = context;
+ mPrefs = mContext.getSharedPreferences(FILE_NAME, 0);
+ }
+
+ // Can also be used for renaming.
+ public void addCat(Cat cat) {
+ mPrefs.edit()
+ .putString(CAT_KEY_PREFIX + String.valueOf(cat.getSeed()), cat.getName())
+ .commit();
+ }
+
+ public void removeCat(Cat cat) {
+ mPrefs.edit()
+ .remove(CAT_KEY_PREFIX + String.valueOf(cat.getSeed()))
+ .commit();
+ }
+
+ public List<Cat> getCats() {
+ ArrayList<Cat> cats = new ArrayList<>();
+ Map<String, ?> map = mPrefs.getAll();
+ for (String key : map.keySet()) {
+ if (key.startsWith(CAT_KEY_PREFIX)) {
+ long seed = Long.parseLong(key.substring(CAT_KEY_PREFIX.length()));
+ Cat cat = new Cat(mContext, seed);
+ cat.setName(String.valueOf(map.get(key)));
+ cats.add(cat);
+ }
+ }
+ return cats;
+ }
+
+ public int getFoodState() {
+ return mPrefs.getInt(FOOD_STATE, 0);
+ }
+
+ public void setFoodState(int foodState) {
+ mPrefs.edit().putInt(FOOD_STATE, foodState).commit();
+ }
+
+ public void setListener(PrefsListener listener) {
+ mListener = listener;
+ if (mListener != null) {
+ mPrefs.registerOnSharedPreferenceChangeListener(this);
+ } else {
+ mPrefs.unregisterOnSharedPreferenceChangeListener(this);
+ }
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ mListener.onPrefsChanged();
+ }
+
+ public interface PrefsListener {
+ void onPrefsChanged();
+ }
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index a8419bf4cbdf..94d9550f77e4 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1040,10 +1040,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
public void onForegroundProfileSwitch(int newProfileId) {
// Ignore.
}
- });
+ }, TAG);
} catch (RemoteException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ e.rethrowAsRuntimeException();
}
IntentFilter strongAuthTimeoutFilter = new IntentFilter();
diff --git a/packages/MtpDocumentsProvider/res/values-af/strings.xml b/packages/MtpDocumentsProvider/res/values-af/strings.xml
new file mode 100644
index 000000000000..c2c8761146f3
--- /dev/null
+++ b/packages/MtpDocumentsProvider/res/values-af/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="6271216747302322594">"MTP-gasheer"</string>
+ <string name="downloads_app_label" msgid="7120690641874849726">"Aflaaie"</string>
+ <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
+ <string name="accessing_notification_title" msgid="3030133609230917944">"Toegang tot lêers word tans van <xliff:g id="DEVICE_MODEL">%1$s</xliff:g> af verkry"</string>
+ <string name="error_busy_device" msgid="3997316850357386589">"Die ander toestel is besig. Jy kan nie lêers oordra voordat dit beskikbaar is nie."</string>
+ <string name="error_locked_device" msgid="7557872102188356147">"Geen lêers is gevind nie. Die ander toestel is dalk gesluit. Indien wel, ontsluit dit en probeer weer."</string>
+</resources>
diff --git a/packages/MtpDocumentsProvider/res/values-sv/strings.xml b/packages/MtpDocumentsProvider/res/values-sv/strings.xml
new file mode 100644
index 000000000000..26818eb220ce
--- /dev/null
+++ b/packages/MtpDocumentsProvider/res/values-sv/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="6271216747302322594">"MTP-värd"</string>
+ <string name="downloads_app_label" msgid="7120690641874849726">"Nedladdningar"</string>
+ <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
+ <string name="accessing_notification_title" msgid="3030133609230917944">"Åtkomst till filer från <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
+ <string name="error_busy_device" msgid="3997316850357386589">"Den andra enheten är upptagen. Du kan inte överföra filer förrän den är tillgänglig."</string>
+ <string name="error_locked_device" msgid="7557872102188356147">"Inga filer hittades. Den andra enheten kan vara låst. Om den är det låser du upp den och försöker igen."</string>
+</resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index 999d82d592ea..6140428d353f 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -838,9 +838,15 @@ public final class PageContentRepository {
try (ParcelFileDescriptor source = pipe[0]) {
try (ParcelFileDescriptor destination = pipe[1]) {
-
- mRenderer.renderPage(mPageIndex, bitmap.getWidth(), bitmap.getHeight(),
- mRenderSpec.printAttributes, destination);
+ synchronized (mLock) {
+ if (mRenderer != null) {
+ mRenderer.renderPage(mPageIndex, bitmap.getWidth(),
+ bitmap.getHeight(), mRenderSpec.printAttributes,
+ destination);
+ } else {
+ throw new IllegalStateException("Renderer is disconnected");
+ }
+ }
}
BitmapSerializeUtils.readBitmapPixels(bitmap, source);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java
index 42ef10e01158..2f58de531dda 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/AddPrinterActivity.java
@@ -26,6 +26,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
+import android.content.pm.ResolveInfo;
import android.database.DataSetObserver;
import android.net.Uri;
import android.os.Bundle;
@@ -450,20 +451,42 @@ public class AddPrinterActivity extends ListActivity implements AdapterView.OnIt
private class EnabledServicesAdapter extends PrintServiceInfoAdapter {
@Override
public void performAction(@IntRange(from = 0) int position) {
- PrintServiceInfo service = (PrintServiceInfo) getItem(position);
+ Intent intent = getAddPrinterIntent((PrintServiceInfo) getItem(position));
+ if (intent != null) {
+ try {
+ startActivity(intent);
+ } catch (ActivityNotFoundException|SecurityException e) {
+ Log.e(LOG_TAG, "Cannot start add printers activity", e);
+ }
+ }
+ }
+
+ /**
+ * Get the intent used to launch the add printers activity.
+ *
+ * @param service The service the printer should be added for
+ *
+ * @return The intent to launch the activity or null if the activity could not be launched.
+ */
+ private Intent getAddPrinterIntent(@NonNull PrintServiceInfo service) {
String addPrinterActivityName = service.getAddPrintersActivityName();
if (!TextUtils.isEmpty(addPrinterActivityName)) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName(service.getComponentName().getPackageName(),
- addPrinterActivityName));
-
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- Log.e(LOG_TAG, "Cannot start add printers activity", e);
+ addPrinterActivityName));
+
+ List<ResolveInfo> resolvedActivities = getPackageManager().queryIntentActivities(
+ intent, 0);
+ if (!resolvedActivities.isEmpty()) {
+ // The activity is a component name, therefore it is one or none.
+ if (resolvedActivities.get(0).activityInfo.exported) {
+ return intent;
+ }
}
}
+
+ return null;
}
@Override
@@ -494,7 +517,7 @@ public class AddPrinterActivity extends ListActivity implements AdapterView.OnIt
title.setText(service.getResolveInfo().loadLabel(getPackageManager()));
icon.setImageDrawable(service.getResolveInfo().loadIcon(getPackageManager()));
- if (TextUtils.isEmpty(service.getAddPrintersActivityName())) {
+ if (getAddPrinterIntent(service) == null) {
subtitle.setText(getString(R.string.cannot_add_printer));
} else {
subtitle.setText(getString(R.string.select_to_add_printers));
diff --git a/packages/SettingsLib/res/values/colors.xml b/packages/SettingsLib/res/values/colors.xml
index 796273dc36a9..02b7ea6ef7a8 100644
--- a/packages/SettingsLib/res/values/colors.xml
+++ b/packages/SettingsLib/res/values/colors.xml
@@ -17,5 +17,5 @@
<resources>
<color name="disabled_text_color">#66000000</color> <!-- 38% black -->
- <color name="usage_graph_dots">#455A64</color>
+ <color name="usage_graph_dots">@*android:color/tertiary_device_default_settings</color>
</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 89c46d74e710..97121e9d6f6f 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -448,8 +448,6 @@
<string name="allow_mock_location_summary">Allow mock locations</string>
<!-- Setting Checkbox title whether to enable view attribute inspection -->
<string name="debug_view_attributes">Enable view attribute inspection</string>
- <!-- Setting Checkbox summary whether to use DHCP client from Lollipop (Android 5.0) [CHAR LIMIT=130] -->
- <string name="legacy_dhcp_client_summary">Use the DHCP client from Lollipop instead of the new Android DHCP client.</string>
<string name="mobile_data_always_on_summary">Always keep mobile data active, even when Wi\u2011Fi is active (for fast network switching).</string>
<!-- Title of warning dialog about the implications of enabling USB debugging -->
<string name="adb_warning_title">Allow USB debugging?</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index d98f1a4740ad..548ddf8aeb28 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -1,5 +1,6 @@
package com.android.settingslib;
+import android.annotation.ColorInt;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -8,12 +9,14 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.os.BatteryManager;
import android.os.UserManager;
+import android.print.PrintManager;
import com.android.internal.util.UserIcons;
import com.android.settingslib.drawable.UserIconDrawable;
@@ -154,6 +157,14 @@ public class Utils {
return statusString;
}
+ @ColorInt
+ public static int getColorAccent(Context context) {
+ TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.colorAccent});
+ @ColorInt int colorAccent = ta.getColor(0, 0);
+ ta.recycle();
+ return colorAccent;
+ }
+
/**
* Determine whether a package is a "system package", in which case certain things (like
* disabling notifications or disabling the package altogether) should be disallowed.
@@ -175,7 +186,8 @@ public class Utils {
&& sSystemSignature[0].equals(getFirstSignature(pkg)))
|| pkg.packageName.equals(sPermissionControllerPackageName)
|| pkg.packageName.equals(sServicesSystemSharedLibPackageName)
- || pkg.packageName.equals(sSharedSystemSharedLibPackageName);
+ || pkg.packageName.equals(sSharedSystemSharedLibPackageName)
+ || pkg.packageName.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME);
}
private static Signature getFirstSignature(PackageInfo pkg) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
index 8512dca93e62..f4f7986a753d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
@@ -76,6 +76,8 @@ final class GenerationRegistry {
bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
backingStore);
bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
+ bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
+ backingStore.get(index));
if (DEBUG) {
Slog.i(LOG_TAG, "Exported index:" + index + " for key:"
+ SettingsProvider.keyToString(key));
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 809774b2efb4..20b562cdad75 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -439,7 +439,6 @@
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT" />
- <category android:name="com.android.internal.category.PLATLOGO" />
</intent-filter>
</activity>
diff --git a/packages/SystemUI/res/color/notification_guts_buttons.xml b/packages/SystemUI/res/color/notification_guts_buttons.xml
index c211e438174a..3b8d59bae744 100644
--- a/packages/SystemUI/res/color/notification_guts_buttons.xml
+++ b/packages/SystemUI/res/color/notification_guts_buttons.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true"
- android:color="@*android:color/material_deep_teal_500" />
+ android:color="?android:attr/colorAccent" />
<item android:color="@android:color/black"
android:alpha=".54" />
</selector> \ No newline at end of file
diff --git a/packages/SystemUI/res/color/qs_detail_progress_track.xml b/packages/SystemUI/res/color/qs_detail_progress_track.xml
new file mode 100644
index 000000000000..c56382e6047f
--- /dev/null
+++ b/packages/SystemUI/res/color/qs_detail_progress_track.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- I really don't want to define this, but the View that uses this asset uses both the
+ light and dark accent colors. -->
+ <item android:alpha="0.6" android:drawable="@*android:color/accent_device_default_light" />
+</selector>
diff --git a/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml b/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
index 20251c2fedc0..344859c27e34 100644
--- a/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
+++ b/packages/SystemUI/res/color/qs_user_detail_avatar_frame.xml
@@ -17,6 +17,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_activated="true" android:color="@color/current_user_border_color" />
+ <item android:state_activated="true" android:color="?android:attr/colorAccent" />
<item android:color="@android:color/transparent" />
</selector> \ No newline at end of file
diff --git a/packages/SystemUI/res/color/qs_user_detail_name.xml b/packages/SystemUI/res/color/qs_user_detail_name.xml
index 35c7a4fe754b..e262209a82c3 100644
--- a/packages/SystemUI/res/color/qs_user_detail_name.xml
+++ b/packages/SystemUI/res/color/qs_user_detail_name.xml
@@ -17,7 +17,7 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_activated="true" android:color="@color/current_user_border_color" />
+ <item android:state_activated="true" android:color="?android:attr/colorAccent" />
<item android:state_enabled="false" android:color="@color/qs_tile_disabled_color" />
<item android:color="#66ffffff" /> <!-- 40% white -->
</selector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/fab_background.xml b/packages/SystemUI/res/color/screen_pinning_nav_icon_highlight_outer.xml
index 7f23f2b63e41..5370f7afb5f5 100644
--- a/packages/SystemUI/res/drawable/fab_background.xml
+++ b/packages/SystemUI/res/color/screen_pinning_nav_icon_highlight_outer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,11 +13,6 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/fab_ripple">
- <item>
- <shape>
- <solid android:color="@color/fab_shape" />
- </shape>
- </item>
-</ripple>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="0.25" android:color="?android:attr/colorAccent" />
+</selector>
diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
index e901e40fe23d..0c69d89b4709 100644
--- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml
+++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
@@ -15,5 +15,5 @@
~ limitations under the License
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@color/system_primary_color" />
+ <solid android:color="?android:attr/colorPrimary" />
</shape>
diff --git a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
index dc978fe0d48d..24ac0184a551 100644
--- a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
+++ b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
@@ -20,7 +20,7 @@ Copyright (C) 2014 The Android Open Source Project
android:viewportHeight="24.0">
<path
android:pathData="m18.250000,12.000000a6.250000,6.250000 0.000000,1.000000 1.000000,-12.500000 0.000000,6.250000 6.250000,0.000000 1.000000,1.000000 12.500000,0.000000z"
- android:fillColor="@color/system_primary_color" />
+ android:fillColor="?android:attr/colorPrimary" />
<path
android:fillColor="#FFFFFFFF"
android:pathData="M20.000000,8.700000L20.000000,4.000000L15.300000,4.000000L12.000000,0.700000 8.700000,4.000000L4.000000,4.000000L4.000000,8.700000L0.700000,12.000000 4.000000,15.300000L4.000000,20.000000L8.700000,20.000000L12.000000,23.299999 15.300000,20.000000L20.000000,20.000000L20.000000,15.300000L23.299999,12.000000 20.000000,8.700000zM12.000000,18.000000C8.700000,18.000000 6.000000,15.300000 6.000000,12.000000 6.000000,8.700000 8.700000,6.000000 12.000000,6.000000c3.300000,0.000000 6.000000,2.700000 6.000000,6.000000 0.000000,3.300000 -2.700000,6.000000 -6.000000,6.000000zM12.000000,8.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000 0.000000,2.200000 1.800000,4.000000 4.000000,4.000000 2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000 0.000000,-2.200000 -1.800000,-4.000000 -4.000000,-4.000000z"/>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
new file mode 100644
index 000000000000..258bd0f7902e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
@@ -0,0 +1,37 @@
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="18.0dp"
+ android:height="24dp"
+ android:viewportWidth="36.0"
+ android:viewportHeight="36.0">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M6.797,13.334h1.231v1.522H6.797v2.509h-1.62v-2.509H1.101l-0.039-1.157l4.069-7.643h1.666V13.334z
+M2.648,13.334h2.53V8.721L5.137,8.713L4.984,9.148L2.648,13.334z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M16.155,15.836c-0.269,0.439-0.695,0.832-1.282,1.177c-0.587,0.344-1.344,0.517-2.271,0.517
+c-1.151,0-2.098-0.432-2.841-1.294c-0.744-0.862-1.115-1.978-1.115-3.345v-2.36c0-1.367,0.359-2.481,1.077-3.343
+c0.719-0.863,1.643-1.293,2.772-1.293c1.132,0,2.017,0.331,2.649,0.994c0.633,0.663,0.941,1.528,0.924,2.594l-0.021,0.047h-1.545
+c0-0.638-0.171-1.15-0.513-1.538c-0.341-0.389-0.831-0.583-1.469-0.583c-0.674,0-1.217,0.292-1.63,0.877
+c-0.413,0.585-0.619,1.328-0.619,2.229v2.375c0,0.912,0.215,1.662,0.645,2.25c0.431,0.587,0.992,0.881,1.684,0.881
+c0.522,0,0.935-0.068,1.238-0.205c0.304-0.138,0.533-0.305,0.688-0.502v-2.338h-2.041v-1.413h3.668V15.836z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19.366,14.701v-2.232h-2.25v-1.541h2.25V8.695h1.5v2.232h2.256v1.541h-2.256v2.232H19.366z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/notification_header_bg.xml b/packages/SystemUI/res/drawable/notification_header_bg.xml
deleted file mode 100644
index 1f46502591ce..000000000000
--- a/packages/SystemUI/res/drawable/notification_header_bg.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2014 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="?android:attr/colorControlHighlight" >
- <item android:drawable="@color/system_secondary_color"/>
-</ripple> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
index 1bf7d4c95216..8ea9e0639108 100644
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_background_primary.xml
@@ -15,6 +15,6 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
- <solid android:color="@color/system_primary_color"/>
+ <solid android:color="?android:attr/colorPrimary"/>
</shape>
</inset>
diff --git a/packages/SystemUI/res/drawable/qs_customizer_background.xml b/packages/SystemUI/res/drawable/qs_customizer_background.xml
index d90f820f5d4d..12d8016bf6a0 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_background.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_background.xml
@@ -15,5 +15,5 @@
-->
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/qs_detail_transition" />
- <item android:drawable="@color/system_primary_color" />
+ <item android:drawable="?android:attr/colorPrimary" />
</transition>
diff --git a/packages/SystemUI/res/drawable/qs_detail_background.xml b/packages/SystemUI/res/drawable/qs_detail_background.xml
index 692cd441c88d..84c793f6abd6 100644
--- a/packages/SystemUI/res/drawable/qs_detail_background.xml
+++ b/packages/SystemUI/res/drawable/qs_detail_background.xml
@@ -15,5 +15,5 @@ Copyright (C) 2014 The Android Open Source Project
-->
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/qs_detail_transition" />
- <item android:drawable="@color/system_primary_color" />
+ <item android:drawable="?android:attr/colorPrimary" />
</transition> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/quick_header_bg.xml b/packages/SystemUI/res/drawable/quick_header_bg.xml
index d45d673d8bca..920e6f5ef086 100644
--- a/packages/SystemUI/res/drawable/quick_header_bg.xml
+++ b/packages/SystemUI/res/drawable/quick_header_bg.xml
@@ -17,5 +17,5 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight" >
- <item android:drawable="@color/system_primary_color"/>
+ <item android:drawable="?android:attr/colorPrimary"/>
</ripple>
diff --git a/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml b/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml
index 354b8bd7607b..1303bdb00a31 100644
--- a/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml
+++ b/packages/SystemUI/res/drawable/screen_pinning_bg_circ.xml
@@ -19,7 +19,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
- <solid android:color="@color/system_accent_color" />
+ <solid android:color="?android:attr/colorAccent" />
<size
android:height="@dimen/screen_pinning_nav_highlight_size"
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
new file mode 100644
index 000000000000..17a4394ce6df
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
@@ -0,0 +1,37 @@
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="15dp"
+ android:height="20dp"
+ android:viewportWidth="36"
+ android:viewportHeight="36">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M6.797,13.334h1.231v1.522H6.797v2.509h-1.62v-2.509H1.101l-0.039-1.157l4.069-7.643h1.666V13.334z
+M2.648,13.334h2.53V8.721L5.137,8.713L4.984,9.148L2.648,13.334z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M16.155,15.836c-0.269,0.439-0.695,0.832-1.282,1.177c-0.587,0.344-1.344,0.517-2.271,0.517
+c-1.151,0-2.098-0.432-2.841-1.294c-0.744-0.862-1.115-1.978-1.115-3.345v-2.36c0-1.367,0.359-2.481,1.077-3.343
+c0.719-0.863,1.643-1.293,2.772-1.293c1.132,0,2.017,0.331,2.649,0.994c0.633,0.663,0.941,1.528,0.924,2.594l-0.021,0.047h-1.545
+c0-0.638-0.171-1.15-0.513-1.538c-0.341-0.389-0.831-0.583-1.469-0.583c-0.674,0-1.217,0.292-1.63,0.877
+c-0.413,0.585-0.619,1.328-0.619,2.229v2.375c0,0.912,0.215,1.662,0.645,2.25c0.431,0.587,0.992,0.881,1.684,0.881
+c0.522,0,0.935-0.068,1.238-0.205c0.304-0.138,0.533-0.305,0.688-0.502v-2.338h-2.041v-1.413h3.668V15.836z" />
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19.366,14.701v-2.232h-2.25v-1.541h2.25V8.695h1.5v2.232h2.256v1.541h-2.256v2.232H19.366z" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/switchbar_background.xml b/packages/SystemUI/res/drawable/switchbar_background.xml
index 8d97c46f8870..fb59633f3ec3 100644
--- a/packages/SystemUI/res/drawable/switchbar_background.xml
+++ b/packages/SystemUI/res/drawable/switchbar_background.xml
@@ -16,6 +16,6 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
- <item android:drawable="@color/switch_bar_background" />
+ <item android:drawable="?android:attr/colorSecondary" />
</ripple>
diff --git a/packages/SystemUI/res/drawable/volume_dialog_background.xml b/packages/SystemUI/res/drawable/volume_dialog_background.xml
index e98bfb8d09f6..d6adea992456 100644
--- a/packages/SystemUI/res/drawable/volume_dialog_background.xml
+++ b/packages/SystemUI/res/drawable/volume_dialog_background.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
- <solid android:color="@color/system_primary_color" />
+ <solid android:color="?android:attr/colorPrimary" />
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/zen_introduction_message_background.xml b/packages/SystemUI/res/drawable/zen_introduction_message_background.xml
index 352fb57bb2b9..e5b41a3fb44c 100644
--- a/packages/SystemUI/res/drawable/zen_introduction_message_background.xml
+++ b/packages/SystemUI/res/drawable/zen_introduction_message_background.xml
@@ -17,6 +17,6 @@
<corners android:radius="@dimen/borderless_button_radius" />
- <solid android:color="@color/zen_introduction_message_background" />
+ <solid android:color="?android:attr/colorAccent" />
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
index 52cab72df120..69e52c53808d 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
@@ -53,5 +53,6 @@
android:layout_alignParentEnd="true"
android:textSize="14sp"
android:scrollHorizontally="false"
- android:layout_centerVertical="true"/>
+ android:layout_centerVertical="true"
+ android:focusable="true"/>
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
index 5db678958ce1..a3901d084930 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml
@@ -21,4 +21,4 @@
android:padding="@dimen/ksh_item_padding"
android:layout_marginStart="@dimen/ksh_item_margin_start"
android:scaleType="fitXY"
- android:background="@drawable/ksh_key_item_background"/>
+ android:background="@drawable/ksh_key_item_background" />
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
index 31a87730a445..b06f7fc3c69d 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
@@ -23,4 +23,5 @@
android:textColor="@color/ksh_key_item_color"
android:singleLine="true"
android:gravity="center"
- android:textSize="@dimen/ksh_item_text_size"/>
+ android:textSize="@dimen/ksh_item_text_size"
+ android:textAllCaps="true"/>
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index d09c42b8a8c2..e84ed23fbc86 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -26,7 +26,8 @@
android:orientation="vertical"
android:paddingStart="@*android:dimen/notification_content_margin_start"
android:paddingEnd="8dp"
- android:background="@color/notification_guts_bg_color">
+ android:background="@color/notification_guts_bg_color"
+ android:theme="@*android:style/Theme.DeviceDefault.Light">
<!-- header -->
<LinearLayout
@@ -145,8 +146,8 @@
android:focusable="true"
android:background="#00ffffff"
android:progressBackgroundTint="@color/notification_guts_secondary_slider_color"
- android:thumbTint="@color/notification_guts_slider_color"
- android:progressTint="@color/notification_guts_slider_color"
+ android:thumbTint="?android:attr/colorAccent"
+ android:progressTint="?android:attr/colorAccent"
style="@android:style/Widget.Material.SeekBar.Discrete"
android:tickMarkTint="@android:color/black" />
diff --git a/packages/SystemUI/res/layout/screen_pinning_request.xml b/packages/SystemUI/res/layout/screen_pinning_request.xml
index fea45cc099cf..d55ba9445bde 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request.xml
@@ -21,7 +21,8 @@
android:layout_height="wrap_content"
android:gravity="bottom|center_horizontal"
android:layoutDirection="ltr"
- android:orientation="vertical" >
+ android:orientation="vertical"
+ android:theme="@android:style/Theme.DeviceDefault.Light">
<include
android:layout_width="@dimen/screen_pinning_request_width"
@@ -32,7 +33,7 @@
android:id="@+id/spacer"
android:layout_width="@dimen/screen_pinning_request_width"
android:layout_height="18dp"
- android:background="@color/screen_pinning_request_bg" />
+ android:background="?android:attr/colorAccent" />
<include
android:layout_width="@dimen/screen_pinning_request_width"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
index 60112be21175..e3662f17b336 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml
@@ -28,7 +28,7 @@
android:id="@+id/screen_pinning_buttons"
android:layout_width="match_parent"
android:layout_height="@dimen/screen_pinning_request_button_height"
- android:background="@color/screen_pinning_request_bg" >
+ android:background="?android:attr/colorAccent">
<View
android:layout_width="@dimen/screen_pinning_request_side_width"
@@ -42,7 +42,8 @@
android:layout_height="@dimen/screen_pinning_request_button_height"
android:layout_weight="0"
android:paddingStart="@dimen/screen_pinning_request_frame_padding"
- android:paddingEnd="@dimen/screen_pinning_request_frame_padding" >
+ android:paddingEnd="@dimen/screen_pinning_request_frame_padding"
+ android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
<ImageView
android:id="@+id/screen_pinning_back_bg_light"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
index ebad7a4085be..3649ffba91a3 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml
@@ -25,8 +25,8 @@
android:id="@+id/screen_pinning_buttons"
android:layout_height="match_parent"
android:layout_width="@dimen/screen_pinning_request_button_height"
- android:background="@color/screen_pinning_request_bg"
- android:orientation="vertical" >
+ android:background="?android:attr/colorAccent"
+ android:orientation="vertical">
<View
android:layout_height="@dimen/screen_pinning_request_side_width"
@@ -82,7 +82,8 @@
android:id="@+id/screen_pinning_back_group"
android:layout_height="@dimen/screen_pinning_request_button_width"
android:layout_width="@dimen/screen_pinning_request_button_height"
- android:layout_weight="0" >
+ android:layout_weight="0"
+ android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
<ImageView
android:id="@+id/screen_pinning_back_bg_light"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_land_phone.xml b/packages/SystemUI/res/layout/screen_pinning_request_land_phone.xml
index e6c22d477886..ec1699165941 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_land_phone.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_land_phone.xml
@@ -20,7 +20,8 @@
android:layout_height="@dimen/screen_pinning_request_width"
android:layout_width="wrap_content"
android:gravity="right|center_vertical"
- android:orientation="horizontal" >
+ android:orientation="horizontal"
+ android:theme="@android:style/Theme.DeviceDefault.Light">
<include
android:layout_width="360dp"
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml b/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
index df957f42145d..cdad94bd1b22 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
@@ -20,8 +20,8 @@
android:id="@+id/screen_pinning_text_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="@color/screen_pinning_request_bg"
- android:gravity="center_vertical" >
+ android:background="?android:attr/colorAccent"
+ android:gravity="center_vertical">
<TextView
android:id="@+id/screen_pinning_title"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
deleted file mode 100644
index c5cd65ea3cf9..000000000000
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ /dev/null
@@ -1,195 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-** Copyright 2012, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
--->
-
-<!-- Extends RelativeLayout -->
-<com.android.systemui.statusbar.phone.StatusBarHeaderView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/header"
- android:layout_width="@dimen/notification_panel_width"
- android:layout_height="@dimen/status_bar_header_height"
- android:layout_gravity="@integer/notification_panel_layout_gravity"
- android:baselineAligned="false"
- android:elevation="4dp"
- android:background="@drawable/notification_header_bg"
- android:clickable="true"
- android:focusable="true"
- >
-
- <com.android.systemui.statusbar.phone.MultiUserSwitch android:id="@+id/multi_user_switch"
- android:layout_width="@dimen/multi_user_switch_width_collapsed"
- android:layout_height="@dimen/status_bar_header_height"
- android:layout_alignParentEnd="true"
- android:background="@drawable/ripple_drawable" >
- <ImageView android:id="@+id/multi_user_avatar"
- android:layout_width="@dimen/multi_user_avatar_expanded_size"
- android:layout_height="@dimen/multi_user_avatar_expanded_size"
- android:layout_gravity="center"
- android:scaleType="centerInside"/>
- </com.android.systemui.statusbar.phone.MultiUserSwitch>
-
- <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
- android:id="@+id/settings_button_container"
- android:layout_width="48dp"
- android:layout_height="@dimen/status_bar_header_height"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:layout_toStartOf="@id/multi_user_switch">
-
- <com.android.systemui.statusbar.phone.SettingsButton android:id="@+id/settings_button"
- style="@android:style/Widget.Material.Button.Borderless"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@drawable/ripple_drawable"
- android:src="@drawable/ic_settings"
- android:contentDescription="@string/accessibility_desc_settings" />
- <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/tuner_icon"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="36dp"
- android:tint="#4DFFFFFF"
- android:tintMode="src_in"
- android:visibility="invisible"
- android:src="@drawable/tuner" />
-
- </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
-
- <LinearLayout android:id="@+id/system_icons_super_container"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/status_bar_header_height"
- android:layout_toStartOf="@id/multi_user_switch"
- android:layout_alignWithParentIfMissing="true"
- android:layout_marginStart="16dp"
- android:background="@drawable/ripple_drawable"
- android:paddingEnd="4dp" >
- <FrameLayout android:id="@+id/system_icons_container"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/status_bar_height"
- android:layout_gravity="center_vertical"
- >
- <include layout="@layout/system_icons" />
- </FrameLayout>
- <TextView android:id="@+id/battery_level"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_marginStart="@dimen/header_battery_margin_expanded"
- android:paddingEnd="@dimen/battery_level_padding_end"
- android:textColor="#ffffff"
- android:textSize="@dimen/battery_level_text_size"
- android:importantForAccessibility="noHideDescendants"/>
- </LinearLayout>
-
- <TextView
- android:id="@+id/header_emergency_calls_only"
- android:layout_height="@dimen/status_bar_header_height"
- android:layout_width="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_toStartOf="@id/system_icons_super_container"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:visibility="gone"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
- android:text="@*android:string/emergency_calls_only"
- android:singleLine="true"
- android:gravity="center_vertical" />
-
- <FrameLayout
- android:id="@+id/date_group"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/clock_collapsed_bottom_margin"
- android:layout_alignParentBottom="true">
- <com.android.systemui.statusbar.policy.DateView android:id="@+id/date_collapsed"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
- android:layout_below="@id/clock"
- systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm"
- />
-
- <com.android.systemui.statusbar.policy.DateView android:id="@+id/date_expanded"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:singleLine="true"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
- android:layout_below="@id/clock"
- systemui:datePattern="eeeeMMMMd"
- />
- </FrameLayout>
-
- <include layout="@layout/split_clock_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="16dp"
- android:layout_above="@id/date_group"
- android:id="@+id/clock"
- />
-
- <com.android.systemui.statusbar.AlphaOptimizedButton android:id="@+id/alarm_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_toEndOf="@id/date_group"
- android:layout_marginBottom="4dp"
- android:drawablePadding="6dp"
- android:drawableStart="@drawable/ic_access_alarms_small"
- android:textColor="#64ffffff"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
- android:paddingEnd="6dp"
- android:paddingStart="6dp"
- android:paddingTop="16dp"
- android:paddingBottom="16dp"
- android:background="?android:attr/selectableItemBackground"
- android:visibility="gone"
- />
-
- <include
- android:id="@+id/qs_detail_header"
- layout="@layout/qs_detail_header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- />
-
- <com.android.systemui.statusbar.AlphaOptimizedImageView
- android:id="@+id/qs_detail_header_progress"
- android:src="@drawable/indeterminate_anim"
- android:alpha="0"
- android:background="@color/qs_detail_progress_track"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- />
-
- <TextView
- android:id="@+id/header_debug_info"
- android:visibility="invisible"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:fontFamily="sans-serif-condensed"
- android:textSize="11dp"
- android:textStyle="bold"
- android:textColor="#00A040"
- android:padding="2dp"
- />
-
-</com.android.systemui.statusbar.phone.StatusBarHeaderView>
diff --git a/packages/SystemUI/res/layout/switch_bar.xml b/packages/SystemUI/res/layout/switch_bar.xml
index f98de96a66f9..41cdb78392a9 100644
--- a/packages/SystemUI/res/layout/switch_bar.xml
+++ b/packages/SystemUI/res/layout/switch_bar.xml
@@ -22,7 +22,8 @@
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:clickable="true"
- android:gravity="center">
+ android:gravity="center"
+ android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent">
<TextView android:id="@+id/switch_text"
android:layout_height="wrap_content"
@@ -42,7 +43,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:background="@null"
- android:theme="@style/ThemeOverlay.SwitchBar" />
+ android:background="@null" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/tile_listing.xml b/packages/SystemUI/res/layout/tile_listing.xml
deleted file mode 100644
index 9ab62cafe40b..000000000000
--- a/packages/SystemUI/res/layout/tile_listing.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ** Copyright 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.
- -->
-
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/qs_background_primary"
- android:paddingBottom="20dp"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/notification_header_bg"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingTop="10dp"
- android:paddingBottom="10dp"
- android:orientation="horizontal">
- <ImageView
- android:id="@android:id/icon"
- android:layout_width="36dp"
- android:layout_height="36dp" />
- <TextView
- android:id="@android:id/title"
- android:paddingStart="10dp"
- android:textColor="@android:color/white"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical" />
- </LinearLayout>
-
- <GridLayout
- android:id="@+id/tile_grid"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:columnCount="4" />
-
- </LinearLayout>
diff --git a/packages/SystemUI/res/layout/tuner_qs.xml b/packages/SystemUI/res/layout/tuner_qs.xml
deleted file mode 100644
index 9a51e0cbfd32..000000000000
--- a/packages/SystemUI/res/layout/tuner_qs.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
--->
-
-<com.android.systemui.tuner.AutoScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/system_secondary_color" >
- <LinearLayout
- android:id="@+id/all_details"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:gravity="center"
- android:orientation="vertical">
-
- <View
- android:background="@color/qs_tile_divider"
- android:layout_width="match_parent"
- android:layout_height="2dp" />
-
- <FrameLayout
- android:id="@+id/remove_target"
- android:layout_width="105dp"
- android:layout_height="@dimen/qs_tile_height" />
-
- <FrameLayout
- android:id="@+id/add_target"
- android:layout_width="105dp"
- android:layout_height="@dimen/qs_tile_height" />
- </LinearLayout>
-</com.android.systemui.tuner.AutoScrollView>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index d3f2a25a6436..68395cd69890 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -20,16 +20,14 @@
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/volume_dialog_margin_bottom"
android:background="@drawable/volume_dialog_background"
- android:translationZ="4dp"
- android:paddingTop="8dp">
+ android:translationZ="4dp" >
<LinearLayout
android:id="@+id/volume_dialog_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:paddingBottom="8dp"
- android:paddingStart="8dp"
+ android:paddingTop="@dimen/volume_dialog_collapsed_padding_top"
android:animateLayoutChanges="true" >
<!-- volume rows added and removed here! :-) -->
@@ -52,6 +50,8 @@
android:src="@drawable/ic_volume_collapse_animation"
tools:ignore="RtlHardcoded"
android:layout_alignParentEnd="true"
- android:layout_alignParentTop="true"/>
+ android:layout_alignParentTop="true"
+ android:layout_marginTop="@dimen/volume_expander_margin_top"
+ android:layout_marginEnd="@dimen/volume_expander_margin_end"/>
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index be05a3ac259c..a30fc4356a51 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -13,14 +13,16 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<RelativeLayout
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="@dimen/volume_row_height"
android:clipChildren="false"
android:clipToPadding="false"
android:id="@+id/volume_dialog_row"
- android:paddingEnd="@dimen/volume_button_size" >
+ android:paddingEnd="@dimen/volume_dialog_padding_end"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/volume_row_padding_bottom" >
<TextView
android:id="@+id/volume_row_header"
@@ -29,32 +31,28 @@
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.Volume.Header"
- android:paddingBottom="0dp"
- android:paddingEnd="12dp"
- android:paddingStart="12dp"
- android:paddingTop="4dp"
- android:visibility="gone" />
+ android:paddingStart="@dimen/volume_row_header_padding_start" />
- <com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/volume_row_icon"
- style="@style/VolumeButtons"
- android:layout_width="@dimen/volume_button_size"
- android:layout_height="@dimen/volume_button_size"
- android:layout_below="@id/volume_row_header"
- android:soundEffectsEnabled="false" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/volume_row_slider_height"
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/volume_row_padding_start" >
+ <com.android.keyguard.AlphaOptimizedImageButton
+ android:id="@+id/volume_row_icon"
+ style="@style/VolumeButtons"
+ android:layout_width="@dimen/volume_button_size"
+ android:layout_height="@dimen/volume_button_size"
+ android:soundEffectsEnabled="false" />
- <SeekBar
- android:id="@+id/volume_row_slider"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignBottom="@+id/volume_row_icon"
- android:layout_alignWithParentIfMissing="true"
- android:layout_below="@id/volume_row_header"
- android:layout_toEndOf="@id/volume_row_icon"
- android:layout_toStartOf="@+id/volume_settings_button"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:paddingEnd="8dp"
- android:paddingStart="8dp" />
+ <SeekBar
+ android:id="@+id/volume_row_slider"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignWithParentIfMissing="true"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:paddingStart="@dimen/volume_row_slider_padding_start"/>
+ </LinearLayout>
-</RelativeLayout> \ No newline at end of file
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml
index f30023dc8ef4..ea26bba89432 100644
--- a/packages/SystemUI/res/layout/volume_zen_footer.xml
+++ b/packages/SystemUI/res/layout/volume_zen_footer.xml
@@ -78,7 +78,7 @@
android:paddingStart="15dp"
android:paddingEnd="15dp"
android:text="@string/volume_zen_end_now"
- android:textColor="@color/system_accent_color"
+ android:textColor="?android:attr/colorAccent"
android:textAppearance="@style/TextAppearance.QS.DetailButton" />
</com.android.systemui.volume.ZenFooter> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 906b8679931b..c0be6762e4ed 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -40,7 +40,8 @@
android:layout_marginEnd="16dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
- android:background="@drawable/zen_introduction_message_background" >
+ android:background="@drawable/zen_introduction_message_background"
+ android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent.Light">
<ImageView
android:id="@+id/zen_introduction_confirm"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index d9138ef0def1..a3e9852d7bcf 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Swerwing"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Tik om die oorspronklike terug te stel."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Jy gebruik tans jou werkprofiel"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tik om te ontdemp."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tik om op vibreer te stel. Toeganklikheidsdienste kan dalk gedemp wees."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tik om te demp. Toeganklikheidsdienste kan dalk gedemp wees."</string>
diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml
index 6b28cfdd8828..f90c426ebf35 100644
--- a/packages/SystemUI/res/values-af/strings_tv.xml
+++ b/packages/SystemUI/res/values-af/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Dit hou jou video in sig totdat jy \'n ander een speel. Druk en hou "<b>"HOME"</b>" om dit te beheer."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Het dit"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Maak toe"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 69d6642e506f..afe088da317b 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"ኤል ቲ ኢ"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ውሂብን በማዛወር ላይ"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> የድምጽ መጠን መገናኛው ነው"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"የመጀመሪያውን ወደነበረበት ለመመለስ መታ ያድርጉ።"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"የስራ መገለጫዎን እየተጠቀሙ ነው"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s። ድምጸ-ከል ለማድረግ መታ ያድርጉ"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s። ወደ ንዝረት ለማቀናበር መታ ያድርጉ። የተደራሽነት አገልግሎቶች ድምጸ-ከል ሊደረግባቸው ይችላል።"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s። ድምጸ-ከል ለማድረግ መታ ያድርጉ። የተደራሽነት አገልግሎቶች ድምጸ-ከል ሊደረግባቸው ይችላል።"</string>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
index c4a47e3e936d..493ae48fc119 100644
--- a/packages/SystemUI/res/values-am/strings_tv.xml
+++ b/packages/SystemUI/res/values-am/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"ይሄ ሌላ እስኪያጫውቱ ድረስ ቪዲዮዎን በእይታ ውስጥ እንዳለ ያቆየዋል። እሱን ለመቆጣጠር "<b>"መነሻ"</b>"ን ተጭነው ይያዙት።"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ገባኝ"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"አሰናብት"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index d7962de2b2c7..7ef02c14d76e 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -147,6 +147,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"شبكة الجيل الثالث"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"‏شبكة 3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"شبكة الجيل الرابع"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"شبكة الجيل الرابع أو أحدث"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"تجوال"</string>
@@ -442,6 +443,18 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> هو مربع حوار مستوى الصوت"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"انقر لاستعادة النسخة الأصلية."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"أنت تستخدم ملفك الشخصي للعمل"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"الاتصال"</item>
+ <item msgid="5997713001067658559">"النظام"</item>
+ <item msgid="7858983209929864160">"الرنين"</item>
+ <item msgid="1850038478268896762">"الوسائط"</item>
+ <item msgid="8265110906352372092">"المنبه"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"البلوتوث"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"‏%1$s. انقر لإلغاء التجاهل."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"‏%1$s. انقر للتعيين على الاهتزاز. قد يتم تجاهل خدمات إمكانية الوصول."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"‏%1$s. انقر للتجاهل. قد يتم تجاهل خدمات إمكانية الوصول."</string>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
index 081e4e36a409..f8cbe54ae09c 100644
--- a/packages/SystemUI/res/values-ar/strings_tv.xml
+++ b/packages/SystemUI/res/values-ar/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"يؤدي هذا إلى الاحتفاظ بعرض الفيديو إلى أن يتم تشغيل فيديو آخر. اضغط مع الاستمرار على زر "<b>"الشاشة الرئيسية"</b>" للتحكم في هذا الإعداد."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"حسنًا"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"رفض"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index acb58cef039c..a081e0a26eba 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -143,6 +143,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"4G+"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Rominq"</string>
@@ -434,6 +435,18 @@
<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="8819536904234337445">"Orijinalı bərpa etmək üçün tıklayın."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"İş profilinizi istifadə edirsiniz"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Çağrı"</item>
+ <item msgid="5997713001067658559">"Sistem"</item>
+ <item msgid="7858983209929864160">"Zəng"</item>
+ <item msgid="1850038478268896762">"Media"</item>
+ <item msgid="8265110906352372092">"Siqnal"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Səsli etmək üçün tıklayın."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Vibrasiyanı ayarlamaq üçün tıklayın. Əlçatımlılıq xidmətləri səssiz edilmiş ola bilər."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Səssiz etmək üçün tıklayın. Əlçatımlılıq xidmətləri səssiz edilmiş ola bilər."</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
index 6b0a18e8fa69..94e61f15b215 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Digərini oxudana kimi videonuzu görünən edir. Nəzarət etmək üçün "<b>"ƏSAS SƏHİFƏ"</b>" düyməsini basıb saxlayın."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Anladım"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Rədd edin"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 8d7e8da337dc..1a35a1080526 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роуминг"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> изпълнява ролята на диалоговия прозорец за силата на звука"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Докоснете, за да се възстанови първоначалната стойност."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Използвате служебния си потребителски профил"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Докоснете, за да включите отново звука."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Докоснете, за да зададете вибриране. Възможно е звукът на услугите за достъпност да бъде заглушен."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Докоснете, за да заглушите звука. Възможно е звукът на услугите за достъпност да бъде заглушен."</string>
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
index a943261e5816..17038addb208 100644
--- a/packages/SystemUI/res/values-bg/strings_tv.xml
+++ b/packages/SystemUI/res/values-bg/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Видеоклипът ви ще остане видим, докато не пуснете друг. Натиснете и задръжте "<b>"HOME"</b>", за да контролирате функцията."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Разбрах"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Отхвърляне"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index e32fb06ae179..3387d20014fc 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"রোমিং"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> হল ভলিউম ডায়লগ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"আসলটি পুনঃস্থাপন করতে আলতো চাপ দিন৷"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"আপনি আপনার কাজের প্রোফাইল ব্যবহার করছেন"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। সশব্দ করতে আলতো চাপুন।"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। কম্পন এ সেট করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে নিঃশব্দ করা হতে পারে।"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। নিঃশব্দ করতে আলতো চাপুন। অ্যাক্সেসযোগ্যতার পরিষেবাগুলিকে নিঃশব্দ করা হতে পারে।"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings_tv.xml b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
index c61dc83952a0..99eb53739622 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"আপনি অন্য একটি না প্লে করা পর্যন্ত এটি আপনার ভিডিও দেখা বজায় রাখে৷ এটিকে নিয়ন্ত্রণ করতে "<b>"হোম"</b>" টিপুন এবং ধরে রাখুন৷"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"বুঝেছি"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"খারিজ করুন"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 789fdc314776..e351d75f6a38 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Itinerància"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Toca la notificació per restaurar el valor original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estàs utilitzant el perfil professional"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toca per activar el so."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toca per activar la vibració. Pot ser que els serveis d\'accessibilitat se silenciïn."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toca per silenciar el so. Pot ser que els serveis d\'accessibilitat se silenciïn."</string>
diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml
index 0a3e2205c136..bc094a9b7f89 100644
--- a/packages/SystemUI/res/values-ca/strings_tv.xml
+++ b/packages/SystemUI/res/values-ca/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Amb aquesta opció el vídeo continua veient-se fins que en reprodueixes un altre. Mantén premut el botó "<b>"INICI"</b>" per controlar-la."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"D\'acord"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Ignora"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2f5d97ceac84..582dd28ed421 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -72,7 +72,7 @@
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ukládání snímku obrazovky..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"Ukládání snímku obrazovky..."</string>
<string name="screenshot_saving_text" msgid="2419718443411738818">"Probíhá ukládání snímku obrazovky."</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky Snímek obrazovky pořízen."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky pořízen"</string>
<string name="screenshot_saved_text" msgid="2685605830386712477">"Klepnutím zobrazíte snímek obrazovky."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Snímek obrazovky se nepodařilo zachytit."</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Při ukládání snímku obrazovky došlo k problému."</string>
@@ -145,6 +145,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -440,6 +442,12 @@
<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="8819536904234337445">"Klepnutím obnovíte původní nastavení."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Používáte pracovní profil"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Klepnutím zapnete zvuk."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Klepnutím aktivujete režim vibrací. Služby přístupnosti mohou být ztlumeny."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Klepnutím vypnete zvuk. Služby přístupnosti mohou být ztlumeny."</string>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
index 731ff5a4a3e4..459b8bc794bc 100644
--- a/packages/SystemUI/res/values-cs/strings_tv.xml
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Video bude připnuto v zobrazení, dokud nepřehrajete další. Funkci lze ovládat podržením tlačítka "<b>"Plocha"</b>"."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Rozumím"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Zavřít"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 603d1e05b4e3..4f043992f5e2 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Tryk for at gendanne det oprindelige."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du bruger din arbejdsprofil"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tryk for at slå lyden til."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tryk for at konfigurere til at vibrere. Tilgængelighedstjenester kan blive deaktiveret."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tryk for at slå lyden fra. Lyden i tilgængelighedstjenester kan blive slået fra."</string>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
index edafd7c879c9..babb671d6122 100644
--- a/packages/SystemUI/res/values-da/strings_tv.xml
+++ b/packages/SystemUI/res/values-da/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Dette fastholder visningen af din video, indtil du afspiller en anden. Tryk på "<b>"START"</b>", og hold fingeren nede for at styre det."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Afvis"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 47040db054ac..28ab3ba18111 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Tippe, um das Original wiederherzustellen."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du verwendest dein Arbeitsprofil."</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Zum Aufheben der Stummschaltung tippen."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tippen, um Vibrieren festzulegen. Bedienungshilfen werden unter Umständen stummgeschaltet."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Zum Stummschalten tippen. Bedienungshilfen werden unter Umständen stummgeschaltet."</string>
diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml
index 373d26cb2f48..1adf279b168f 100644
--- a/packages/SystemUI/res/values-de/strings_tv.xml
+++ b/packages/SystemUI/res/values-de/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Dein Video wird dir so lange angezeigt, bis du ein anderes ansiehst. Taste "<b>"STARTBILDSCHIRM"</b>" zum Steuern drücken und halten."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Beenden"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 0c3c6ffb79d7..8fcec5a9d97b 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Περιαγωγή"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> αποτελεί το παράθυρο διαλόγου ελέγχου έντασης"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Πατήστε για να επαναφέρετε την αρχική μορφή της εικόνας."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Χρησιμοποιείτε το προφίλ εργασίας σας"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Πατήστε για κατάργηση σίγασης."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Πατήστε για ενεργοποιήσετε τη δόνηση. Οι υπηρεσίες προσβασιμότητας ενδέχεται να τεθούν σε σίγαση."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Πατήστε για σίγαση. Οι υπηρεσίες προσβασιμότητας ενδέχεται να τεθούν σε σίγαση."</string>
diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml
index 655b424180cb..d3d246311ca2 100644
--- a/packages/SystemUI/res/values-el/strings_tv.xml
+++ b/packages/SystemUI/res/values-el/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Αυτό διατηρεί το βίντεό σας σε προβολή έως ότου γίνει αναπαραγωγή κάποιου άλλου. Πατήστε παρατεταμένα το πλήκτρο "<b></b>" (ΑΡΧΙΚΗ ΣΕΛΙΔΑ) για να ελέγξετε αυτήν την επιλογή."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Κατάλαβα"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Παράβλεψη"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 2ede27943e60..35307611e0f6 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -143,6 +143,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"4G+"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +435,18 @@
<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="8819536904234337445">"Tap to restore the original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"You\'re using your work profile"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Call"</item>
+ <item msgid="5997713001067658559">"System"</item>
+ <item msgid="7858983209929864160">"Ring"</item>
+ <item msgid="1850038478268896762">"Media"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tap to unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tap to set to vibrate. Accessibility services may be muted."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tap to mute. Accessibility services may be muted."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
index 730cf74fe239..dff61c0bf802 100644
--- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"This keeps your video in view until you play another one. Press and hold "<b>"HOME"</b>" to control it."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Dismiss"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 2ede27943e60..35307611e0f6 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -143,6 +143,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"4G+"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +435,18 @@
<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="8819536904234337445">"Tap to restore the original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"You\'re using your work profile"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Call"</item>
+ <item msgid="5997713001067658559">"System"</item>
+ <item msgid="7858983209929864160">"Ring"</item>
+ <item msgid="1850038478268896762">"Media"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tap to unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tap to set to vibrate. Accessibility services may be muted."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tap to mute. Accessibility services may be muted."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
index 730cf74fe239..dff61c0bf802 100644
--- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"This keeps your video in view until you play another one. Press and hold "<b>"HOME"</b>" to control it."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Dismiss"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 2ede27943e60..35307611e0f6 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -143,6 +143,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"4G+"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +435,18 @@
<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="8819536904234337445">"Tap to restore the original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"You\'re using your work profile"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Call"</item>
+ <item msgid="5997713001067658559">"System"</item>
+ <item msgid="7858983209929864160">"Ring"</item>
+ <item msgid="1850038478268896762">"Media"</item>
+ <item msgid="8265110906352372092">"Alarm"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tap to unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tap to set to vibrate. Accessibility services may be muted."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tap to mute. Accessibility services may be muted."</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
index 730cf74fe239..dff61c0bf802 100644
--- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"This keeps your video in view until you play another one. Press and hold "<b>"HOME"</b>" to control it."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Dismiss"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index cd08f34aa6a5..051aee9ca9f0 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Presiona para restablecer el original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estás usando tu perfil de trabajo"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Presiona para dejar de silenciar."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Presiona para establecer el modo vibración. Es posible que los servicios de accesibilidad estén silenciados."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Presiona para silenciar. Es posible que los servicios de accesibilidad estén silenciados."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
index 1dfa04c29d1a..9703b75806e0 100644
--- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Mantiene el video a la vista hasta que reproduzcas otro. Mantén presionado "<b>"INICIO"</b>" para controlar la función."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Entendido"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Descartar"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 5e0fa43e7936..11600bc69b09 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5 G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Itinerancia"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Toca para restaurar el original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estás usando tu perfil de trabajo"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toca para activar el sonido."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toca para poner el dispositivo en vibración. Los servicios de accesibilidad pueden silenciarse."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toca para silenciar. Los servicios de accesibilidad pueden silenciarse."</string>
diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml
index 32b3b8c59473..53e463797918 100644
--- a/packages/SystemUI/res/values-es/strings_tv.xml
+++ b/packages/SystemUI/res/values-es/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"El vídeo estará visible hasta que reproduzcas otro. Mantén pulsado el botón "<b>"INICIO"</b>" para controlarlo."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Entendido"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Descartar"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 405d351f726c..b9a978f7b384 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Rändlus"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Puudutage originaali taastamiseks."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Kasutate oma tööprofiili"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Puudutage vaigistuse tühistamiseks."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Puudutage värinarežiimi määramiseks. Juurdepääsetavuse teenused võidakse vaigistada."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Puudutage vaigistamiseks. Juurdepääsetavuse teenused võidakse vaigistada."</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings_tv.xml b/packages/SystemUI/res/values-et-rEE/strings_tv.xml
index 3386f5719751..1a7931071b11 100644
--- a/packages/SystemUI/res/values-et-rEE/strings_tv.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"See hoiab teie videot kuval, kuni esitate järgmise. Selle juhtimiseks vajutage pikalt nuppu "<b>"AVAEKRAAN"</b>"."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Selge"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Loobu"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index d8e3446ec952..edc9c4662819 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Ibiltaritza"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Sakatu jatorrizkora leheneratzeko."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Work profila erabiltzen ari zara"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Sakatu audioa aktibatzeko."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Sakatu dardara ezartzeko. Baliteke erabilerraztasun-eginbideen audioa desaktibatzea."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Sakatu audioa desaktibatzeko. Baliteke erabilerraztasun-eginbideen audioa desaktibatzea."</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings_tv.xml b/packages/SystemUI/res/values-eu-rES/strings_tv.xml
index e1bd3a8fe2c1..381e86e5a5c7 100644
--- a/packages/SystemUI/res/values-eu-rES/strings_tv.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Horrela, ikusgai egongo da bideoa beste bat erreproduzitu arte. Pantaila txikia kontrolatzeko, eduki sakatuta "<b>"HOME"</b>" botoia."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Ados"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Baztertu"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 7c77d59c578c..21e7bff73c92 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"رومینگ"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> کنترل‌کننده صدا است"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"برای بازیابی نسخه اصلی ضربه بزنید."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"درحال استفاده از نمایه کاری‌تان هستید"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"‏%1$s. برای باصدا کردن ضربه بزنید."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"‏%1$s. برای تنظیم روی لرزش ضربه بزنید. ممکن است سرویس‌های دسترس‌پذیری بی‌صدا شوند."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"‏%1$s. برای بی‌صدا کردن ضربه بزنید. ممکن است سرویس‌های دسترس‌پذیری بی‌صدا شوند."</string>
diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
index 86e578d15abe..2894abba3b92 100644
--- a/packages/SystemUI/res/values-fa/strings_tv.xml
+++ b/packages/SystemUI/res/values-fa/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"تا زمانی که ویدیوی دیگری را پخش کنید، این صفحه حالت ویدیو در ویدیوی شما را حفظ می‌کند. برای کنترل آن، دکمه "<b>"صفحه اصلی"</b>" را فشار دهید و نگه دارید."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"متوجه شدم"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"رد کردن"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 3ae25e1a194f..66551f182a23 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Palauta alkuperäinen napauttamalla."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Käytät työprofiilia."</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Poista mykistys koskettamalla."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Siirry värinätilaan koskettamalla. Myös esteettömyyspalvelut saattavat mykistyä."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Mykistä koskettamalla. Myös esteettömyyspalvelut saattavat mykistyä."</string>
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
index 5edd349a04e5..20c3fe414751 100644
--- a/packages/SystemUI/res/values-fi/strings_tv.xml
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Videosi pysyy näkyvissä, kunnes toistat toisen videon. Hallinnoi tilaa painamalla "<b>"HOME"</b>"-painiketta pitkään."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Selvä"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Hylkää"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 9aa176f98932..cedc1e5e2b99 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3G+"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Itinérance"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Touchez pour restaurer l\'original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Vous utilisez votre profil professionnel."</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Touchez pour réactiver le son."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Touchez pour activer les vibrations. Il est possible de couper le son des services d\'accessibilité."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Touchez pour couper le son. Il est possible de couper le son des services d\'accessibilité."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
index 8b382a29fcd8..41a6f1b146dd 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Cette option maintient une vidéo affichée jusqu\'à la lecture de la suivante. Maintenez enfoncée la touche "<b>"ACCUEIL"</b>" pour la contrôler."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Fermer"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index b6c08cae9bb1..27e6a8a75de2 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3G+"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Itinérance"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Appuyez pour rétablir la version d\'origine."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Vous utilisez votre profil professionnel."</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Appuyez pour ne plus ignorer."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Appuyez pour mettre en mode vibreur. Vous pouvez ignorer les services d\'accessibilité."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Appuyez pour ignorer. Vous pouvez ignorer les services d\'accessibilité."</string>
diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
index db0c464c346e..01905b8eba70 100644
--- a/packages/SystemUI/res/values-fr/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Cette option maintient une vidéo affichée jusqu\'à la lecture de la suivante. Appuyez de manière prolongée sur le bouton "<b>"ACCUEIL"</b>" pour la contrôler."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Ignorer"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index c18bae79ee40..dc8811a72472 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Itinerancia"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Toca para restaurar o orixinal."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Estás usando o perfil de traballo"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toca para activar o son."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toca para establecer a vibración. Pódense silenciar os servizos de accesibilidade."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toca para silenciar. Pódense silenciar os servizos de accesibilidade."</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings_tv.xml b/packages/SystemUI/res/values-gl-rES/strings_tv.xml
index bd840aae601e..019f475928ab 100644
--- a/packages/SystemUI/res/values-gl-rES/strings_tv.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"O vídeo manterase visible ata que reproduzas outro. Mantén premido "<b>"INICIO"</b>" para controlalo."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"De acordo"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Ignorar"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 8c00ebd82db8..6a4e492fa81b 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"રોમિંગ"</string>
@@ -344,8 +346,7 @@
<string name="zen_silence_introduction" msgid="3137882381093271568">"એલાર્મ્સ, સંગીત, વિડિઓઝ અને રમતો સહિત તમામ ધ્વનિઓ અને વાઇબ્રેશન્સને આ અવરોધિત કરે છે."</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"નીચે ઓછી તાકીદની સૂચનાઓ"</string>
- <!-- no translation found for notification_tap_again (7590196980943943842) -->
- <skip />
+ <string name="notification_tap_again" msgid="7590196980943943842">"ખોલવા માટે ફરીથી ટૅપ કરો"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"અનલૉક કરવા માટે ઉપર સ્વાઇપ કરો"</string>
<string name="phone_hint" msgid="4872890986869209950">"ફોન માટે આયકનમાંથી સ્વાઇપ કરો"</string>
<string name="voice_hint" msgid="8939888732119726665">"વૉઇસ સહાય માટે આયકનમાંથી સ્વાઇપ કરો"</string>
@@ -435,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> એ વૉલ્યૂમ સંવાદ છે"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"મૂળને પુનઃસ્થાપિત કરવા માટે ટૅપ કરો."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"તમે તમારી કાર્ય પ્રોફાઇલનો ઉપયોગ કરી રહ્યાં છો"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. અનમ્યૂટ કરવા માટે ટૅપ કરો."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. વાઇબ્રેટ પર સેટ કરવા માટે ટૅપ કરો. ઍક્સેસિબિલિટી સેવાઓ મ્યૂટ કરવામાં આવી શકે છે."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. મ્યૂટ કરવા માટે ટૅપ કરો. ઍક્સેસિબિલિટી સેવાઓ મ્યૂટ કરવામાં આવી શકે છે."</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings_tv.xml b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
index 4af9f52d93c2..e2ce121dd667 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"તમે બીજી વિડિઓ ચલાવો નહીં ત્યાં સુધી આ તમારી વિડિઓને દૃશ્યક્ષમ રાખે છે. તેને નિયંત્રિત કરવા માટે "<b>"હોમ"</b>" દબાવી અને પકડી રાખો."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"સમજાઈ ગયું"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"છોડી દો"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 983faed99bdd..22aacd286cf6 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"रोमिंग"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> वॉल्यूम संवाद है"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"मूल को पुन: स्थापित करने के लिए टैप करें."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"आप अपनी कार्य प्रोफ़ाइल का उपयोग कर रहे हैं"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. अनम्यूट करने के लिए टैप करें."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. कंपन पर सेट करने के लिए टैप करें. एक्सेस-योग्यता सेवाएं म्यूट हो सकती हैं."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. म्यूट करने के लिए टैप करें. एक्सेस-योग्यता सेवाएं म्यूट हो सकती हैं."</string>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
index e0b09035efbe..8f0f8985ede0 100644
--- a/packages/SystemUI/res/values-hi/strings_tv.xml
+++ b/packages/SystemUI/res/values-hi/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"यह आपके वीडियो को तब तक दृश्यमान बनाए रखता है जब तक कि आप कोई दूसरा वीडियो नहीं चलाते. उसे नियंत्रित करने के लिए "<b>"HOME"</b>" को दबाए रखें."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"समझ लिया"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"ख़ारिज करें"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index e1afb4d361e8..e1895603738b 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -144,6 +144,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Dodirnite da biste vratili izvornik."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Upotrebljavate radni profil"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Dodirnite da biste uključili zvuk."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Dodirnite da biste postavili na vibraciju. Usluge pristupačnosti možda neće imati zvuk."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Dodirnite da biste isključili zvuk. Usluge pristupačnosti možda neće imati zvuk."</string>
diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
index e4c31c9f3d55..5d69704f23a1 100644
--- a/packages/SystemUI/res/values-hr/strings_tv.xml
+++ b/packages/SystemUI/res/values-hr/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Videozapis će se prikazivati dok ne počnete reproducirati neki drugi. Pritisnite i zadržite tipku "<b>"HOME"</b>" da biste upravljali tom značajkom."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Shvaćam"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Odbaci"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index ca2ca61ec3d1..20859299fd6a 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Barangolás"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Koppintson az eredeti visszaállításához."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"A munkaprofilt használja"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Koppintson a némítás megszüntetéséhez."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Koppintson a rezgés beállításához. Előfordulhat, hogy a kisegítő lehetőségek szolgáltatásai le vannak némítva."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Koppintson a némításhoz. Előfordulhat, hogy a kisegítő lehetőségek szolgáltatásai le vannak némítva."</string>
diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
index db20b430533f..08112f5999aa 100644
--- a/packages/SystemUI/res/values-hu/strings_tv.xml
+++ b/packages/SystemUI/res/values-hu/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"A következő lejátszásáig ezt a videót tartja előtérben. A vezérléshez tartsa nyomva a "<b>"HOME"</b>" gombot."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Rendben"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Elvetés"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 5d01d15adce8..a71fcfa4e279 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Ռոումինգ"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ը ձայնի ուժգնության երկխոսության հավելված է"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Հպեք՝ բնօրինակը վերականգնելու համար:"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Դուք օգտագործում եք ձեր աշխատանքային պրոֆիլը"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s: Հպեք՝ ձայնը միացնելու համար:"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s: Հպեք՝ թրթռումը միացնելու համար: Մատչելիության ծառայությունների ձայնը կարող է անջատվել:"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s: Հպեք՝ ձայնն անջատելու համար: Մատչելիության ծառայությունների ձայնը կարող է անջատվել:"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
index cd9b159a0d45..a447ba8dc9f8 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Տեսանյութը կմնա տեսադաշտում մինչև մեկ այլ տեսանյութ նվագարկելը: Կառավարելու համար սեղմեք և պահեք "<b>"HOME"</b>" կոճակը:"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Պարզ է"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Փակել"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 293cd0070081..8e84c11bb492 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Ketuk untuk memulihkan aslinya."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Anda menggunakan profil kerja"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Ketuk untuk menyuarakan."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Ketuk untuk menyetel agar bergetar. Layanan aksesibilitas mungkin dibisukan."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Ketuk untuk membisukan. Layanan aksesibilitas mungkin dibisukan."</string>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
index a99770346fde..14f64b2bdd6e 100644
--- a/packages/SystemUI/res/values-in/strings_tv.xml
+++ b/packages/SystemUI/res/values-in/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Tindakan ini terus menampilkan video hingga Anda memutar yang lain. Tekan dan tahan tombol "<b>"UTAMA"</b>" untuk mengontrolnya."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Mengerti"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Tutup"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 05e6256a979b..cd24952dfe1a 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Reiki"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Ýttu til að færa í upprunalegt horf."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Þú ert að nota vinnusniðið"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Ýttu til að hætta að þagga."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Ýttu til að stilla á titring. Hugsanlega verður slökkt á hljóði aðgengisþjónustu."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Ýttu til að þagga. Hugsanlega verður slökkt á hljóði aðgengisþjónustu."</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings_tv.xml b/packages/SystemUI/res/values-is-rIS/strings_tv.xml
index 582c044e7abf..6e1918e6c636 100644
--- a/packages/SystemUI/res/values-is-rIS/strings_tv.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Þetta heldur myndskeiðinu sýnilegu þar til þú spilar annað. Haltu inni "<b>"HOME"</b>" til að stjórna."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Ég skil"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Hunsa"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index e8aacd5eb5db..3eafeb7b9435 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Tocca per ripristinare l\'originale."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Stai utilizzando il profilo di lavoro"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tocca per riattivare l\'audio."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tocca per attivare la vibrazione. L\'audio dei servizi di accessibilità può essere disattivato."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tocca per disattivare l\'audio. L\'audio dei servizi di accessibilità può essere disattivato."</string>
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
index 8c47e5617a88..7269bfacab39 100644
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Il video rimane visualizzato fino alla riproduzione di un altro video. Tieni premuto "<b>"HOME"</b>" per controllare la funzione."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Ignora"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 2f1393e6b721..ba7da668fff3 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -145,6 +145,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"נדידה"</string>
@@ -438,6 +440,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> הוא תיבת הדו-שיח של עוצמת הקול"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"הקש כדי לשחזר את המקור."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"אתה משתמש בפרופיל העבודה שלך"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"‏%1$s. הקש כדי לבטל את ההשתקה."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"‏%1$s. הקש כדי להגדיר רטט. ייתכן ששירותי הנגישות מושתקים."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"‏%1$s. הקש כדי להשתיק. ייתכן ששירותי הנגישות מושתקים."</string>
diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml
index eea7a910112f..0556bb0cbaf5 100644
--- a/packages/SystemUI/res/values-iw/strings_tv.xml
+++ b/packages/SystemUI/res/values-iw/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"תכונה זו שומרת על תצוגת הסרטון עד שתפעיל סרטון אחר. לחץ לחיצה ממושכת על לחצן ה"<b>"בית"</b>" כדי לשלוט בתכונה."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"הבנתי"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"דחה"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 39b9ea79e74b..5560773066b7 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ローミング中"</string>
@@ -436,6 +438,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>を音量ダイアログとして使用"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"タップすると元に戻ります。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"仕事用プロファイルを使用しています"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。タップしてミュートを解除します。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。タップしてバイブレーションに設定します。ユーザー補助機能サービスがミュートされる場合があります。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。タップしてミュートします。ユーザー補助機能サービスがミュートされる場合があります。"</string>
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
index 85cddf49e607..dce5874e760c 100644
--- a/packages/SystemUI/res/values-ja/strings_tv.xml
+++ b/packages/SystemUI/res/values-ja/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"これにより、別のビデオを再生するまでこのビデオが表示されます。["<b>"ホーム"</b>"] を押し続けると、操作できます。"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"閉じる"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"閉じる"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 378b36c0b89a..a00d036c0574 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5გბ"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"როუმინგი"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ხმოვან დიალოგშია"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"შეეხეთ ორიგინალის აღსადგენად."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"თქვენ სამსახურის პროფილს იყენებთ"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. შეეხეთ დადუმების გასაუქმებლად."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. შეეხეთ ვიბრაციაზე დასაყენებლად. შეიძლება დადუმდეს მარტივი წვდომის სერვისებიც."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. შეეხეთ დასადუმებლად. შეიძლება დადუმდეს მარტივი წვდომის სერვისებიც."</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
index 67957c99815e..d3b5fa893b80 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"ვიდეო ჩამაგრებული იქნება, სანამ ახალს არ დაუკრავთ. სამართავად, ხანგრძლივად დააჭირეთ "<b>"მთავარ ღილაკზე"</b>"."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"გასაგებია"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"დახურვა"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 1e1544bc9d73..c7e8cf35729e 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3Г"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5Г"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4Г"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"ҰМД"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA (кодтармен бөлінген бірнеше қол жетімділік)"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роуминг"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> — көлем диалогтық терезесі"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Бастапқы қалпына келтіру үшін түртіңіз."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Сіз жұмыс профиліңізді пайдаланып жатырсыз"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Дыбысын қосу үшін түртіңіз."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Діріл режимін орнату үшін түртіңіз. Арнайы мүмкіндік қызметтерінің дыбысы өшуі мүмкін."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Дыбысын өшіру үшін түртіңіз. Арнайы мүмкіндік қызметтерінің дыбысы өшуі мүмкін."</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
index c9823e98fb61..1e0caf7fd977 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Басқа бейне ойнатылғанға дейін ағымдағы бейне көрсетіле береді. Оны басқару үшін "<b>"HOME"</b>" түймесін басып тұрыңыз."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Түсіндім"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Жабу"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 84d3470f502f..b100d73e1423 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"រ៉ូ​មីង"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> គឺជាប្រអប់សម្លេង"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ប៉ះដើម្បីស្តារច្បាប់ដើម"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"អ្នកកំពុងប្រើប្រវត្តិរូបការងាររបស់អ្នក"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s។ ប៉ះដើម្បីបើកសំឡេង។"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s។ ប៉ះដើម្បីកំណត់ឲ្យញ័រ។ សេវាកម្មលទ្ធភាពប្រើប្រាស់អាចនឹងត្រូវបានបិទសំឡេង។"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s។ ប៉ះដើម្បីបិទសំឡេង។ សេវាកម្មលទ្ធភាពប្រើប្រាស់អាចនឹងត្រូវបានបិទសំឡេង។"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings_tv.xml b/packages/SystemUI/res/values-km-rKH/strings_tv.xml
index 0e7b3f2608b4..e4d4f3266b98 100644
--- a/packages/SystemUI/res/values-km-rKH/strings_tv.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"វាបន្តផ្អាកវីដេអូរបស់អ្នក រហូតដល់អ្នកចុចចាក់វីដេអូមួយផ្សេងទៀត។ ចុច ហើយសង្កត់ប៊ូតុង"<b>"ដើម"</b>" ដើម្បីគ្រប់គ្រងវា។"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"យល់ហើយ"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"បដិសេធ"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index ed48bcbd9489..216eb0e22258 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ರೋಮಿಂಗ್"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ವಾಲ್ಯೂಮ್ ಸಂವಾದವಾಗಿದೆ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ಮೂಲಕ್ಕೆ ಮರುಸ್ಥಾಪಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌ ಅನ್ನು ನೀವು ಬಳಸುತ್ತಿರುವಿರಿ"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ಅನ್‌ಮ್ಯೂಟ್‌ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. ಕಂಪನಕ್ಕೆ ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್‌ ಮಾಡಬಹುದು."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ಮ್ಯೂಟ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಪ್ರವೇಶಿಸುವಿಕೆ ಸೇವೆಗಳನ್ನು ಮ್ಯೂಟ್‌ ಮಾಡಬಹುದು."</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
index e617c6ec048a..5afb322d3ea6 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"ನೀವು ಮತ್ತೊಂದನ್ನು ಪ್ಲೇ ಮಾಡುವ ತನಕ ಇದು ನಿಮ್ಮ ವೀಡಿಯೋವನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿರಿಸುತ್ತದೆ. ಅದನ್ನು ನಿಯಂತ್ರಿಸಲು "<b>"ಹೋಮ್"</b>" ಅನ್ನು ಒತ್ತಿ ಹಿಡಿಯಿರಿ."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ಅರ್ಥವಾಯಿತು"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"ವಜಾಗೊಳಿಸಿ"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 5c46e00a3f10..0b269eddb397 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"로밍"</string>
@@ -436,6 +438,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>은(는) 볼륨 대화입니다."</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"원본을 복원하려면 탭하세요."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"직장 프로필을 사용하고 있습니다."</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. 탭하여 음소거를 해제하세요."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. 탭하여 진동으로 설정하세요. 접근성 서비스가 음소거될 수 있습니다."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. 탭하여 음소거로 설정하세요. 접근성 서비스가 음소거될 수 있습니다."</string>
diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml
index b0e9f4557c2d..df22a2418d5a 100644
--- a/packages/SystemUI/res/values-ko/strings_tv.xml
+++ b/packages/SystemUI/res/values-ko/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"다른 동영상을 재생할 때까지 동영상이 계속 표시됩니다. 제어하려면 "<b>"홈"</b>"을 길게 누릅니다."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"확인"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"닫기"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 46fed8b39605..9690a8fbd43e 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роуминг"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> үндү катуулатуу диалогу"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Үндүн баштапкы деңгээлин калыбына келтирүү үчүн таптап коюңуз."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Жумуш профилиңизди колдонуп жатасыз"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Үнүн чыгаруу үчүн таптап коюңуз."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Дирилдөөгө коюу үчүн таптап коюңуз. Атайын мүмкүнчүлүктөр кызматынын үнүн өчүрүп койсо болот."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Үнүн өчүрүү үчүн таптап коюңуз. Атайын мүмкүнчүлүктөр кызматынын үнүн өчүрүп койсо болот."</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
index 771e39527c1a..3d34e2f9bbf0 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Ушуну менен, башка видео ойнотмоюнча видеоңуз көрсөтүлө берет. Аны башкаруу үчүн "<b>"БАШКЫ БЕТ"</b>" баскычын басып, кармап туруңуз."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Түшүндүм"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Көз жаздымда калтыруу"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index f8aea2619d4f..db0e29f6c7d6 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ໂຣມມິງ"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ແມ່ນ​ໜ້າ​ຕ່າງ​ລະ​ດັບ​ສຽງ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ແຕະເພື່ອກູ້ຕົ້ນສະບັບຄືນມາ."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ທ່ານກຳລັງໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານ"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ແຕະເພື່ອເຊົາປິດສຽງ."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. ແຕະເພື່ອຕັ້ງເປັນສັ່ນ. ບໍລິການຊ່ວຍເຂົ້າເຖິງອາດຖືກປິດສຽງໄວ້."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ແຕະເພື່ອປິດສຽງ. ບໍລິການຊ່ວຍເຂົ້າເຖິງອາດຖືກປິດສຽງໄວ້."</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
index ba325977d402..cf2ef1ed3318 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"ນີ້ຈະເປັນການເຮັດໃຫ້ວິດີໂອຂອງທ່ານຢູ່ໃນມຸມມອງຈົນກວ່າທ່ານຈະຫຼິ້ນວິດີໂອອື່ນ. ໃຫ້ກົດປຸ່ມ "<b>"HOME"</b>" ຄ້າງໄວ້ເພື່ອຄວບຄຸມມັນ."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ເຂົ້າໃຈແລ້ວ"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"ປິດໄວ້"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a40bef9b3d74..79d71e976b99 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -145,6 +145,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Tarptinklinis ryšys"</string>
@@ -438,6 +440,12 @@
<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="8819536904234337445">"Palieskite, kad atkurtumėte originalą."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Naudojate darbo profilį"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Palieskite, kad įjungtumėte garsą."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Palieskite, kad nustatytumėte vibravimą. Gali būti nutildytos pritaikymo neįgaliesiems paslaugos."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Palieskite, kad nutildytumėte. Gali būti nutildytos pritaikymo neįgaliesiems paslaugos."</string>
diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml
index e263da4deabe..0cdc085533b1 100644
--- a/packages/SystemUI/res/values-lt/strings_tv.xml
+++ b/packages/SystemUI/res/values-lt/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Vaizdo įrašas bus rodomas, kol paleisite kitą vaizdo įrašą. Jei norite valdyti, palaikykite paspaudę mygtuką "<b>"HOME"</b>"."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Supratau"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Atsisakyti"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index d5b29c4105de..0d36062fb154 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -144,6 +144,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Viesabonēšana"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Pieskarieties, lai atjaunotu sākotnējo saturu."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Jūs izmantojat darba profilu."</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Pieskarieties, lai ieslēgtu skaņu."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Pieskarieties, lai iestatītu uz vibrozvanu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Pieskarieties, lai izslēgtu skaņu. Var tikt izslēgti pieejamības pakalpojumu signāli."</string>
diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml
index cafc10da0931..33450fa8d430 100644
--- a/packages/SystemUI/res/values-lv/strings_tv.xml
+++ b/packages/SystemUI/res/values-lv/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Šādi videoklips būs redzams, līdz atskaņosiet citu videoklipu. Lai to kontrolētu, nospiediet un turiet nospiestu pogu "<b>"HOME"</b>"."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Labi"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Nerādīt"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index f4dd7bc00074..955532cfca97 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роаминг"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> е дијалог за јачина на звук"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Допрете за да го вратите оригиналот."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Го користите работниот профил"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Допрете за да вклучите звук."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Допрете за да поставите на вибрации. Можеби ќе се исклучи звукот на услугите за достапност."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Допрете за да исклучите звук. Можеби ќе се исклучи звукот на услугите за достапност."</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
index 453272ca695e..6d7a53ac1147 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Видеото се прикажува сѐ додека не пуштите друго. Притиснете и задржете "<b>"ПОЧЕТЕН ЕКРАН"</b>" за да го контролирате."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Разбрав"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Отфрли"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 7178b298fc25..8a6776c3371b 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"റോമിംഗ്"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g>, വോളിയം ഡയലോഗാണ്"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ഒറിജിനൽ പുനഃസ്ഥാപിക്കാൻ ടാപ്പുചെയ്യുക."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"നിങ്ങൾ ഉപയോഗിക്കുന്നത് ഔദ്യോഗിക പ്രൊഫൈലാണ്"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. അൺമ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. വൈബ്രേറ്റിലേക്ക് സജ്ജമാക്കുന്നതിന് ടാപ്പുചെയ്യുക. പ്രവേശനക്ഷമതാ സേവനങ്ങൾ മ്യൂട്ടുചെയ്യപ്പെട്ടേക്കാം."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. മ്യൂട്ടുചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക. പ്രവേശനക്ഷമതാ സേവനങ്ങൾ മ്യൂട്ടുചെയ്യപ്പെട്ടേക്കാം."</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
index 48bdb51bda26..e971b9ae108e 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"മറ്റൊരു വീഡിയോ പ്ലേ ചെയ്യുന്നത് വരെ നിങ്ങളുടെ വീഡിയോയെ ഇത് കാഴ്ചയിൽ നിലനിർത്തുന്നു. ഇത് നിയന്ത്രിക്കുന്നതിന് "<b>"ഹോം"</b>" അമർത്തിപ്പിടിക്കുക."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"മനസ്സിലായി"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"ഡിസ്മിസ് ചെയ്യുക"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 296658bd3dfd..24c82bd87539 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -141,6 +141,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Рүүминг"</string>
@@ -432,6 +434,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> нь дууны диалог юм."</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Эх хувилбарыг сэргээхийн тулд дарна уу."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Та өөрийн ажлын профайлыг ашиглаж байна"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Дууг нь нээхийн тулд товшино уу."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Чичиргээнд тохируулахын тулд товшино уу. Хүртээмжийн үйлчилгээний дууг хаасан."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Дууг нь хаахын тулд товшино уу. Хүртээмжийн үйлчилгээний дууг хаасан."</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
index 8c6ffbb3c7a3..40933d894c02 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Таныг өөр видео тоглуулах хүртэл таны видеог гаргасаар байх болно. Үүнийг удирдахын тулд "<b>"НҮҮР ХУУДАС"</b>" товчлуурыг дараад, хүлээнэ үү."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Ойлголоо"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Хаах"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 1fb4beb1e14f..62e264ac57f5 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"रोमिंग"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> हा व्हॉल्यूम संवाद आहे"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"मूळ पुनर्संचयित करण्यासाठी टॅप करा."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"आपण आपले कार्य प्रोफाईल वापरत आहात"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. सशब्द करण्यासाठी टॅप करा."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. कंपन सेट करण्यासाठी टॅप करा. प्रवेशयोग्यता सेवा नि:शब्द केल्या जाऊ शकतात."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. नि:शब्द करण्यासाठी टॅप करा. प्रवेशक्षमता सेवा नि:शब्द केल्या जाऊ शकतात."</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings_tv.xml b/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
index 58415000ea87..bfada643a460 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"आपण दुसरा व्हिडिओ प्ले करेपर्यंत हे आपल्या व्हिडिओस दृश्यामध्ये ठेवते. ते नियंत्रित करण्यासाठी "<b>"मुख्यपृष्ठ"</b>" दाबा आणि धरून ठेवा."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"समजले"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"डिसमिस करा"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 8729ae86d2bd..7aa09a656f35 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Perayauan"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Ketik untuk memulihkan yang asal."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Anda sedang menggunakan profil kerja"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Ketik untuk menyahredam."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Ketik untuk menetapkan pada getar. Perkhidmatan kebolehaksesan mungkin diredamkan."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Ketik untuk meredam. Perkhidmatan kebolehaksesan mungkin diredamkan."</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
index 502f231583db..de221cc147ad 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Tindakan ini memastikan video anda sentiasa dipaparkan sehingga anda memainkan video lain. Tekan dan tahan "<b>"SKRIN UTAMA"</b>" untuk mengawalnya."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Ketepikan"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 2522e39aa7bb..e31c11c519dc 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -143,6 +143,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"4G+"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"မြန်နှုန်းမြင့်လိုင်း"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ကွန်ယက်ပြင်ပဒေတာအသုံးပြုခြင်း"</string>
@@ -434,6 +435,18 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> သည် အသံဒိုင်ယာလော့ခ်ဖြစ်သည်"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"မူရင်းကိုပြန်ယူရန် တို့ပါ။"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"သင်သည် အလုပ်ပရိုဖိုင်းအား သုံးနေသည်"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ခေါ်ဆိုမှု"</item>
+ <item msgid="5997713001067658559">"စနစ်"</item>
+ <item msgid="7858983209929864160">"ဖုန်းခေါ်ဆိုမှု"</item>
+ <item msgid="1850038478268896762">"မီဒီယာ"</item>
+ <item msgid="8265110906352372092">"နှိုးစက်"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ဘလူးတုသ်"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s။ အသံပြန်ဖွင့်ရန် တို့ပါ။"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s။ တုန်ခါမှုကို သတ်မှတ်ရန် တို့ပါ။ အများသုံးစွဲနိုင်မှု ဝန်ဆောင်မှုများကို အသံပိတ်ထားနိုင်ပါသည်။"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s။ အသံပိတ်ရန် တို့ပါ။ အများသုံးစွဲနိုင်မှု ဝန်ဆောင်မှုများကို အသံပိတ်ထားနိုင်ပါသည်။"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings_tv.xml b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
index 4ce1992460e5..2c5b94b3cf45 100644
--- a/packages/SystemUI/res/values-my-rMM/strings_tv.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"နောက်တစ်ခုမဖွင့်မချင်း သင့်ဗီဒီယိုကို ပြသထားပါမည်။ ၎င်းကိုထိန်းချုပ်ရန် "<b>"ပင်မ"</b>" ခလုတ်ကို နှိပ်ပြီးဖိထားပါ။"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ရပါပြီ"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"ပယ်ပါ"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index fc81c3cd5c07..4db9ab61510f 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Trykk for å gjenopprette originalen."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du bruker jobbprofilen din"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Trykk for å slå på lyden."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Trykk for å angi vibrasjon. Lyden kan bli slått av for tilgjengelighetstjenestene."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Trykk for å slå av lyden. Lyden kan bli slått av for tilgjengelighetstjenestene."</string>
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
index 3dc7ae0be820..20b0f24d1250 100644
--- a/packages/SystemUI/res/values-nb/strings_tv.xml
+++ b/packages/SystemUI/res/values-nb/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Dette holder videoen din synlig frem til du spiller av en annen video. Trykk og hold inne "<b>"HOME"</b>" for å styre dette."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Greit"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Avvis"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 4f321cf8be24..a0991362a666 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -143,6 +143,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"4G+"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"रोमिङ"</string>
@@ -434,6 +435,18 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> भोल्यूम संवाद हो"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"मूललाई पुनर्स्थापना गर्न ट्याप गर्नुहोस्।"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"तपाईँले कार्य प्रोफाइल प्रयोग गर्दै हुनुहुन्छ"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"कल"</item>
+ <item msgid="5997713001067658559">"प्रणाली"</item>
+ <item msgid="7858983209929864160">"रिङटोन"</item>
+ <item msgid="1850038478268896762">"मिडिया"</item>
+ <item msgid="8265110906352372092">"अलार्म"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"ब्लुटुथ"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। अनम्यूट गर्नका लागि ट्याप गर्नुहोस्।"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। कम्पनमा सेट गर्नका लागि ट्याप गर्नुहोस्। पहुँच सम्बन्धी सेवाहरू म्यूट हुन सक्छन्।"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। म्यूट गर्नका लागि ट्याप गर्नुहोस्। पहुँच सम्बन्धी सेवाहरू म्यूट हुन सक्छन्।"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings_tv.xml b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
index 61a16699c535..648eed067758 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"तपाईँले अर्को भिडियोलाई प्ले नगरेसम्म यसले तपाईँको भिडियोलाई दृश्यमा राख्दछ। यसलाई नियन्त्रण गर्नका लागि "<b>"HOME"</b>" लाई थिचिरहनुहोस्।"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"बुझेँ"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"खारेज गर्नुहोस्"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 72f04bbafdb3..cf530ec990ea 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Tik om het origineel te herstellen."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"U gebruikt je werkprofiel"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tik om dempen op te heffen."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tik om in te stellen op trillen. Toegankelijkheidsservices kunnen zijn gedempt."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tik om te dempen. Toegankelijkheidsservices kunnen zijn gedempt."</string>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
index ee0510c251ce..4fdaf5dd10b6 100644
--- a/packages/SystemUI/res/values-nl/strings_tv.xml
+++ b/packages/SystemUI/res/values-nl/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Hiermee blijft je video in beeld totdat je een andere afspeelt. Houd "<b>"HOME"</b>" ingedrukt om de functie te bedienen."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Sluiten"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index d9cb04f3ba8b..a38d58d721f2 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ਰੋਮਿੰਗ"</string>
@@ -344,8 +346,7 @@
<string name="zen_silence_introduction" msgid="3137882381093271568">"ਇਹ ਅਲਾਰਮ, ਸੰਗੀਤ, ਵੀਡੀਓਜ਼, ਅਤੇ ਗੇਮਸ ਸਮੇਤ, ਸਾਰੀਆਂ ਧੁਨੀਆਂ ਅਤੇ ਵਾਇਬ੍ਰੇਸ਼ਨ ਨੂੰ ਬਲੌਕ ਕਰਦਾ ਹੈ।"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"ਹੇਠਾਂ ਘੱਟ ਲਾਜ਼ਮੀ ਸੂਚਨਾਵਾਂ"</string>
- <!-- no translation found for notification_tap_again (7590196980943943842) -->
- <skip />
+ <string name="notification_tap_again" msgid="7590196980943943842">"ਖੋਲ੍ਹਣ ਲਈ ਦੁਬਾਰਾ ਟੈਪ ਕਰੋ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਉੱਪਰ ਸਵਾਈਪ ਕਰੋ।"</string>
<string name="phone_hint" msgid="4872890986869209950">"ਫ਼ੋਨ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="voice_hint" msgid="8939888732119726665">"ਵੌਇਸ ਅਸਿਸਟ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
@@ -435,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੋਲਯੂਮ ਡਾਇਲੌਗ ਹੈ"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"ਅਸਲ ਨੂੰ ਮੁੜ-ਬਹਾਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ਤੁਸੀਂ ਆਪਣੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਵਰਤ ਰਹੇ ਹੋ"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s। ਅਣਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s। ਥਰਥਰਾਹਟ ਸੈੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings_tv.xml b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
index afaa6583beb4..cbd5cbf5e113 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"ਇਹ ਤੁਹਾਡੀ ਵੀਡੀਓ ਨੂੰ ਤਦ ਤੱਕ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਰੱਖਦਾ ਹੈ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਕੋਈ ਹੋਰ ਵੀਡੀਓ ਨਹੀਂ ਚਲਾਉਂਦੇ ਹੋ। ਇਸ ਨੂੰ ਕੰਟਰੋਲ ਕਰਨ ਲਈ "<b>"ਹੋਮ"</b>" ਬਟਨ ਨੂੰ ਦੱਬੋ ਅਤੇ ਦਬਾਈ ਰੱਖੋ।"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ਸਮਝ ਲਿਆ"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"ਖ਼ਾਰਜ ਕਰੋ"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3cf8294e58a0..5a62d8c3ea27 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -145,6 +145,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -438,6 +440,12 @@
<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="8819536904234337445">"Kliknij, by przywrócić ustawienie początkowe."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Używasz profilu do pracy"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Kliknij, by wyłączyć wyciszenie."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Kliknij, by włączyć wibracje. Ułatwienia dostępu mogą być wyciszone."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Kliknij, by wyciszyć. Ułatwienia dostępu mogą być wyciszone."</string>
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
index 03a18bda187f..09c63e43e0a3 100644
--- a/packages/SystemUI/res/values-pl/strings_tv.xml
+++ b/packages/SystemUI/res/values-pl/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"W tym trybie film pozostaje na ekranie do czasu, aż odtworzysz kolejny. Aby sterować trybem, przytrzymaj przycisk "<b>"EKRAN GŁÓWNY"</b>"."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Zamknij"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 6feea2089fab..94c882e8fbd2 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Toque para restaurar o original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Você está usando seu perfil de trabalho"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toque para ativar o som."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toque para configurar para vibrar. É possível que os serviços de acessibilidade sejam silenciados."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toque para silenciar. É possível que os serviços de acessibilidade sejam silenciados."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
index 1857feed7199..4b76e6452359 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Esse recurso faz com que seu vídeo continue sendo exibido até que você reproduza outro. Mantenha "<b>"INÍCIO"</b>" pressionado para controlá-lo."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Entendi"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Dispensar"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index c3934009b922..e08d94b5f0bc 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Toque para restaurar o original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Está a utilizar o seu perfil de trabalho"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toque para reativar o som."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toque para ativar a vibração. Os serviços de acessibilidade podem ser silenciados."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toque para desativar o som. Os serviços de acessibilidade podem ser silenciados."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
index 915b2272f47b..9465cc2f9843 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Esta opção mantém o vídeo visível até reproduzir outro vídeo. Prima sem soltar "<b>"HOME"</b>" para o controlar."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Compreendi"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Ignorar"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 6feea2089fab..94c882e8fbd2 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Toque para restaurar o original."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Você está usando seu perfil de trabalho"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Toque para ativar o som."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Toque para configurar para vibrar. É possível que os serviços de acessibilidade sejam silenciados."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Toque para silenciar. É possível que os serviços de acessibilidade sejam silenciados."</string>
diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml
index 1857feed7199..4b76e6452359 100644
--- a/packages/SystemUI/res/values-pt/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Esse recurso faz com que seu vídeo continue sendo exibido até que você reproduza outro. Mantenha "<b>"INÍCIO"</b>" pressionado para controlá-lo."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Entendi"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Dispensar"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 5f3eed7243f1..3105f9ff31cb 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -71,7 +71,7 @@
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"Se salv. captura de ecran..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"Se salvează captura de ecran..."</string>
<string name="screenshot_saving_text" msgid="2419718443411738818">"Captura de ecran este salvată."</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"Captură de ecran realizată."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"Captură de ecran salvată."</string>
<string name="screenshot_saved_text" msgid="2685605830386712477">"Atingeți pentru a vedea captura de ecran."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Captura de ecran nu a putut fi realizată."</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problemă întâmpinată la salvarea capturii de ecran."</string>
@@ -144,6 +144,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -438,6 +440,12 @@
<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="8819536904234337445">"Atingeți pentru a restabili versiunea originală."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Acum folosiți profilul de serviciu"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Atingeți pentru a activa sunetul."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Atingeți pentru a seta vibrarea. Sunetul se poate dezactiva pentru serviciile de accesibilitate."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Atingeți pentru a dezactiva sunetul. Sunetul se poate dezactiva pentru serviciile de accesibilitate."</string>
diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml
index 0287cb72bb54..233eb3a0aaf8 100644
--- a/packages/SystemUI/res/values-ro/strings_tv.xml
+++ b/packages/SystemUI/res/values-ro/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Astfel, videoclipul este afișat până când redați alt videoclip. Apăsați lung pe butonul "<b>"ACASĂ"</b>" pentru a controla funcția."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Am înțeles"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Închideți"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 062ea4870bb3..a0df12d0221b 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -145,6 +145,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роуминг"</string>
@@ -440,6 +442,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"Приложение <xliff:g id="APP_NAME">%1$s</xliff:g> назначено регулятором громкости"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Нажмите, чтобы восстановить оригинал"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Вы перешли в рабочий профиль"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Нажмите, чтобы включить звук."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Нажмите, чтобы включить вибрацию. Специальные возможности могут прекратить работу."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Нажмите, чтобы выключить звук. Специальные возможности могут прекратить работу."</string>
diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml
index 3c001601d133..d60a114b4e05 100644
--- a/packages/SystemUI/res/values-ru/strings_tv.xml
+++ b/packages/SystemUI/res/values-ru/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Позволяет смотреть одно видео в другом. Для управления нажмите и удерживайте клавишу "<b>"HOME"</b>"."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ОК"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Закрыть"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 90f75a6d090f..bffb443447a5 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -143,6 +143,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"4G+"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"රෝමිං"</string>
@@ -434,6 +435,18 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> ධාරිතා සංවාදයයි"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"මුල් තත්ත්වය නැවත ප්‍රතිසාධනය කිරීමට තට්ටු කරන්න."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"ඔබ ඔබේ කාර්යාල පැතිකඩ භාවිත කරමින් සිටී"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"ඇමතුම"</item>
+ <item msgid="5997713001067658559">"පද්ධතිය"</item>
+ <item msgid="7858983209929864160">"නාද කරන්න"</item>
+ <item msgid="1850038478268896762">"මාධ්‍ය"</item>
+ <item msgid="8265110906352372092">"එලාමය"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"බ්ලූටූත්"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. නිහඬ කිරීම ඉවත් කිරීමට තට්ටු කරන්න."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. කම්පනය කිරීමට තට්ටු කරන්න. ප්‍රවේශ්‍යතා සේවා නිහඬ කළ හැකිය."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. නිහඬ කිරීමට තට්ටු කරන්න. ප්‍රවේශ්‍යතා සේවා නිහඬ කළ හැකිය."</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings_tv.xml b/packages/SystemUI/res/values-si-rLK/strings_tv.xml
index 7c3d4fc11c28..7fd7641d1f33 100644
--- a/packages/SystemUI/res/values-si-rLK/strings_tv.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"මෙය ඔබේ වීඩියෝව ඔබ වෙනත් එකක් ධාවනය කරන තෙක් දසුනෙහි තබා ගනියි. එය පාලනය කිරීමට "<b>"මුල් පිටුව"</b>" ඔබා අල්ලාගෙන සිටින්න."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"හරි, තේරුණා"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"අස් කරන්න"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f0537c3e5325..67865567c8df 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -145,6 +145,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -440,6 +442,12 @@
<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="8819536904234337445">"Klepnutím obnovíte pôvodnú verziu."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Používate svoj pracovný profil."</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Klepnutím zapnite zvuk."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Klepnutím aktivujte režim vibrovania. Služby dostupnosti je možné stlmiť."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Klepnutím vypnite zvuk. Služby dostupnosti je možné stlmiť."</string>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
index f4e781af0551..29728629f8dc 100644
--- a/packages/SystemUI/res/values-sk/strings_tv.xml
+++ b/packages/SystemUI/res/values-sk/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Táto možnosť podrží video v obraze, dokým prehráte ďalšie. Stlačením a podržaním tlačidla "<b>"HOME"</b>" ho môžete ovládať."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Dobre"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Odmietnuť"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 4eafc0b13efb..4ebf274ddbb7 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -145,6 +145,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Gostovanje"</string>
@@ -440,6 +442,12 @@
<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="8819536904234337445">"Dotaknite se, če želite obnoviti prvotno stanje."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Uporabljate delovni profil"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Dotaknite se, če želite vklopiti zvok."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Dotaknite se, če želite nastaviti vibriranje. V storitvah za ljudi s posebnimi potrebami bo morda izklopljen zvok."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Dotaknite se, če želite izklopiti zvok. V storitvah za ljudi s posebnimi potrebami bo morda izklopljen zvok."</string>
diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
index b29253f3da8f..72f3c0cf5e70 100644
--- a/packages/SystemUI/res/values-sl/strings_tv.xml
+++ b/packages/SystemUI/res/values-sl/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"S tem videoposnetek ostane v pogledu, dokler ne predvajate drugega. Pridržite tipko "<b>"HOME"</b>", če ga želite upravljati."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Razumem"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Opusti"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 688e6437f564..e6534c2580c3 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"Lidhje CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -344,8 +346,7 @@
<string name="zen_silence_introduction" msgid="3137882381093271568">"Kjo bllokon TË GJITHË tingujt dhe dridhjet, duke përfshirë edhe nga alarmet, muzika, videot dhe lojërat."</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Njoftimet më pak urgjente, më poshtë!"</string>
- <!-- no translation found for notification_tap_again (7590196980943943842) -->
- <skip />
+ <string name="notification_tap_again" msgid="7590196980943943842">"Trokit përsëri për ta hapur"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Rrëshqit për të shkyçur"</string>
<string name="phone_hint" msgid="4872890986869209950">"Rrëshqit për të hapur telefonin"</string>
<string name="voice_hint" msgid="8939888732119726665">"Rrëshqit për të hapur ndihmën zanore"</string>
@@ -435,6 +436,12 @@
<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="8819536904234337445">"Trokit për të restauruar origjinalin."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Po përdor profilin tënd të punës"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Trokit për të aktivizuar."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Trokit për ta caktuar te dridhja. Shërbimet e qasshmërisë mund të çaktivizohen."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Trokit për të çaktivizuar. Shërbimet e qasshmërisë mund të çaktivizohen."</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
index 4d9ed2b7cd97..9bfd18f44731 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Kjo e mban videon të dukshme derisa të luash një tjetër. Shtyp dhe mbaj shtypur "<b>"HOME"</b>" për ta kontrolluar."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"E kuptova"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Hiqe"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 2bfdc887dc98..a6ab116ce243 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -144,6 +144,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роминг"</string>
@@ -436,6 +438,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> је дијалог за јачину звука"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Додирните да бисте вратили оригинал."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Користите профил за Work"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Додирните да бисте укључили звук."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Додирните да бисте подесили на вибрацију. Звук услуга приступачности ће можда бити искључен."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Додирните да бисте искључили звук. Звук услуга приступачности ће можда бити искључен."</string>
diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml
index f5d948d2d4d8..85a21a9e857d 100644
--- a/packages/SystemUI/res/values-sr/strings_tv.xml
+++ b/packages/SystemUI/res/values-sr/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"На овај начин ће видео бити приказан док не пустите неки други. Притисните и задржите "<b>"ПОЧЕТНА"</b>" да бисте га контролисали."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Важи"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Одбаци"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 7c2f3af066ae..487595ace533 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Återställ originalet genom att trycka här."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Du använder din jobbprofil"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Tryck här om du vill slå på ljudet."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tryck här om du vill sätta på vibrationen. Tillgänglighetstjänster kanske inaktiveras."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Tryck här om du vill stänga av ljudet. Tillgänglighetstjänsterna kanske inaktiveras."</string>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
index 6341d5f9b0ca..4e1281ba63da 100644
--- a/packages/SystemUI/res/values-sv/strings_tv.xml
+++ b/packages/SystemUI/res/values-sv/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Då visas videon tills du spelar upp en annan. Tryck länge på "<b>"startknappen"</b>" om du vill styra uppspelningen."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Ignorera"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 28b6153cde1a..e88cb7f995ed 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Inatumia data nje mtandao wako wa kawaida"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Gonga ili urejeshe picha ya asili."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Unatumia wasifu wako wa kazini"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Gonga ili urejeshe."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Gonga ili uweke mtetemo. Huenda ikakomesha huduma za zana za walio na matatizo ya kuona au kusikia."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Gonga ili ukomeshe. Huenda ikakomesha huduma za zana za walio na matatizo ya kuona au kusikia."</string>
diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml
index 20e96293cf5e..02c28aebe79e 100644
--- a/packages/SystemUI/res/values-sw/strings_tv.xml
+++ b/packages/SystemUI/res/values-sw/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Hali hii itaendelea kuonyesha video yako hadi utakapocheza video nyingine. Bonyeza na ushikilie kitufe cha "<b>"HOME"</b>" ili uidhibiti."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Nimeelewa"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Ondoa"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index d7ba7193d6ea..81e7b5348757 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ரோமிங்"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"ஒலியளவு செய்தி: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"அசலை மீட்டமைக்க, தட்டவும்."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"பணி சுயவிவரத்தைப் பயன்படுத்துகிறீர்கள்"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. ஒலி இயக்க, தட்டவும்."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. அதிர்விற்கு அமைக்க, தட்டவும். அணுகல்தன்மை சேவைகள் ஒலியடக்கப்படக்கூடும்."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. ஒலியடக்க, தட்டவும். அணுகல்தன்மை சேவைகள் ஒலியடக்கப்படக்கூடும்."</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings_tv.xml b/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
index f875a372bcef..cf9a5008c76d 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"இது நீங்கள் அடுத்த வீடியோவை இயக்கும் வரை தற்போதுள்ள வீடியோவை வைத்திருக்கும். அதைக் கட்டுப்படுத்த, "<b>"முகப்பு"</b>" என்பதை அழுத்திப் பிடிக்கவும்."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"சரி"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"நிராகரி"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 1843ee4d3bc7..cbf037c34409 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"రోమింగ్"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> అనేది వాల్యూమ్ డైలాగ్"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"అసలు దాన్ని పునరుద్ధరించడానికి నొక్కండి."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"మీరు మీ కార్యాలయ ప్రొఫైల్‌ను ఉపయోగిస్తున్నారు"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. అన్‌మ్యూట్ చేయడానికి నొక్కండి."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. వైబ్రేషన్‌కు సెట్ చేయడానికి నొక్కండి. ప్రాప్యత సేవలు మ్యూట్ చేయబడవచ్చు."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. మ్యూట్ చేయడానికి నొక్కండి. ప్రాప్యత సేవలు మ్యూట్ చేయబడవచ్చు."</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings_tv.xml b/packages/SystemUI/res/values-te-rIN/strings_tv.xml
index c48b6b947e40..d065cbd572a2 100644
--- a/packages/SystemUI/res/values-te-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"ఇది మీరు మరొకటి ప్లే చేసే వరకు మీ వీడియోను వీక్షణలో ఉంచుతుంది. దాన్ని నియంత్రించడానికి "<b>"హోమ్"</b>" నొక్కి, పట్టుకోండి."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"అర్థమైంది"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"తీసివేస్తుంది"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index a20033af6de3..ba08ab766e14 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"โรมมิ่ง"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> เป็นช่องโต้ตอบระดับเสียง"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"แตะเพื่อคืนค่าเป็นค่าเดิม"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"คุณกำลังใช้โปรไฟล์งานของคุณ"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s แตะเพื่อเปิดเสียง"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s แตะเพื่อตั้งค่าให้สั่น อาจมีการปิดเสียงบริการการเข้าถึง"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s แตะเพื่อปิดเสียง อาจมีการปิดเสียงบริการการเข้าถึง"</string>
diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
index 7ac4807ca0a5..b6c61f13bffb 100644
--- a/packages/SystemUI/res/values-th/strings_tv.xml
+++ b/packages/SystemUI/res/values-th/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"การตั้งค่านี้จะทำให้คุณมองเห็นวิดีโอนี้จนกว่าคุณจะเล่นวิดีโออีกรายการหนึ่ง กดปุ่ม"<b>"หน้าแรก"</b>"ค้างไว้เพื่อควบคุม"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"รับทราบ"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"ปิด"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 41326ab74a39..bb4354040b66 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"I-tap upang i-restore ang orihinal."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Ginagamit mo ang iyong profile sa trabaho"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. I-tap upang i-unmute."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. I-tap upang itakda na mag-vibrate. Maaaring i-mute ang mga serbisyo sa Accessibility."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. I-tap upang i-mute. Maaaring i-mute ang mga serbisyo sa Accessibility."</string>
diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
index 45fa081ab271..83244de45da8 100644
--- a/packages/SystemUI/res/values-tl/strings_tv.xml
+++ b/packages/SystemUI/res/values-tl/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Pinapanatili nitong nakikita ang iyong video hanggang sa mag-play ka ng iba. Pindutin nang matagal ang "<b>"HOME"</b>" upang kontrolin ito."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"I-dismiss"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index e95785fd9d8b..7f05b35ae93f 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Dolaşımda"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Orijinali geri yüklemek için dokunun."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"İş profilinizi kullanıyorsunuz"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Sesi açmak için hafifçe dokunun."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Titreşime ayarlamak için hafifçe dokunun. Erişilebilirlik hizmetlerinin sesi kapatılabilir."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Sesi kapatmak için hafifçe dokunun. Erişilebilirlik hizmetlerinin sesi kapatılabilir."</string>
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
index 8fe5395c6a1e..bcce4658a260 100644
--- a/packages/SystemUI/res/values-tr/strings_tv.xml
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Bu işlev, videonuzu, başka bir video oynatılıncaya kadar görünür tutar. Bu işlevi kontrol etmek için "<b>"ANA EKRAN"</b>" tuşunu basılı tutun."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Anladım"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Kapat"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index f68521cb0158..99aa62e2fb13 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -145,6 +145,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Роумінг"</string>
@@ -440,6 +442,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> призначено регулятором гучності"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"Торкніться, щоб відновити оригінал."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Ви в робочому профілі"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Торкніться, щоб увімкнути звук."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Торкніться, щоб налаштувати вібросигнал. Спеціальні можливості може бути вимкнено."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Торкніться, щоб вимкнути звук. Спеціальні можливості може бути вимкнено."</string>
diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml
index 76277d6275e3..0d5750a3e7d0 100644
--- a/packages/SystemUI/res/values-uk/strings_tv.xml
+++ b/packages/SystemUI/res/values-uk/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Відео буде закріплено, доки ви не запустите інше відео. Щоб керувати, утримуйте кнопку "<b>"HOME"</b>"."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Закрити"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 92139f169440..ff4b00d135a0 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"رومنگ"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"<xliff:g id="APP_NAME">%1$s</xliff:g> والیوم ڈائلاگ ہے"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"اصل بحال کرنے کیلئے تھپتھپائیں۔"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"آپ اپنا دفتری پروفائل استعمال کر رہے ہیں۔"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"‏‎%1$s۔ آواز چالو کرنے کیلئے تھپتھپائیں۔"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"‏‎%1$s۔ ارتعاش پر سیٹ کرنے کیلئے تھپتھپائیں۔ Accessibility سروسز شاید خاموش ہوں۔"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"‏‎%1$s۔ خاموش کرنے کیلئے تھپتھپائیں۔ Accessibility سروسز شاید خاموش ہوں۔"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
index 1844c96780eb..b5b0b722a148 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"یہ آپ کی ویڈیو تب تک دکھاتا رہتا ہے جب تک آپ کوئی دوسری نہیں چلاتے۔ اسے کنٹرول کرنے کیلئے "<b>"ہوم"</b>" دبائیں اور پکڑے رہیں۔"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"سمجھ آ گئی"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"برخاست کریں"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 84e2a2980346..d6f3951a8a7c 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Rouming"</string>
@@ -436,6 +438,12 @@
<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="8819536904234337445">"Aslini tiklash uchun bosing."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Siz ishchi profildan foydalanmoqdasiz"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Ovozini yoqish uchun ustiga bosing."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Tebranishni yoqish uchun ustiga bosing. Maxsus imkoniyatlar ishlamasligi mumkin."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Ovozini o‘chirish uchun ustiga bosing. Maxsus imkoniyatlar ishlamasligi mumkin."</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
index 2af885e0e2de..a9cbac486caa 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Bir videoni boshqasida ko‘rish imkonini beradi. Boshqarish uchun "<b>"HOME"</b>" tugmasini bosib turing."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Yopish"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 24c29072eb4e..7d56b2a9571d 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3,5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Chuyển vùng"</string>
@@ -434,6 +436,12 @@
<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="8819536904234337445">"Nhấn để khôi phục ảnh chụp màn hình gốc."</string>
<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>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Nhấn để bật tiếng."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Nhấn để đặt chế độ rung. Bạn có thể tắt tiếng dịch vụ trợ năng."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Nhấn để tắt tiếng. Bạn có thể tắt tiếng dịch vụ trợ năng."</string>
diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml
index 21343bee6d2b..30b1e88f12ef 100644
--- a/packages/SystemUI/res/values-vi/strings_tv.xml
+++ b/packages/SystemUI/res/values-vi/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Màn hình này sẽ giữ video của bạn ở chế độ xem cho đến khi bạn phát video khác. Nhấn và giữ "<b>"HOME"</b>" để điều khiển màn hình."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Loại bỏ"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 76130990fdc1..fc6495ec7772 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -143,6 +143,8 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <!-- no translation found for accessibility_data_connection_4g_plus (3032226872470658661) -->
+ <skip />
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"漫游中"</string>
@@ -434,6 +436,12 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”已用作音量控制对话框"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"点按即可恢复原始设置。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您当前正在使用工作资料"</string>
+ <!-- no translation found for volume_stream_titles:0 (5841843895402729630) -->
+ <!-- no translation found for volume_stream_titles:1 (5997713001067658559) -->
+ <!-- no translation found for volume_stream_titles:2 (7858983209929864160) -->
+ <!-- no translation found for volume_stream_titles:3 (1850038478268896762) -->
+ <!-- no translation found for volume_stream_titles:4 (8265110906352372092) -->
+ <!-- no translation found for volume_stream_titles:6 (2951313578278086204) -->
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。点按即可取消静音。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。点按即可设为振动,但可能会同时将无障碍服务设为静音。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。点按即可设为静音,但可能会同时将无障碍服务设为静音。"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
index e29dec396dea..db9b2c873c18 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"这样会固定显示您的视频,直到您播放其他视频为止。按住"<b>"主屏幕"</b>"按钮即可控制该功能。"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"知道了"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"关闭"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 40d342961450..9d25d711d885 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -143,6 +143,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"4G+"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"漫遊"</string>
@@ -436,6 +437,18 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」為音量對話框"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"輕按即可復原。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您正在使用工作設定檔"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"通話"</item>
+ <item msgid="5997713001067658559">"系統"</item>
+ <item msgid="7858983209929864160">"鈴聲"</item>
+ <item msgid="1850038478268896762">"媒體"</item>
+ <item msgid="8265110906352372092">"鬧鐘"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"藍牙"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。輕按即可取消靜音。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。輕按即可設為震動。無障礙功能服務可能已經設為靜音。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。輕按即可設為靜音。無障礙功能服務可能已經設為靜音。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
index bc164c8765c5..deba65ba8c49 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"這讓您繼續觀看影片,直至您播放下一部影片。按住"<b>"主按鈕"</b>"即可控制「畫中畫」。"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"知道了"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"關閉"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 7f03c5d8e19e..8979b85c5cd9 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -143,6 +143,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"4G+"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"漫遊中"</string>
@@ -434,6 +435,18 @@
<string name="volumeui_notification_title" msgid="4906770126345910955">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」現在是預設的音量控制對話方塊。"</string>
<string name="volumeui_notification_text" msgid="8819536904234337445">"輕觸即可恢復原始設定。"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"您正在使用 Work 設定檔"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"通話"</item>
+ <item msgid="5997713001067658559">"系統"</item>
+ <item msgid="7858983209929864160">"鈴聲"</item>
+ <item msgid="1850038478268896762">"媒體"</item>
+ <item msgid="8265110906352372092">"鬧鐘"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"藍牙"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s。輕觸即可取消靜音。"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s。輕觸即可設為震動,但系統可能會將無障礙服務一併設為靜音。"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s。輕觸即可設為靜音,但系統可能會將無障礙服務一併設為靜音。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
index 583a6ed92442..890995cbf4cf 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"您的影片會一直顯示在畫面中,直到您播放其他影片為止。按住 [HOME] (主畫面) 按鈕即可控制子母畫面。"<b></b></string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"我知道了"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"關閉"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index bedaeca11beb..b4526bd03156 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -143,6 +143,7 @@
<string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
<string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
<string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_4g_plus" msgid="3032226872470658661">"4G+"</string>
<string name="accessibility_data_connection_lte" msgid="5413468808637540658">"I-LTE"</string>
<string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Iyazulazula"</string>
@@ -434,6 +435,18 @@
<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="8819536904234337445">"Thepha ukuze ubuyisele okwasekuqaleni."</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Usebenzisa iphrofayela yakho yomsebenzi"</string>
+ <string-array name="volume_stream_titles">
+ <item msgid="5841843895402729630">"Shayela"</item>
+ <item msgid="5997713001067658559">"Isistimu"</item>
+ <item msgid="7858983209929864160">"Khalisa"</item>
+ <item msgid="1850038478268896762">"Abezindaba"</item>
+ <item msgid="8265110906352372092">"I-Alamu"</item>
+ <item msgid="5339394737636839168"></item>
+ <item msgid="2951313578278086204">"I-Bluetooth"</item>
+ <item msgid="2919807739709798970"></item>
+ <item msgid="150349973435223405"></item>
+ <item msgid="6761963760295549099"></item>
+ </string-array>
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$s. Thepha ukuze ususe ukuthula."</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$s. Thepha ukuze usethe ukudlidliza. Amasevisi okufinyelela angathuliswa."</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s. Thepha ukuze uthulise. Amasevisi okufinyelela angathuliswa."</string>
diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml
index e1d0b5bec917..71c2e09369e8 100644
--- a/packages/SystemUI/res/values-zu/strings_tv.xml
+++ b/packages/SystemUI/res/values-zu/strings_tv.xml
@@ -28,4 +28,6 @@
<string name="pip_onboarding_description" msgid="4028124563309465267">"Lokhu kugcina ividiyo yakho ibonakala uze udlale enye. Cindezela futhi ubambe okuthi "<b>"EKHAYA"</b>" ukuze uyilawule."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Ngiyezwa"</string>
<string name="recents_tv_dismiss" msgid="3555093879593377731">"Cashisa"</string>
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index cb5164945923..d12ef42590dc 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -30,9 +30,6 @@
<color name="batterymeter_charge_color">#FFFFFFFF</color>
<color name="batterymeter_bolt_color">#FFFFFFFF</color>
<color name="qs_batterymeter_frame_color">#FF404040</color>
- <color name="system_primary_color">#ff263238</color><!-- blue grey 900 -->
- <color name="system_secondary_color">#ff37474F</color><!-- blue grey 800 -->
- <color name="system_accent_color">#ff80CBC4</color><!-- deep teal 200 -->
<color name="system_warning_color">#fff4511e</color><!-- deep orange 600 -->
<color name="qs_text">#FFFFFFFF</color>
<color name="qs_tile_divider">#29ffffff</color><!-- 16% white -->
@@ -41,7 +38,6 @@
<color name="qs_detail_button">#FFB0BEC5</color><!-- 100% blue grey 200 -->
<color name="qs_detail_button_white">#B3FFFFFF</color><!-- 70% white -->
<color name="qs_detail_transition">#66FFFFFF</color>
- <color name="qs_detail_progress_track">#99009688</color><!-- 60% deep teal 500 -->
<color name="data_usage_secondary">#99FFFFFF</color><!-- 60% white -->
<color name="data_usage_graph_track">#33FFFFFF</color><!-- 20% white -->
<color name="data_usage_graph_warning">#FFFFFFFF</color>
@@ -99,15 +95,11 @@
<!-- The color of the ripples on the tinted notifications -->
<color name="notification_ripple_tinted_color">#30ffffff</color>
- <!-- The color of the circle around the primary user in the user switcher -->
- <color name="current_user_border_color">@color/system_accent_color</color>
-
<!-- The color of the gear shown behind a notification -->
<color name="notification_gear_color">#ff757575</color>
<!-- The "inside" of a notification, reached via longpress -->
<color name="notification_guts_bg_color">#eeeeee</color>
- <color name="notification_guts_slider_color">@*android:color/material_deep_teal_500</color>
<color name="notification_guts_disabled_slider_color">@*android:color/material_grey_300</color>
<color name="notification_guts_secondary_slider_color">#858383</color>
<color name="notification_guts_icon_tint">#8a000000</color>
@@ -126,8 +118,6 @@
<!-- Shadow color for the furthest pixels around the fake shadow for recents. -->
<color name="fake_shadow_end_color">#03000000</color>
- <color name="screen_pinning_nav_icon_highlight_outer">#4080cbc4</color><!-- 25% deep teal 200 -->
- <color name="screen_pinning_request_bg">#ff009688</color><!-- deep teal 500 -->
<color name="screen_pinning_request_window_bg">#80000000</color>
<color name="segmented_buttons_background">#14FFFFFF</color><!-- 8% white -->
@@ -142,14 +132,10 @@
<color name="light_mode_icon_color_dual_tone_background">#4dffffff</color>
<color name="light_mode_icon_color_dual_tone_fill">#ffffff</color>
- <color name="zen_introduction_message_background">#ff009688</color><!-- deep teal 500 -->
<color name="volume_icon_color">#ffffffff</color>
<color name="volume_settings_icon_color">#7fffffff</color>
<color name="volume_slider_inactive">#FFB0BEC5</color><!-- blue grey 200 -->
- <color name="fab_ripple">#1fffffff</color><!-- 12% white -->
- <color name="fab_shape">#ff009688</color><!-- Teal 500 -->
-
<color name="docked_divider_background">#ff000000</color>
<color name="docked_divider_handle">#ffffff</color>
<drawable name="forced_resizable_background">#59000000</drawable>
@@ -166,16 +152,10 @@
<color name="qs_tile_tint_inactive">#4dffffff</color>
<color name="qs_tile_tint_active">#ffffffff</color>
- <color name="switch_bar_background">#ff37474f</color>
- <color name="switch_accent_color">#ff7fcac3</color>
-
<!-- Keyboard shortcuts colors -->
- <color name="ksh_system_group_color">@color/material_deep_teal_500</color>
<color name="ksh_application_group_color">#fff44336</color>
<color name="ksh_keyword_color">#d9000000</color>
<color name="ksh_key_item_color">@color/material_grey_600</color>
<color name="ksh_key_item_background">@color/material_grey_100</color>
- <!-- Background color of edit overflow -->
- <color name="qs_edit_overflow_bg">#455A64</color>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index eef57171db41..0365e800f34a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -535,6 +535,19 @@
<!-- Volume dialog root view bottom margin, at rest -->
<dimen name="volume_dialog_margin_bottom">4dp</dimen>
+ <dimen name="volume_dialog_collapsed_padding_top">8dp</dimen>
+ <dimen name="volume_dialog_expanded_padding_top">22dp</dimen>
+ <dimen name="volume_dialog_padding_end">40dp</dimen>
+
+ <dimen name="volume_row_padding_bottom">9.4dp</dimen>
+ <dimen name="volume_row_padding_start">4dp</dimen>
+ <dimen name="volume_row_header_padding_start">16dp</dimen>
+ <dimen name="volume_row_height">64dp</dimen>
+ <dimen name="volume_row_slider_height">48dp</dimen>
+ <dimen name="volume_row_slider_padding_start">12dp</dimen>
+
+ <dimen name="volume_expander_margin_end">2dp</dimen>
+ <dimen name="volume_expander_margin_top">6dp</dimen>
<!-- Padding between icon and text for managed profile toast -->
<dimen name="managed_profile_toast_padding">4dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index f7a169cb4d5b..4f523f3f8138 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -348,6 +348,9 @@
<!-- Content description of the data connection type 4G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_data_connection_4g">4G</string>
+ <!-- Content description of the data connection type 4G for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_data_connection_4g_plus">4G+</string>
+
<!-- Content description of the data connection type LTE for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_data_connection_lte">LTE</string>
@@ -1093,14 +1096,14 @@
<!-- Toast shown when user unlocks screen and managed profile activity is in the foreground -->
<string name="managed_profile_foreground_toast">You\'re using your work profile</string>
- <string-array name="volume_stream_titles" translatable="false">
- <item>Voice calls</item> <!-- STREAM_VOICE_CALL -->
+ <string-array name="volume_stream_titles">
+ <item>Call</item> <!-- STREAM_VOICE_CALL -->
<item>System</item> <!-- STREAM_SYSTEM -->
- <item>Notifications</item> <!-- STREAM_RING -->
+ <item>Ring</item> <!-- STREAM_RING -->
<item>Media</item> <!-- STREAM_MUSIC -->
- <item>Alarms</item> <!-- STREAM_ALARM -->
+ <item>Alarm</item> <!-- STREAM_ALARM -->
<item></item> <!-- STREAM_NOTIFICATION -->
- <item>Bluetooth calls</item> <!-- STREAM_BLUETOOTH_SCO -->
+ <item>Bluetooth</item> <!-- STREAM_BLUETOOTH_SCO -->
<item></item> <!-- STREAM_SYSTEM_ENFORCED -->
<item></item> <!-- STREAM_DTMF -->
<item></item> <!-- STREAM_TTS -->
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index b1d23d899852..f49d2019873c 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -44,4 +44,8 @@
<string name="font_roboto_regular" translatable="false">sans-serif</string>
<!-- DO NOT TRANSLATE -->
<string name="font_roboto_light" translatable="false">sans-serif-light</string>
+ <!-- Package names to be blacklisted in Recents, add package names into overlay as needed -->
+ <string-array name="recents_tv_blacklist_array">
+ </string-array>
+
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index aeb484f8ffc4..e5681ce517f9 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -132,7 +132,7 @@
<style name="TextAppearance.QS.DetailItemSecondary">
<item name="android:textSize">@dimen/qs_detail_item_secondary_text_size</item>
- <item name="android:textColor">@color/system_accent_color</item>
+ <item name="android:textColor">?android:attr/colorAccent</item>
</style>
<style name="TextAppearance.QS.Introduction">
@@ -177,7 +177,7 @@
<style name="TextAppearance.QS.DataUsage.Usage">
<item name="android:textSize">@dimen/qs_data_usage_usage_text_size</item>
- <item name="android:textColor">@color/system_accent_color</item>
+ <item name="android:textColor">?android:attr/colorAccent</item>
</style>
<style name="TextAppearance.QS.DataUsage.Secondary">
@@ -217,19 +217,13 @@
<style name="Animation.StatusBar">
</style>
- <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault">
- <item name="android:colorPrimary">@color/system_primary_color</item>
- <item name="android:colorControlActivated">@color/system_accent_color</item>
- </style>
+ <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault" />
<style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
<item name="android:colorAccent">@color/remote_input_accent</item>
</style>
- <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog">
- <item name="android:colorPrimary">@color/system_primary_color</item>
- <item name="android:colorControlActivated">@color/system_accent_color</item>
- </style>
+ <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog" />
<style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
@@ -320,12 +314,12 @@
<item name="android:layout_height">48dp</item>
</style>
- <style name="TunerSettings" parent="@android:style/Theme.Material.Settings">
+ <style name="TunerSettings" parent="@android:style/Theme.DeviceDefault.Settings">
<item name="android:windowActionBar">false</item>
<item name="preferenceTheme">@style/TunerPreferenceTheme</item>
</style>
- <style name="TunerPreferenceTheme" parent="@android:style/Theme.Material.Settings">
+ <style name="TunerPreferenceTheme" parent="@android:style/Theme.DeviceDefault.Settings">
<item name="dropdownPreferenceStyle">@style/Preference.DropDown.Material</item>
</style>
@@ -341,16 +335,16 @@
</style>
<style name="TextAppearance.NotificationGuts.Secondary">
- <item name="android:alpha">.54</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
<style name="TextAppearance.NotificationGuts.Primary">
- <item name="android:alpha">.87</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textSize">16sp</item>
</style>
<style name="TextAppearance.NotificationGuts.Radio">
- <item name="android:alpha">.87</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="TextAppearance.NotificationGuts.Button">
@@ -358,15 +352,11 @@
<item name="android:textAllCaps">true</item>
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:gravity">center</item>
- <item name="android:textColor">@*android:color/material_deep_teal_500</item>
- </style>
-
- <style name="ThemeOverlay.SwitchBar" parent="@android:style/ThemeOverlay">
- <item name="android:colorAccent">@color/switch_accent_color</item>
+ <item name="android:textColor">?android:attr/colorAccent</item>
</style>
- <style name="edit_theme" parent="@android:style/Theme.Material">
- <item name="android:colorBackground">@color/qs_edit_overflow_bg</item>
+ <style name="edit_theme" parent="@*android:style/Theme.DeviceDefault.Settings.Dark">
+ <item name="android:colorBackground">?android:attr/colorSecondary</item>
</style>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index 85befff9eed3..f30baee35f3a 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -16,8 +16,10 @@
package com.android.systemui;
+import android.app.Notification;
import android.content.Context;
import android.content.res.Configuration;
+import android.os.Bundle;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -48,4 +50,12 @@ public abstract class SystemUI {
mComponents.put(interfaceType, component);
}
}
+
+ public static void overrideNotificationAppName(Context context, Notification.Builder n) {
+ final Bundle extras = new Bundle();
+ extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
+ context.getString(com.android.internal.R.string.android_system_label));
+
+ n.addExtras(extras);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3bbcf6eb99c5..42a9ed502701 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -926,6 +926,11 @@ public class KeyguardViewMediator extends SystemUI {
// In this case, send out ACTION_USER_PRESENT here instead of in
// handleKeyguardDone()
sendUserPresentBroadcast();
+ } else if (mSystemReady && shouldWaitForProvisioning()) {
+ // Skipping the lockscreen because we're not yet provisioned, but we still need to
+ // notify the StrongAuthTracker that it's now safe to run trust agents, in case the
+ // user sets a credential later.
+ getLockPatternUtils().userPresent(KeyguardUpdateMonitor.getCurrentUser());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index ea1c9bf3b853..b831235d1179 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -38,6 +38,7 @@ import android.provider.Settings;
import android.util.Slog;
import com.android.systemui.R;
+import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -143,6 +144,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setColor(mContext.getColor(
com.android.internal.R.color.system_notification_accent_color));
+ SystemUI.overrideNotificationAppName(mContext, nb);
final Notification n = nb.build();
mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
}
@@ -173,8 +175,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
attachLowBatterySound(nb);
mPlaySound = false;
}
- final Notification n = nb.build();
- mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, n, UserHandle.ALL);
+ SystemUI.overrideNotificationAppName(mContext, nb);
+ mNoMan.notifyAsUser(TAG_NOTIFICATION, R.id.notification_power, nb.build(), UserHandle.ALL);
}
private PendingIntent pendingActivity(Intent intent) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
index aff5d2b95531..5f23a40ab3b8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
@@ -24,6 +24,7 @@ import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
+import com.android.settingslib.Utils;
import com.android.systemui.R;
public class DataUsageGraph extends View {
@@ -45,7 +46,7 @@ public class DataUsageGraph extends View {
super(context, attrs);
final Resources res = context.getResources();
mTrackColor = context.getColor(R.color.data_usage_graph_track);
- mUsageColor = context.getColor(R.color.system_accent_color);
+ mUsageColor = Utils.getColorAccent(context);
mOverlimitColor = context.getColor(R.color.system_warning_color);
mWarningColor = context.getColor(R.color.data_usage_graph_warning);
mMarkerWidth = res.getDimensionPixelSize(R.dimen.data_usage_graph_marker_width);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index e9a03f2ec2e8..ce6aa7183356 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -358,7 +358,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback {
}
};
r.tileView.init(click, longClick);
- callback.onStateChanged(r.tile.getState());
r.tile.refreshState();
mRecords.add(r);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 974de0804f64..27b079a06c99 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -225,7 +225,7 @@ public abstract class QSTile<TState extends State> {
private void handleAddCallback(Callback callback) {
mCallbacks.add(callback);
- handleRefreshState(null);
+ callback.onStateChanged(mState);
}
private void handleRemoveCallback(Callback callback) {
@@ -634,6 +634,18 @@ public abstract class QSTile<TState extends State> {
}
}
+ public static class AirplaneBooleanState extends BooleanState {
+ public boolean isAirplaneMode;
+
+ @Override
+ public boolean copyTo(State other) {
+ final AirplaneBooleanState o = (AirplaneBooleanState) other;
+ final boolean changed = super.copyTo(other) || o.isAirplaneMode != isAirplaneMode;
+ o.isAirplaneMode = isAirplaneMode;
+ return changed;
+ }
+ }
+
public static final class SignalState extends BooleanState {
public boolean connected;
public boolean activityIn;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index afc987e26d23..f09275ddc0de 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -113,6 +113,11 @@ public class QuickQSPanel extends QSPanel {
}
@Override
+ protected void onTileClick(QSTile<?> tile) {
+ tile.secondaryClick();
+ }
+
+ @Override
public void onTuningChanged(String key, String newValue) {
// No tunings for you.
if (key.equals(QS_SHOW_BRIGHTNESS)) {
@@ -130,7 +135,7 @@ public class QuickQSPanel extends QSPanel {
break;
}
}
- super.setTiles(quickTiles, false);
+ super.setTiles(quickTiles, true);
}
private final Tunable mNumTiles = new Tunable() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 8a0079d2c537..0de1e3022b6c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -233,6 +233,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
setVisibility(View.GONE);
}
mNotifQsContainer.setCustomizerAnimating(false);
+ mRecyclerView.setAdapter(mTileAdapter);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 60c24d095aa7..3a693cff7cc9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -19,6 +19,7 @@ import android.app.AlertDialog.Builder;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
@@ -37,6 +38,7 @@ import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
import android.widget.TextView;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto;
import com.android.systemui.R;
@@ -70,6 +72,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
private final Handler mHandler = new Handler();
private final List<TileInfo> mTiles = new ArrayList<>();
private final ItemTouchHelper mItemTouchHelper;
+ private final ItemDecoration mDecoration;
private final AccessibilityManager mAccessibilityManager;
private int mEditIndex;
private int mTileDividerIndex;
@@ -87,6 +90,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
mContext = context;
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mItemTouchHelper = new ItemTouchHelper(mCallbacks);
+ mDecoration = new TileItemDecoration(context);
}
public void setHost(QSTileHost host) {
@@ -111,6 +115,9 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
}
public void setTileSpecs(List<String> currentSpecs) {
+ if (currentSpecs.equals(mCurrentSpecs)) {
+ return;
+ }
mCurrentSpecs = currentSpecs;
recalcSpecs();
}
@@ -227,6 +234,8 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
});
if (mNeedsFocus) {
// Wait for this to get laid out then set its focus.
+ // Ensure that tile gets laid out so we get the callback.
+ holder.mTileView.requestLayout();
holder.mTileView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
@@ -254,7 +263,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
}
holder.mTileView.onStateChanged(info.state);
holder.mTileView.setAppLabel(info.appLabel);
- holder.mTileView.setShowAppLabel(mTileDividerIndex > -1 && position > mTileDividerIndex);
+ holder.mTileView.setShowAppLabel(position > mEditIndex && !info.isSystem);
if (mAccessibilityManager.isTouchExplorationEnabled()) {
final boolean selectable = !mAccessibilityMoving || position < mEditIndex;
@@ -289,13 +298,11 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
mTiles.remove(mEditIndex--);
notifyItemRemoved(mEditIndex - 1);
move(mAccessibilityFromIndex, position, v);
- updateDividerLocations();
notifyDataSetChanged();
- saveSpecs(mHost);
}
private void showAccessibilityDialog(final int position, final View v) {
- TileInfo info = mTiles.get(position);
+ final TileInfo info = mTiles.get(position);
CharSequence[] options = new CharSequence[] {
mContext.getString(R.string.accessibility_qs_edit_move_tile, info.state.label),
mContext.getString(R.string.accessibility_qs_edit_remove_tile, info.state.label),
@@ -307,7 +314,9 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
if (which == 0) {
startAccessibleDrag(position);
} else {
- move(position, mEditIndex, v);
+ move(position, info.isSystem ? mEditIndex : mTileDividerIndex, v);
+ notifyItemChanged(mTileDividerIndex);
+ notifyDataSetChanged();
}
}
}).setNegativeButton(android.R.string.cancel, null)
@@ -331,40 +340,12 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
}
private boolean move(int from, int to, View v) {
- if (to >= mEditIndex) {
- if (from < mEditIndex) {
- // Removing a tile.
- // Sort tiles into system/non-system groups.
- TileInfo tile = mTiles.get(from);
- if (tile.isSystem) {
- if (to > mTileDividerIndex) {
- to = mTileDividerIndex;
- }
- } else {
- if (mTileDividerIndex == mTiles.size() - 1) {
- notifyItemChanged(mTileDividerIndex);
- }
- if (to <= mTileDividerIndex) {
- to = mTileDividerIndex;
- }
- }
- } else {
- if (to > mEditIndex) {
- // Don't allow tiles to be dragged around when they aren't added.
- to = from;
- }
- // Allow the case where to == mEditIndex to fall through and swap which
- // side the tile is currently on.
- // This lets the the cases where all tiles are on one side of the line
- // work.
- }
+ if (to == from) {
+ return true;
}
CharSequence fromLabel = mTiles.get(from).state.label;
move(from, to, mTiles);
updateDividerLocations();
- if (to == from) {
- return true;
- }
CharSequence announcement;
if (to >= mEditIndex) {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_REMOVE_SPEC,
@@ -424,7 +405,6 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
private <T> void move(int from, int to, List<T> list) {
list.add(to, list.remove(from));
notifyItemMoved(from, to);
- notifyItemChanged(to);
}
public class Holder extends ViewHolder {
@@ -482,9 +462,16 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
}
};
- private final ItemDecoration mDecoration = new ItemDecoration() {
- // TODO: Move this to resource.
- private final ColorDrawable mDrawable = new ColorDrawable(0xff384248);
+ private class TileItemDecoration extends ItemDecoration {
+ private final ColorDrawable mDrawable;
+
+ private TileItemDecoration(Context context) {
+ TypedArray ta =
+ context.obtainStyledAttributes(new int[]{android.R.attr.colorSecondary});
+ mDrawable = new ColorDrawable(ta.getColor(0, 0));
+ ta.recycle();
+ }
+
@Override
public void onDraw(Canvas c, RecyclerView parent, State state) {
@@ -496,7 +483,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final ViewHolder holder = parent.getChildViewHolder(child);
- if (holder.getAdapterPosition() < mEditIndex) {
+ if (holder.getAdapterPosition() < mEditIndex && !(child instanceof TextView)) {
continue;
}
@@ -527,7 +514,15 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
@Override
public void onSelectedChanged(ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
+ if (actionState != ItemTouchHelper.ACTION_STATE_DRAG) {
+ viewHolder = null;
+ }
+ if (viewHolder == mCurrentDrag) return;
if (mCurrentDrag != null) {
+ int position = mCurrentDrag.getAdapterPosition();
+ TileInfo info = mTiles.get(position);
+ mCurrentDrag.mTileView.setShowAppLabel(
+ position > mEditIndex && !info.isSystem);
mCurrentDrag.stopDrag();
mCurrentDrag = null;
}
@@ -544,6 +539,12 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
}
@Override
+ public boolean canDropOver(RecyclerView recyclerView, ViewHolder current,
+ ViewHolder target) {
+ return target.getAdapterPosition() <= mEditIndex + 1;
+ }
+
+ @Override
public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) {
if (viewHolder.getItemViewType() == TYPE_EDIT) {
return makeMovementFlags(0, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 3d192e5c185f..40ef6eb999db 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -161,7 +161,7 @@ public class TileQueryHelper {
addTile(spec, appLabel, state, false);
continue;
}
- if (info.serviceInfo.icon == 0) {
+ if (info.serviceInfo.icon == 0 && info.serviceInfo.applicationInfo.icon == 0) {
continue;
}
Drawable icon = info.serviceInfo.loadIcon(pm);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 23a3ca128de2..569a567c25fa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -71,29 +71,29 @@ public class CustomTile extends QSTile<QSTile.State> implements TileChangeListen
super(host);
mWindowManager = WindowManagerGlobal.getWindowManagerService();
mComponent = ComponentName.unflattenFromString(action);
+ mTile = new Tile(mComponent);
+ setTileIcon();
mServiceManager = host.getTileServices().getTileWrapper(this);
mService = mServiceManager.getTileService();
mServiceManager.setTileChangeListener(this);
- mTile = new Tile(mComponent);
mUser = ActivityManager.getCurrentUser();
- setTileIcon();
- try {
- mService.setQSTile(mTile);
- } catch (RemoteException e) {
- // Called through wrapper, won't happen here.
- }
}
private void setTileIcon() {
try {
PackageManager pm = mContext.getPackageManager();
- ServiceInfo info = pm.getServiceInfo(mComponent,
- PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+ int flags = PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+ if (isSystemApp(pm)) {
+ flags |= PackageManager.MATCH_DISABLED_COMPONENTS;
+ }
+ ServiceInfo info = pm.getServiceInfo(mComponent, flags);
+ int icon = info.icon != 0 ? info.icon
+ : info.applicationInfo.icon;
// Update the icon if its not set or is the default icon.
boolean updateIcon = mTile.getIcon() == null
|| iconEquals(mTile.getIcon(), mDefaultIcon);
- mDefaultIcon = info.icon != 0 ? android.graphics.drawable.Icon
- .createWithResource(mComponent.getPackageName(), info.icon) : null;
+ mDefaultIcon = icon != 0 ? android.graphics.drawable.Icon
+ .createWithResource(mComponent.getPackageName(), icon) : null;
if (updateIcon) {
mTile.setIcon(mDefaultIcon);
}
@@ -106,6 +106,10 @@ public class CustomTile extends QSTile<QSTile.State> implements TileChangeListen
}
}
+ private boolean isSystemApp(PackageManager pm) throws PackageManager.NameNotFoundException {
+ return pm.getApplicationInfo(mComponent.getPackageName(), 0).isSystemApp();
+ }
+
/**
* Compare two icons, only works for resources.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
index 3830ac50c60b..407453c6e3b2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
@@ -35,16 +35,6 @@ public class QSTileServiceWrapper {
return mService.asBinder();
}
- public boolean setQSTile(Tile tile) {
- try {
- mService.setQSTile(tile);
- return true;
- } catch (Exception e) {
- Log.d(TAG, "Caught exception from TileService", e);
- return false;
- }
- }
-
public boolean onTileAdded() {
try {
mService.onTileAdded();
@@ -95,16 +85,6 @@ public class QSTileServiceWrapper {
}
}
- public boolean setQSService(IQSService service) {
- try {
- mService.setQSService(service);
- return true;
- } catch (Exception e) {
- Log.d(TAG, "Caught exception from TileService", e);
- return false;
- }
- }
-
public boolean onUnlockComplete() {
try {
mService.onUnlockComplete();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 87d6307ffce2..79f9de6b4bf7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -71,23 +71,24 @@ public class TileLifecycleManager extends BroadcastReceiver implements
private Set<Integer> mQueuedMessages = new ArraySet<>();
private QSTileServiceWrapper mWrapper;
private boolean mListening;
- private Tile mTile;
private IBinder mClickBinder;
private int mBindTryCount;
private boolean mBound;
@VisibleForTesting
boolean mReceiverRegistered;
- private IQSService mService;
private boolean mUnbindImmediate;
private TileChangeListener mChangeListener;
// Return value from bindServiceAsUser, determines whether safe to call unbind.
private boolean mIsBound;
- public TileLifecycleManager(Handler handler, Context context, Intent intent, UserHandle user) {
+ public TileLifecycleManager(Handler handler, Context context, IQSService service,
+ Tile tile, Intent intent, UserHandle user) {
mContext = context;
mHandler = handler;
mIntent = intent;
+ mIntent.putExtra(TileService.EXTRA_SERVICE, service.asBinder());
+ mIntent.putExtra(TileService.EXTRA_COMPONENT, intent.getComponent());
mUser = user;
if (DEBUG) Log.d(TAG, "Creating " + mIntent + " " + mUser);
}
@@ -164,14 +165,6 @@ public class TileLifecycleManager extends BroadcastReceiver implements
service.linkToDeath(this, 0);
} catch (RemoteException e) {
}
- if (!wrapper.setQSService(mService)) {
- handleDeath();
- return;
- }
- if (!wrapper.setQSTile(mTile)) {
- handleDeath();
- return;
- }
mWrapper = wrapper;
handlePendingMessages();
}
@@ -255,15 +248,6 @@ public class TileLifecycleManager extends BroadcastReceiver implements
}
}
- @Override
- public void setQSTile(Tile tile) {
- if (DEBUG) Log.d(TAG, "setQSTile " + tile);
- mTile = tile;
- if (mWrapper != null && !mWrapper.setQSTile(tile)) {
- handleDeath();
- }
- }
-
private boolean checkComponentState() {
PackageManager pm = mContext.getPackageManager();
if (!isPackageAvailable(pm) || !isComponentAvailable(pm)) {
@@ -347,14 +331,6 @@ public class TileLifecycleManager extends BroadcastReceiver implements
}
@Override
- public void setQSService(IQSService service) {
- mService = service;
- if (mWrapper == null || !mWrapper.setQSService(service)) {
- handleDeath();
- }
- }
-
- @Override
public void onTileAdded() {
if (DEBUG) Log.d(TAG, "onTileAdded");
if (mWrapper == null || !mWrapper.onTileAdded()) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index ce9bbf42679a..3d030f977fbc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -27,6 +27,7 @@ import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.service.quicksettings.IQSTileService;
+import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
@@ -68,9 +69,10 @@ public class TileServiceManager {
// This defaults to true to ensure tiles start out unavailable.
private boolean mPendingBind = true;
- TileServiceManager(TileServices tileServices, Handler handler, ComponentName component) {
+ TileServiceManager(TileServices tileServices, Handler handler, ComponentName component,
+ Tile tile) {
this(tileServices, handler, new TileLifecycleManager(handler,
- tileServices.getContext(), new Intent().setComponent(component),
+ tileServices.getContext(), tileServices, tile, new Intent().setComponent(component),
new UserHandle(ActivityManager.getCurrentUser())));
}
@@ -80,7 +82,6 @@ public class TileServiceManager {
mServices = tileServices;
mHandler = handler;
mStateManager = tileLifecycleManager;
- mStateManager.setQSService(tileServices);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 2ab6b5fc98e9..6f0bed2f5445 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -78,7 +78,7 @@ public class TileServices extends IQSService.Stub {
public TileServiceManager getTileWrapper(CustomTile tile) {
ComponentName component = tile.getComponent();
- TileServiceManager service = onCreateTileService(component);
+ TileServiceManager service = onCreateTileService(component, tile.getQsTile());
synchronized (mServices) {
mServices.put(tile, service);
mTiles.put(component, tile);
@@ -86,8 +86,8 @@ public class TileServices extends IQSService.Stub {
return service;
}
- protected TileServiceManager onCreateTileService(ComponentName component) {
- return new TileServiceManager(this, mHandler, component);
+ protected TileServiceManager onCreateTileService(ComponentName component, Tile tile) {
+ return new TileServiceManager(this, mHandler, component, tile);
}
public void freeService(CustomTile tile, TileServiceManager service) {
@@ -263,6 +263,16 @@ public class TileServices extends IQSService.Stub {
}
@Override
+ public Tile getTile(ComponentName componentName) {
+ verifyCaller(componentName.getPackageName());
+ CustomTile customTile = getTileForComponent(componentName);
+ if (customTile != null) {
+ return customTile.getQsTile();
+ }
+ return null;
+ }
+
+ @Override
public void startUnlockAndRun(Tile tile) {
ComponentName componentName = tile.getComponentName();
verifyCaller(componentName.getPackageName());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 18191cf782dc..0de5105485dc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -95,14 +95,6 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
}
@Override
- protected void handleSecondaryClick() {
- boolean dataEnabled = mDataController.isMobileDataSupported()
- && mDataController.isMobileDataEnabled();
- MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, !dataEnabled);
- mDataController.setMobileDataEnabled(!dataEnabled);
- }
-
- @Override
public CharSequence getTileLabel() {
return mContext.getString(R.string.quick_settings_cellular_detail_title);
}
@@ -152,8 +144,8 @@ public class CellularTile extends QSTile<QSTile.SignalState> {
}
state.contentDescription = state.contentDescription + "," + r.getString(
R.string.accessibility_quick_settings_open_settings, getTileLabel());
- state.expandedAccessibilityClassName = Button.class.getName();
- state.minimalAccessibilityClassName = Switch.class.getName();
+ state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
+ = Button.class.getName();
state.value = mDataController.isMobileDataSupported()
&& mDataController.isMobileDataEnabled();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index bad4e7971904..a63eabc8ad85 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -16,6 +16,7 @@
package com.android.systemui.qs.tiles;
+import android.annotation.ColorInt;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -24,6 +25,7 @@ import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.settingslib.Utils;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
@@ -64,7 +66,7 @@ public class DataUsageDetailView extends LinearLayout {
final Resources res = mContext.getResources();
final int titleId;
final long bytes;
- int usageColor = R.color.system_accent_color;
+ @ColorInt int usageColor = 0;
final String top;
String bottom = null;
if (info.usageLevel < info.warningLevel || info.limitLevel <= 0) {
@@ -89,14 +91,18 @@ public class DataUsageDetailView extends LinearLayout {
formatBytes(info.usageLevel));
bottom = res.getString(R.string.quick_settings_cellular_detail_data_limit,
formatBytes(info.limitLevel));
- usageColor = R.color.system_warning_color;
+ usageColor = mContext.getColor(R.color.system_warning_color);
+ }
+
+ if (usageColor == 0) {
+ usageColor = Utils.getColorAccent(mContext);
}
final TextView title = (TextView) findViewById(android.R.id.title);
title.setText(titleId);
final TextView usage = (TextView) findViewById(R.id.usage_text);
usage.setText(formatBytes(bytes));
- usage.setTextColor(mContext.getColor(usageColor));
+ usage.setTextColor(usageColor);
final DataUsageGraph graph = (DataUsageGraph) findViewById(R.id.usage_graph);
graph.setLevels(info.limitLevel, info.warningLevel, info.usageLevel);
final TextView carrier = (TextView) findViewById(R.id.usage_carrier_text);
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 1c134c1e1424..016c4b70f485 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -36,15 +36,16 @@ import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.HotspotController;
/** Quick settings tile: Hotspot **/
-public class HotspotTile extends QSTile<QSTile.BooleanState> {
+public class HotspotTile extends QSTile<QSTile.AirplaneBooleanState> {
private final AnimationIcon mEnable =
new AnimationIcon(R.drawable.ic_hotspot_enable_animation,
R.drawable.ic_hotspot_disable);
private final AnimationIcon mDisable =
new AnimationIcon(R.drawable.ic_hotspot_disable_animation,
R.drawable.ic_hotspot_enable);
- private final Icon mUnavailable =
- ResourceIcon.get(R.drawable.ic_hotspot_unavailable);
+ private final Icon mDisableNoAnimation = ResourceIcon.get(R.drawable.ic_hotspot_enable);
+ private final Icon mUnavailable = ResourceIcon.get(R.drawable.ic_hotspot_unavailable);
+
private final HotspotController mController;
private final Callback mCallback = new Callback();
private final GlobalSetting mAirplaneMode;
@@ -72,8 +73,8 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
}
@Override
- public BooleanState newTileState() {
- return new BooleanState();
+ public AirplaneBooleanState newTileState() {
+ return new AirplaneBooleanState();
}
@Override
@@ -84,10 +85,9 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
mController.addCallback(mCallback);
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- mContext.registerReceiver(mReceiver, filter);
+ refreshState();
} else {
mController.removeCallback(mCallback);
- mContext.unregisterReceiver(mReceiver);
}
mAirplaneMode.setListening(listening);
}
@@ -113,7 +113,7 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
}
@Override
- protected void handleUpdateState(BooleanState state, Object arg) {
+ protected void handleUpdateState(AirplaneBooleanState state, Object arg) {
state.label = mContext.getString(R.string.quick_settings_hotspot_label);
checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_TETHERING);
@@ -123,12 +123,16 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
state.value = mController.isHotspotEnabled();
}
state.icon = state.value ? mEnable : mDisable;
- if (mAirplaneMode.getValue() != 0) {
+ boolean wasAirplane = state.isAirplaneMode;
+ state.isAirplaneMode = mAirplaneMode.getValue() != 0;
+ if (state.isAirplaneMode) {
final int disabledColor = mHost.getContext().getColor(R.color.qs_tile_tint_unavailable);
state.label = new SpannableStringBuilder().append(state.label,
new ForegroundColorSpan(disabledColor),
SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
state.icon = mUnavailable;
+ } else if (wasAirplane) {
+ state.icon = mDisableNoAnimation;
}
state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
= Switch.class.getName();
@@ -155,13 +159,4 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
refreshState(enabled);
}
};
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
- refreshState();
- }
- }
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index b20f46f6b1f5..7e1deec3429a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -184,7 +184,9 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
null, false);
reloadResources();
+ }
+ public void onBootCompleted() {
// When we start, preload the data associated with the previous recent tasks.
// We can use a new plan since the caches will be the same.
RecentsTaskLoader loader = Recents.getTaskLoader();
@@ -197,10 +199,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
loader.loadTasks(mContext, plan, launchOpts);
}
- public void onBootCompleted() {
- // Do nothing
- }
-
public void onConfigurationChanged() {
reloadResources();
mDummyStackView.reloadOnConfigurationChange();
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 1a944ce71796..37a4948ae8b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -29,6 +29,7 @@ import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.ITaskStackListener;
+import android.app.UiModeManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -38,6 +39,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -83,6 +85,7 @@ import com.android.systemui.recents.model.ThumbnailData;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
@@ -234,6 +237,13 @@ public class SystemServicesProxy {
mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
mDummyIcon.eraseColor(0xFF999999);
}
+
+ UiModeManager uiModeManager = (UiModeManager) context.
+ getSystemService(Context.UI_MODE_SERVICE);
+ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
+ Collections.addAll(sRecentsBlacklist,
+ res.getStringArray(R.array.recents_tv_blacklist_array));
+ }
}
/**
@@ -304,8 +314,12 @@ public class SystemServicesProxy {
if (includeFrontMostExcludedTask) {
flags |= ActivityManager.RECENT_WITH_EXCLUDED;
}
- List<ActivityManager.RecentTaskInfo> tasks = mAm.getRecentTasksForUser(numTasksToQuery,
- flags, userId);
+ List<ActivityManager.RecentTaskInfo> tasks = null;
+ try {
+ tasks = mAm.getRecentTasksForUser(numTasksToQuery, flags, userId);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to get recent tasks", e);
+ }
// Break early if we can't get a valid set of tasks
if (tasks == null) {
@@ -320,8 +334,9 @@ public class SystemServicesProxy {
// NOTE: The order of these checks happens in the expected order of the traversal of the
// tasks
- // Remove the task if it is blacklisted
- if (sRecentsBlacklist.contains(t.realActivity.getClassName())) {
+ // Remove the task if it or it's package are blacklsited
+ if (sRecentsBlacklist.contains(t.realActivity.getClassName()) ||
+ sRecentsBlacklist.contains(t.realActivity.getPackageName())) {
iter.remove();
continue;
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index e6cbbea4a1c5..d7894772454d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -60,6 +60,7 @@ import android.view.animation.Interpolator;
import android.widget.ImageView;
import com.android.systemui.R;
+import com.android.systemui.SystemUI;
import java.io.File;
import java.io.FileOutputStream;
@@ -165,11 +166,6 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
c.drawColor(overlayColor);
c.setBitmap(null);
- // swap "System UI" out for "Android System"
- final Bundle extras = new Bundle();
- extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- context.getString(com.android.internal.R.string.android_system_label));
-
// Show the intermediate notification
mTickerAddSpace = !mTickerAddSpace;
mNotificationManager = nManager;
@@ -187,9 +183,9 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
.setCategory(Notification.CATEGORY_PROGRESS)
.setWhen(now)
.setShowWhen(true)
- .addExtras(extras)
.setColor(r.getColor(
com.android.internal.R.color.system_notification_accent_color));
+ SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder);
mNotificationBuilder = new Notification.Builder(context)
.setTicker(r.getString(R.string.screenshot_saving_ticker)
@@ -199,11 +195,11 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
.setSmallIcon(R.drawable.stat_notify_image)
.setWhen(now)
.setShowWhen(true)
- .addExtras(extras)
.setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color))
.setStyle(mNotificationStyle)
.setPublicVersion(mPublicNotificationBuilder.build());
mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
+ SystemUI.overrideNotificationAppName(context, mNotificationBuilder);
mNotificationManager.notify(R.id.notification_screenshot, mNotificationBuilder.build());
@@ -864,6 +860,7 @@ class GlobalScreenshot {
.setAutoCancel(true)
.setColor(context.getColor(
com.android.internal.R.color.system_notification_accent_color));
+ SystemUI.overrideNotificationAppName(context, b);
Notification n = new Notification.BigTextStyle(b)
.bigText(errorMsg)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 542b25859036..8ee34a4cbd45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -844,7 +844,6 @@ public abstract class BaseStatusBar extends SystemUI implements
new Intent(BANNER_ACTION_SETUP).setPackage(packageName),
PendingIntent.FLAG_CANCEL_CURRENT);
- final Resources res = mContext.getResources();
final int colorRes = com.android.internal.R.color.system_notification_accent_color;
Notification.Builder note = new Notification.Builder(mContext)
.setSmallIcon(R.drawable.ic_android)
@@ -860,6 +859,7 @@ public abstract class BaseStatusBar extends SystemUI implements
.addAction(R.drawable.ic_settings,
mContext.getString(R.string.hidden_notifications_setup),
setupIntent);
+ overrideNotificationAppName(mContext, note);
NotificationManager noMan =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
@@ -1083,10 +1083,10 @@ public abstract class BaseStatusBar extends SystemUI implements
pkgicon = pmUser.getDefaultActivityIcon();
}
- ((ImageView) row.findViewById(R.id.app_icon)).setImageDrawable(pkgicon);
- ((TextView) row.findViewById(R.id.pkgname)).setText(appname);
+ ((ImageView) guts.findViewById(R.id.app_icon)).setImageDrawable(pkgicon);
+ ((TextView) guts.findViewById(R.id.pkgname)).setText(appname);
- final View settingsButton = guts.findViewById(R.id.more_settings);
+ final TextView settingsButton = (TextView) guts.findViewById(R.id.more_settings);
if (appUid >= 0) {
final int appUidF = appUid;
settingsButton.setOnClickListener(new View.OnClickListener() {
@@ -1096,11 +1096,16 @@ public abstract class BaseStatusBar extends SystemUI implements
startAppNotificationSettingsActivity(pkg, appUidF);
}
});
+ settingsButton.setText(R.string.notification_more_settings);
} else {
settingsButton.setVisibility(View.GONE);
}
- row.findViewById(R.id.done).setOnClickListener(new View.OnClickListener() {
+ guts.bindImportance(pmUser, sbn, mNotificationData.getImportance(sbn.getKey()));
+
+ final TextView doneButton = (TextView) guts.findViewById(R.id.done);
+ doneButton.setText(R.string.notification_done);
+ doneButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// If the user has security enabled, show challenge if the setting is changed.
@@ -1120,7 +1125,6 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
});
- guts.bindImportance(pmUser, sbn, row, mNotificationData.getImportance(sbn.getKey()));
}
private void saveImportanceCloseControls(StatusBarNotification sbn,
@@ -2491,7 +2495,7 @@ public abstract class BaseStatusBar extends SystemUI implements
}
protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) {
- if (isDeviceInVrMode()) {
+ if (!mUseHeadsUp || isDeviceInVrMode()) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 7b23c809fd4e..419c91b11e37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -23,6 +23,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Pair;
+import android.view.KeyEvent;
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
@@ -75,6 +76,7 @@ public class CommandQueue extends IStatusBar.Stub {
private static final int MSG_TOGGLE_APP_SPLIT_SCREEN = 30 << MSG_SHIFT;
private static final int MSG_APP_TRANSITION_FINISHED = 31 << MSG_SHIFT;
private static final int MSG_DISMISS_KEYBOARD_SHORTCUTS = 32 << MSG_SHIFT;
+ private static final int MSG_HANDLE_SYSNAV_KEY = 33 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -129,6 +131,8 @@ public class CommandQueue extends IStatusBar.Stub {
void addQsTile(ComponentName tile);
void remQsTile(ComponentName tile);
void clickTile(ComponentName tile);
+
+ void handleSystemNavigationKey(int arg1);
}
public CommandQueue(Callbacks callbacks) {
@@ -388,6 +392,13 @@ public class CommandQueue extends IStatusBar.Stub {
}
}
+ @Override
+ public void handleSystemNavigationKey(int key) {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_HANDLE_SYSNAV_KEY, key, 0).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
@@ -503,6 +514,9 @@ public class CommandQueue extends IStatusBar.Stub {
case MSG_TOGGLE_APP_SPLIT_SCREEN:
mCallbacks.toggleSplitScreen();
break;
+ case MSG_HANDLE_SYSNAV_KEY:
+ mCallbacks.handleSystemNavigationKey(msg.arg1);
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index e1d4c8aea83c..f09eae84df9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -185,6 +185,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
}
};
private OnClickListener mOnClickListener;
+ private boolean mHeadsupDisappearRunning;
private View mChildAfterViewWhenDismissed;
private View mGroupParentWhenDismissed;
private boolean mRefocusOnDismiss;
@@ -759,15 +760,17 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
mRemoved = true;
mPrivateLayout.setRemoved();
- if (mChildrenContainer != null) {
- mChildrenContainer.setRemoved();
- }
}
public NotificationChildrenContainer getChildrenContainer() {
return mChildrenContainer;
}
+ public void setHeadsupDisappearRunning(boolean running) {
+ mHeadsupDisappearRunning = running;
+ mPrivateLayout.setHeadsupDisappearRunning(running);
+ }
+
public View getChildAfterViewWhenDismissed() {
return mChildAfterViewWhenDismissed;
}
@@ -1173,8 +1176,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
return getMinHeight();
} else if (mIsSummaryWithChildren && !mOnKeyguard) {
return mChildrenContainer.getIntrinsicHeight();
- } else if (mIsHeadsUp) {
- if (isPinned()) {
+ } else if (mIsHeadsUp || mHeadsupDisappearRunning) {
+ if (isPinned() || mHeadsupDisappearRunning) {
return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
} else if (isExpanded()) {
return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
@@ -1300,6 +1303,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
if (!animated) {
mPublicLayout.animate().cancel();
mPrivateLayout.animate().cancel();
+ if (mChildrenContainer != null) {
+ mChildrenContainer.animate().cancel();
+ mChildrenContainer.setAlpha(1f);
+ }
mPublicLayout.setAlpha(1f);
mPrivateLayout.setAlpha(1f);
mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 92115620a81b..016e1f2f5a98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AlertDialog;
import android.app.AppGlobals;
import android.app.Dialog;
@@ -45,15 +47,18 @@ import android.view.KeyboardShortcutGroup;
import android.view.KeyboardShortcutInfo;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.AccessibilityDelegate;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager.KeyboardShortcutsReceiver;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.internal.app.AssistUtils;
+import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
@@ -63,6 +68,7 @@ import java.util.Comparator;
import java.util.List;
import static android.content.Context.LAYOUT_INFLATER_SERVICE;
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
/**
@@ -112,7 +118,7 @@ public final class KeyboardShortcuts {
private KeyCharacterMap mKeyCharacterMap;
private KeyboardShortcuts(Context context) {
- this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
+ this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault_Light);
this.mPackageManager = AppGlobals.getPackageManager();
loadResources(context);
}
@@ -582,7 +588,7 @@ public final class KeyboardShortcuts {
R.layout.keyboard_shortcuts_category_title, keyboardShortcutsLayout, false);
categoryTitle.setText(group.getLabel());
categoryTitle.setTextColor(group.isSystemGroup()
- ? mContext.getColor(R.color.ksh_system_group_color)
+ ? Utils.getColorAccent(mContext)
: mContext.getColor(R.color.ksh_application_group_color));
keyboardShortcutsLayout.addView(categoryTitle);
@@ -591,7 +597,7 @@ public final class KeyboardShortcuts {
final int itemsSize = group.getItems().size();
for (int j = 0; j < itemsSize; j++) {
KeyboardShortcutInfo info = group.getItems().get(j);
- List<StringOrDrawable> shortcutKeys = getHumanReadableShortcutKeys(info);
+ List<StringDrawableContainer> shortcutKeys = getHumanReadableShortcutKeys(info);
if (shortcutKeys == null) {
// Ignore shortcuts we can't display keys for.
Log.w(TAG, "Keyboard Shortcut contains unsupported keys, skipping.");
@@ -621,25 +627,33 @@ public final class KeyboardShortcuts {
.findViewById(R.id.keyboard_shortcuts_item_container);
final int shortcutKeysSize = shortcutKeys.size();
for (int k = 0; k < shortcutKeysSize; k++) {
- StringOrDrawable shortcutRepresentation = shortcutKeys.get(k);
- if (shortcutRepresentation.drawable != null) {
+ StringDrawableContainer shortcutRepresentation = shortcutKeys.get(k);
+ if (shortcutRepresentation.mDrawable != null) {
ImageView shortcutKeyIconView = (ImageView) inflater.inflate(
R.layout.keyboard_shortcuts_key_icon_view, shortcutItemsContainer,
false);
Bitmap bitmap = Bitmap.createBitmap(shortcutKeyIconItemHeightWidth,
shortcutKeyIconItemHeightWidth, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
- shortcutRepresentation.drawable.setBounds(0, 0, canvas.getWidth(),
+ shortcutRepresentation.mDrawable.setBounds(0, 0, canvas.getWidth(),
canvas.getHeight());
- shortcutRepresentation.drawable.draw(canvas);
+ shortcutRepresentation.mDrawable.draw(canvas);
shortcutKeyIconView.setImageBitmap(bitmap);
+ shortcutKeyIconView.setImportantForAccessibility(
+ IMPORTANT_FOR_ACCESSIBILITY_YES);
+ shortcutKeyIconView.setAccessibilityDelegate(
+ new ShortcutKeyAccessibilityDelegate(
+ shortcutRepresentation.mString));
shortcutItemsContainer.addView(shortcutKeyIconView);
- } else if (shortcutRepresentation.string != null) {
+ } else if (shortcutRepresentation.mString != null) {
TextView shortcutKeyTextView = (TextView) inflater.inflate(
R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer,
false);
shortcutKeyTextView.setMinimumWidth(shortcutKeyTextItemMinWidth);
- shortcutKeyTextView.setText(shortcutRepresentation.string);
+ shortcutKeyTextView.setText(shortcutRepresentation.mString);
+ shortcutKeyTextView.setAccessibilityDelegate(
+ new ShortcutKeyAccessibilityDelegate(
+ shortcutRepresentation.mString));
shortcutItemsContainer.addView(shortcutKeyTextView);
}
}
@@ -655,19 +669,20 @@ public final class KeyboardShortcuts {
}
}
- private List<StringOrDrawable> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
- List<StringOrDrawable> shortcutKeys = getHumanReadableModifiers(info);
+ private List<StringDrawableContainer> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
+ List<StringDrawableContainer> shortcutKeys = getHumanReadableModifiers(info);
if (shortcutKeys == null) {
return null;
}
- String displayLabelString = null;
- Drawable displayLabelDrawable = null;
+ String shortcutKeyString = null;
+ Drawable shortcutKeyDrawable = null;
if (info.getBaseCharacter() > Character.MIN_VALUE) {
- displayLabelString = String.valueOf(info.getBaseCharacter());
+ shortcutKeyString = String.valueOf(info.getBaseCharacter());
} else if (mSpecialCharacterDrawables.get(info.getKeycode()) != null) {
- displayLabelDrawable = mSpecialCharacterDrawables.get(info.getKeycode());
+ shortcutKeyDrawable = mSpecialCharacterDrawables.get(info.getKeycode());
+ shortcutKeyString = mSpecialCharacterNames.get(info.getKeycode());
} else if (mSpecialCharacterNames.get(info.getKeycode()) != null) {
- displayLabelString = mSpecialCharacterNames.get(info.getKeycode());
+ shortcutKeyString = mSpecialCharacterNames.get(info.getKeycode());
} else {
// Special case for shortcuts with no base key or keycode.
if (info.getKeycode() == KeyEvent.KEYCODE_UNKNOWN) {
@@ -675,22 +690,23 @@ public final class KeyboardShortcuts {
}
char displayLabel = mKeyCharacterMap.getDisplayLabel(info.getKeycode());
if (displayLabel != 0) {
- displayLabelString = String.valueOf(displayLabel);
+ shortcutKeyString = String.valueOf(displayLabel);
} else {
return null;
}
}
- if (displayLabelDrawable != null) {
- shortcutKeys.add(new StringOrDrawable(displayLabelDrawable));
- } else if (displayLabelString != null) {
- shortcutKeys.add(new StringOrDrawable(displayLabelString.toUpperCase()));
+ if (shortcutKeyString != null) {
+ shortcutKeys.add(new StringDrawableContainer(shortcutKeyString, shortcutKeyDrawable));
+ } else {
+ Log.w(TAG, "Keyboard Shortcut does not have a text representation, skipping.");
}
+
return shortcutKeys;
}
- private List<StringOrDrawable> getHumanReadableModifiers(KeyboardShortcutInfo info) {
- final List<StringOrDrawable> shortcutKeys = new ArrayList<>();
+ private List<StringDrawableContainer> getHumanReadableModifiers(KeyboardShortcutInfo info) {
+ final List<StringDrawableContainer> shortcutKeys = new ArrayList<>();
int modifiers = info.getModifiers();
if (modifiers == 0) {
return shortcutKeys;
@@ -698,13 +714,9 @@ public final class KeyboardShortcuts {
for(int i = 0; i < mModifierNames.size(); ++i) {
final int supportedModifier = mModifierNames.keyAt(i);
if ((modifiers & supportedModifier) != 0) {
- if (mModifierDrawables.get(supportedModifier) != null) {
- shortcutKeys.add(new StringOrDrawable(
- mModifierDrawables.get(supportedModifier)));
- } else {
- shortcutKeys.add(new StringOrDrawable(
- mModifierNames.get(supportedModifier).toUpperCase()));
- }
+ shortcutKeys.add(new StringDrawableContainer(
+ mModifierNames.get(supportedModifier),
+ mModifierDrawables.get(supportedModifier)));
modifiers &= ~supportedModifier;
}
}
@@ -715,16 +727,31 @@ public final class KeyboardShortcuts {
return shortcutKeys;
}
- private static final class StringOrDrawable {
- public String string;
- public Drawable drawable;
+ private final class ShortcutKeyAccessibilityDelegate extends AccessibilityDelegate {
+ private String mContentDescription;
+
+ ShortcutKeyAccessibilityDelegate(String contentDescription) {
+ mContentDescription = contentDescription;
+ }
- public StringOrDrawable(String string) {
- this.string = string;
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ if (mContentDescription != null) {
+ info.setContentDescription(mContentDescription.toLowerCase());
+ }
}
+ }
+
+ private static final class StringDrawableContainer {
+ @NonNull
+ public String mString;
+ @Nullable
+ public Drawable mDrawable;
- public StringOrDrawable(Drawable drawable) {
- this.drawable = drawable;
+ StringDrawableContainer(String string, Drawable drawable) {
+ mString = string;
+ mDrawable = drawable;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 30ac9cad346f..9fd09d92162c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -119,6 +119,7 @@ public class NotificationContentView extends FrameLayout {
private int mContentHeightAtAnimationStart = UNDEFINED;
private boolean mFocusOnVisibilityChange;
+ private boolean mHeadsupDisappearRunning;
public NotificationContentView(Context context, AttributeSet attrs) {
@@ -446,7 +447,8 @@ public class NotificationContentView extends FrameLayout {
boolean transitioningBetweenHunAndExpanded =
isTransitioningFromTo(VISIBLE_TYPE_HEADSUP, VISIBLE_TYPE_EXPANDED) ||
isTransitioningFromTo(VISIBLE_TYPE_EXPANDED, VISIBLE_TYPE_HEADSUP);
- boolean pinned = !isVisibleOrTransitioning(VISIBLE_TYPE_CONTRACTED) && mIsHeadsUp;
+ boolean pinned = !isVisibleOrTransitioning(VISIBLE_TYPE_CONTRACTED)
+ && (mIsHeadsUp || mHeadsupDisappearRunning);
if (transitioningBetweenHunAndExpanded || pinned) {
return Math.min(mHeadsUpChild.getHeight(), mExpandedChild.getHeight());
}
@@ -830,7 +832,7 @@ public class NotificationContentView extends FrameLayout {
return VISIBLE_TYPE_SINGLELINE;
}
- if (mIsHeadsUp && mHeadsUpChild != null) {
+ if ((mIsHeadsUp || mHeadsupDisappearRunning) && mHeadsUpChild != null) {
if (viewHeight <= mHeadsUpChild.getHeight() || noExpandedChild) {
return VISIBLE_TYPE_HEADSUP;
} else {
@@ -1153,6 +1155,11 @@ public class NotificationContentView extends FrameLayout {
}
}
+ public void setHeadsupDisappearRunning(boolean headsupDisappearRunning) {
+ mHeadsupDisappearRunning = headsupDisappearRunning;
+ selectLayout(false /* animate */, true /* force */);
+ }
+
public void setFocusOnVisibilityChange() {
mFocusOnVisibilityChange = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 5bbca1552a14..b66a4fbba949 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -173,7 +173,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
}
void bindImportance(final PackageManager pm, final StatusBarNotification sbn,
- final ExpandableNotificationRow row, final int importance) {
+ final int importance) {
mINotificationManager = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
mStartingUserImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
@@ -191,8 +191,8 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
// unlikely.
}
- final View importanceSlider = row.findViewById(R.id.importance_slider);
- final View importanceButtons = row.findViewById(R.id.importance_buttons);
+ final View importanceSlider = findViewById(R.id.importance_slider);
+ final View importanceButtons = findViewById(R.id.importance_buttons);
if (mShowSlider) {
bindSlider(importanceSlider, systemApp);
importanceSlider.setVisibility(View.VISIBLE);
@@ -256,6 +256,8 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
} else {
mReset.setText(mContext.getString(R.string.do_not_silence_block));
}
+ mBlock.setText(mContext.getString(R.string.block));
+ mSilent.setText(mContext.getString(R.string.show_silently));
if (importance == NotificationListenerService.Ranking.IMPORTANCE_LOW) {
mSilent.setChecked(true);
} else {
@@ -264,7 +266,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
}
private void bindSlider(final View importanceSlider, final boolean systemApp) {
- mActiveSliderTint = loadColorStateList(R.color.notification_guts_slider_color);
+ mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
mInactiveSliderTint = loadColorStateList(R.color.notification_guts_disabled_slider_color);
mImportanceSummary = ((TextView) importanceSlider.findViewById(R.id.summary));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index 5fea674f47b1..6cbaceaa00ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -130,6 +130,28 @@ public class RemoteInputController {
}
}
+ public void closeRemoteInputs() {
+ if (mOpen.size() == 0) {
+ return;
+ }
+
+ // Make a copy because closing the remote inputs will modify mOpen.
+ ArrayList<NotificationData.Entry> list = new ArrayList<>(mOpen.size());
+ for (int i = mOpen.size() - 1; i >= 0; i--) {
+ NotificationData.Entry item = mOpen.get(i).get();
+ if (item != null && item.row != null) {
+ list.add(item);
+ }
+ }
+
+ for (int i = list.size() - 1; i >= 0; i--) {
+ NotificationData.Entry item = list.get(i);
+ if (item.row != null) {
+ item.row.closeRemoteInput();
+ }
+ }
+ }
+
public interface Callback {
default void onRemoteInputActive(boolean active) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index a2ad46a0c0e1..74caa5326f83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -237,6 +237,14 @@ public class SignalClusterView
super.onDetachedFromWindow();
}
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+
+ // Re-run all checks against the tint area for all icons
+ applyIconTint();
+ }
+
// From SecurityController.
@Override
public void onStateChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
index f75f357421f8..1ff2b1328464 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
@@ -20,6 +20,7 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.view.View;
import android.view.ViewGroup;
@@ -194,7 +195,7 @@ public class ViewTransformationHelper implements TransformableView {
for (Integer viewType : mTransformedViews.keySet()) {
TransformState ownState = getCurrentState(viewType);
if (ownState != null) {
- ownState.setVisible(visible);
+ ownState.setVisible(visible, false /* force */);
ownState.recycle();
}
}
@@ -252,6 +253,19 @@ public class ViewTransformationHelper implements TransformableView {
}
}
+ public void resetTransformedView(View view) {
+ TransformState state = TransformState.createFrom(view);
+ state.setVisible(true /* visible */, true /* force */);
+ state.recycle();
+ }
+
+ /**
+ * @return a set of all views are being transformed.
+ */
+ public ArraySet<View> getAllTransformingViews() {
+ return new ArraySet<>(mTransformedViews.values());
+ }
+
public static abstract class CustomTransformation {
/**
* Transform a state to the given view
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
index 8463e069abc1..9501f907e575 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HeaderTransformState.java
@@ -123,8 +123,9 @@ public class HeaderTransformState extends TransformState {
}
}
- public void setVisible(boolean visible) {
- super.setVisible(visible);
+ @Override
+ public void setVisible(boolean visible, boolean force) {
+ super.setVisible(visible, force);
if (!(mTransformedView instanceof NotificationHeaderView)) {
return;
}
@@ -132,11 +133,13 @@ public class HeaderTransformState extends TransformState {
int childCount = header.getChildCount();
for (int i = 0; i < childCount; i++) {
View headerChild = header.getChildAt(i);
- if (headerChild.getVisibility() == View.GONE) {
+ if (!force && headerChild.getVisibility() == View.GONE) {
continue;
}
headerChild.animate().cancel();
- headerChild.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ if (headerChild.getVisibility() != View.GONE) {
+ headerChild.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ }
if (headerChild == mExpandButton) {
headerChild.setAlpha(visible ? 1.0f : 0.0f);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index 1bfbaa228532..7794d5ba9a0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -22,18 +22,17 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.ColorFilter;
-import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
-import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -92,12 +91,25 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
@Override
public void notifyContentUpdated(StatusBarNotification notification) {
super.notifyContentUpdated(notification);
+
+ ArraySet<View> previousViews = mTransformationHelper.getAllTransformingViews();
+
// Reinspect the notification.
resolveHeaderViews();
updateInvertHelper();
updateTransformedTypes();
addRemainingTransformTypes();
updateCropToPaddingForImageViews();
+
+ // We need to reset all views that are no longer transforming in case a view was previously
+ // transformed, but now we decided to transform its container instead.
+ ArraySet<View> currentViews = mTransformationHelper.getAllTransformingViews();
+ for (int i = 0; i < previousViews.size(); i++) {
+ View view = previousViews.valueAt(i);
+ if (!currentViews.contains(view)) {
+ mTransformationHelper.resetTransformedView(view);
+ }
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 7d3da1b67422..f0f5c8db1821 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -301,6 +301,9 @@ public class TransformState {
}
public static void setClippingDeactivated(final View transformedView, boolean deactivated) {
+ if (!(transformedView.getParent() instanceof ViewGroup)) {
+ return;
+ }
ViewGroup view = (ViewGroup) transformedView.getParent();
while (true) {
ArraySet<View> clipSet = (ArraySet<View>) view.getTag(CLIP_CLIPPING_SET);
@@ -456,12 +459,14 @@ public class TransformState {
mTransformationEndY = UNDEFINED;
}
- public void setVisible(boolean visible) {
- if (mTransformedView.getVisibility() == View.GONE) {
+ public void setVisible(boolean visible, boolean force) {
+ if (!force && mTransformedView.getVisibility() == View.GONE) {
return;
}
+ if (mTransformedView.getVisibility() != View.GONE) {
+ mTransformedView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ }
mTransformedView.animate().cancel();
- mTransformedView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
mTransformedView.setAlpha(visible ? 1.0f : 0.0f);
resetTransformedView();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 7db2870620a0..42f398d8d83f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -56,6 +56,7 @@ public class KeyguardStatusBarView extends RelativeLayout
private BatteryController mBatteryController;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
+ private UserSwitcherController mUserSwitcherController;
private int mSystemIconsSwitcherHiddenExpandedMargin;
private View mSystemIconsContainer;
@@ -149,6 +150,16 @@ public class KeyguardStatusBarView extends RelativeLayout
} else if (mMultiUserSwitch.getParent() == this && mKeyguardUserSwitcherShowing) {
removeView(mMultiUserSwitch);
}
+ if (mKeyguardUserSwitcher == null) {
+ // If we have no keyguard switcher, the screen width is under 600dp. In this case,
+ // we don't show the multi-user avatar unless there is more than 1 user on the device.
+ if (mUserSwitcherController != null
+ && mUserSwitcherController.getSwitchableUserCount() > 1) {
+ mMultiUserSwitch.setVisibility(View.VISIBLE);
+ } else {
+ mMultiUserSwitch.setVisibility(View.GONE);
+ }
+ }
mBatteryLevel.setVisibility(mBatteryCharging ? View.VISIBLE : View.GONE);
}
@@ -187,6 +198,7 @@ public class KeyguardStatusBarView extends RelativeLayout
}
public void setUserSwitcherController(UserSwitcherController controller) {
+ mUserSwitcherController = controller;
mMultiUserSwitch.setUserSwitcherController(controller);
}
@@ -287,6 +299,8 @@ public class KeyguardStatusBarView extends RelativeLayout
mSystemIconsSuperContainer.animate().cancel();
mMultiUserSwitch.animate().cancel();
mMultiUserSwitch.setAlpha(1f);
+ } else {
+ updateVisibilities();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 9ecff18d2d11..204ab7e3aa80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -213,18 +213,18 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
return isGroupSuppressed(getGroupKey(sbn)) && sbn.getNotification().isGroupSummary();
}
- public boolean isOnlyChildInSuppressedGroup(StatusBarNotification sbn) {
- return isGroupSuppressed(sbn.getGroupKey())
- && isOnlyChild(sbn);
- }
-
private boolean isOnlyChild(StatusBarNotification sbn) {
return !sbn.getNotification().isGroupSummary()
&& getTotalNumberOfChildren(sbn) == 1;
}
public boolean isOnlyChildInGroup(StatusBarNotification sbn) {
- return isOnlyChild(sbn) && getLogicalGroupSummary(sbn) != null;
+ if (!isOnlyChild(sbn)) {
+ return false;
+ }
+ ExpandableNotificationRow logicalGroupSummary = getLogicalGroupSummary(sbn);
+ return logicalGroupSummary != null
+ && !logicalGroupSummary.getStatusBarNotification().equals(sbn);
}
private int getTotalNumberOfChildren(StatusBarNotification sbn) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 5064d8eb1d4c..4b822793a34a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1296,7 +1296,7 @@ public class NotificationPanelView extends PanelView implements
}
}
- private void flingSettings(float vel, boolean expand) {
+ public void flingSettings(float vel, boolean expand) {
flingSettings(vel, expand, null, false /* isClick */);
}
@@ -1390,10 +1390,14 @@ public class NotificationPanelView extends PanelView implements
return maxHeight;
}
- private boolean isInSettings() {
+ public boolean isInSettings() {
return mQsExpanded;
}
+ public boolean isExpanding() {
+ return mIsExpanding;
+ }
+
@Override
protected void onHeightUpdated(float expandedHeight) {
if (!mQsExpanded || mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted) {
@@ -2108,6 +2112,7 @@ public class NotificationPanelView extends PanelView implements
onEmptySpaceClick(x);
}
+ @Override
protected boolean onMiddleClicked() {
switch (mStatusBar.getBarState()) {
case StatusBarState.KEYGUARD:
@@ -2257,6 +2262,7 @@ public class NotificationPanelView extends PanelView implements
mStatusBar.clearNotificationEffects();
}
+ @Override
protected boolean isPanelVisibleBecauseOfHeadsUp() {
return mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 376f724a97fc..4de769db61c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1235,6 +1235,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
+ @Override
public void onClick(View v) {
awakenDreams();
toggleRecentApps();
@@ -1299,6 +1300,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
};
private final View.OnTouchListener mHomeActionListener = new View.OnTouchListener() {
+ @Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
@@ -1409,7 +1411,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (shadeEntry == null) {
return;
}
- boolean isHeadsUped = mUseHeadsUp && shouldPeek(shadeEntry);
+ boolean isHeadsUped = shouldPeek(shadeEntry);
if (isHeadsUped) {
mHeadsUpManager.showNotification(shadeEntry);
// Mark as seen immediately
@@ -2232,6 +2234,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
/**
* State is one or more of the DISABLE constants from StatusBarManager.
*/
+ @Override
public void disable(int state1, int state2, boolean animate) {
animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN;
mDisabledUnmodified1 = state1;
@@ -2461,6 +2464,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
+ @Override
protected void updateHeadsUp(String key, Entry entry, boolean shouldPeek,
boolean alertAgain) {
final boolean wasHeadsUp = isHeadsUp(key);
@@ -2477,6 +2481,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
+ @Override
protected void setHeadsUpUser(int newUserId) {
if (mHeadsUpManager != null) {
mHeadsUpManager.setUser(newUserId);
@@ -2487,6 +2492,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return mHeadsUpManager.isHeadsUp(key);
}
+ @Override
protected boolean isSnoozedPackage(StatusBarNotification sbn) {
return mHeadsUpManager.isSnoozed(sbn.getPackageName());
}
@@ -2527,6 +2533,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
* All changes to the status bar and notifications funnel through here and are batched.
*/
private class H extends BaseStatusBar.H {
+ @Override
public void handleMessage(Message m) {
super.handleMessage(m);
switch (m.what) {
@@ -2568,6 +2575,32 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mHeadsUpManager.releaseAllImmediately();
}
+ /**
+ * Called for system navigation gestures. First action opens the panel, second opens
+ * settings. Down action closes the entire panel.
+ */
+ @Override
+ public void handleSystemNavigationKey(int key) {
+ if (SPEW) Log.d(TAG, "handleSystemNavigationKey: " + key);
+ if (!panelsEnabled()) {
+ return;
+ }
+
+ // Panels are not available in setup
+ if (!mUserSetup) return;
+
+ if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key) {
+ mNotificationPanel.collapse(false /* delayed */, 1.0f /* speedUpFactor */);
+ } else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key) {
+ if (mNotificationPanel.isFullyCollapsed()) {
+ mNotificationPanel.expand(true /* animate */);
+ } else if (!mNotificationPanel.isInSettings() && !mNotificationPanel.isExpanding()){
+ mNotificationPanel.flingSettings(0 /* velocity */, true /* expand */);
+ }
+ }
+
+ }
+
boolean panelsEnabled() {
return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0 && !ONLY_CORE_APPS;
}
@@ -2609,15 +2642,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mHandler.sendEmptyMessage(MSG_OPEN_SETTINGS_PANEL);
}
+ @Override
public void animateCollapsePanels(int flags) {
animateCollapsePanels(flags, false /* force */, false /* delayed */,
1.0f /* speedUpFactor */);
}
+ @Override
public void animateCollapsePanels(int flags, boolean force) {
animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */);
}
+ @Override
public void animateCollapsePanels(int flags, boolean force, boolean delayed) {
animateCollapsePanels(flags, force, delayed, 1.0f /* speedUpFactor */);
}
@@ -3054,6 +3090,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
+ @Override
public void topAppWindowChanged(boolean showMenu) {
if (SPEW) {
Log.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
@@ -3090,6 +3127,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
+ ") " + v.getWidth() + "x" + v.getHeight() + "]";
}
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mQueueLock) {
pw.println("Current Status Bar state:");
@@ -3167,6 +3205,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
pw.println("see the logcat for a dump of the views we have created.");
// must happen on ui thread
mHandler.post(new Runnable() {
+ @Override
public void run() {
mStatusBarView.getLocationOnScreen(mAbsPos);
Log.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
@@ -3277,6 +3316,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mContext, intent, mCurrentUserId);
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Runnable runnable = new Runnable() {
+ @Override
public void run() {
mAssistManager.hideAssist();
intent.setFlags(
@@ -3321,6 +3361,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public boolean onDismiss() {
AsyncTask.execute(new Runnable() {
+ @Override
public void run() {
try {
if (keyguardShowing && !afterKeyguardGone) {
@@ -3344,11 +3385,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.v(TAG, "onReceive: " + intent);
String action = intent.getAction();
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
KeyboardShortcuts.dismiss();
+ if (mRemoteInputController != null) {
+ mRemoteInputController.closeRemoteInputs();
+ }
if (isCurrentProfile(getSendingUserId())) {
int flags = CommandQueue.FLAG_EXCLUDE_NONE;
String reason = intent.getStringExtra("reason");
@@ -3371,6 +3416,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
};
private BroadcastReceiver mDemoReceiver = new BroadcastReceiver() {
+ @Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.v(TAG, "onReceive: " + intent);
String action = intent.getAction();
@@ -3630,6 +3676,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
Runnable mStartTracing = new Runnable() {
+ @Override
public void run() {
vibrate();
SystemClock.sleep(250);
@@ -3640,6 +3687,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
};
Runnable mStopTracing = new Runnable() {
+ @Override
public void run() {
android.os.Debug.stopMethodTracing();
Log.d(TAG, "stopTracing");
@@ -4592,7 +4640,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void vibrateForCameraGesture() {
// Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
- mVibrator.vibrate(new long[]{0, 750L}, -1 /* repeat */);
+ mVibrator.vibrate(new long[]{0, 400}, -1 /* repeat */);
}
public void onScreenTurnedOn() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 81c0d812997a..a13138d4e6f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -144,7 +144,7 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
// listen for user / profile change.
try {
- ActivityManagerNative.getDefault().registerUserSwitchObserver(mUserSwitchListener);
+ ActivityManagerNative.getDefault().registerUserSwitchObserver(mUserSwitchListener, TAG);
} catch (RemoteException e) {
// Ignore
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index ae1e5d04aec6..011ec22d2b3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -30,6 +30,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Secure;
+import android.service.quicksettings.Tile;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@@ -403,10 +404,11 @@ public class QSTileHost implements QSTile.Host, Tunable {
String tileSpec = previousTiles.get(i);
if (!tileSpec.startsWith(CustomTile.PREFIX)) continue;
if (!newTiles.contains(tileSpec)) {
- Intent intent = new Intent().setComponent(
- CustomTile.getComponentFromSpec(tileSpec));
+ ComponentName component = CustomTile.getComponentFromSpec(tileSpec);
+ Intent intent = new Intent().setComponent(component);
TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
- mContext, intent, new UserHandle(ActivityManager.getCurrentUser()));
+ mContext, mServices, new Tile(component), intent,
+ new UserHandle(ActivityManager.getCurrentUser()));
lifecycleManager.onStopListening();
lifecycleManager.onTileRemoved();
lifecycleManager.flushMessagesAndUnbind();
@@ -416,10 +418,11 @@ public class QSTileHost implements QSTile.Host, Tunable {
String tileSpec = newTiles.get(i);
if (!tileSpec.startsWith(CustomTile.PREFIX)) continue;
if (!previousTiles.contains(tileSpec)) {
- Intent intent = new Intent().setComponent(
- CustomTile.getComponentFromSpec(tileSpec));
+ ComponentName component = CustomTile.getComponentFromSpec(tileSpec);
+ Intent intent = new Intent().setComponent(component);
TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
- mContext, intent, new UserHandle(ActivityManager.getCurrentUser()));
+ mContext, mServices, new Tile(component), intent,
+ new UserHandle(ActivityManager.getCurrentUser()));
lifecycleManager.onTileAdded();
lifecycleManager.flushMessagesAndUnbind();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
deleted file mode 100644
index 72eafd84789c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ /dev/null
@@ -1,842 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Outline;
-import android.graphics.Rect;
-import android.graphics.drawable.Animatable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.RippleDrawable;
-import android.util.AttributeSet;
-import android.util.MathUtils;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewOutlineProvider;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-import android.widget.Switch;
-import android.widget.TextView;
-import android.widget.Toast;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.systemui.BatteryMeterView;
-import com.android.systemui.FontSizeUtils;
-import com.android.systemui.R;
-import com.android.systemui.qs.QSPanel;
-import com.android.systemui.qs.QSPanel.Callback;
-import com.android.systemui.qs.QSTile;
-import com.android.systemui.qs.QSTile.DetailAdapter;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.tuner.TunerService;
-
-import java.text.NumberFormat;
-
-/**
- * The view to manage the header area in the expanded status bar.
- */
-public class StatusBarHeaderView extends BaseStatusBarHeader implements View.OnClickListener,
- BatteryController.BatteryStateChangeCallback, NextAlarmController.NextAlarmChangeCallback,
- EmergencyListener {
-
- private boolean mExpanded;
- private boolean mListening;
-
- private ViewGroup mSystemIconsContainer;
- private View mSystemIconsSuperContainer;
- private View mDateGroup;
- private View mClock;
- private TextView mTime;
- private TextView mAmPm;
- private MultiUserSwitch mMultiUserSwitch;
- private ImageView mMultiUserAvatar;
- private TextView mDateCollapsed;
- private TextView mDateExpanded;
- private LinearLayout mSystemIcons;
- private View mSignalCluster;
- private SettingsButton mSettingsButton;
- private View mSettingsContainer;
- private View mQsDetailHeader;
- private TextView mQsDetailHeaderTitle;
- private Switch mQsDetailHeaderSwitch;
- private ImageView mQsDetailHeaderProgress;
- private TextView mEmergencyCallsOnly;
- private TextView mBatteryLevel;
- private TextView mAlarmStatus;
-
- private boolean mShowEmergencyCallsOnly;
- private boolean mAlarmShowing;
- private AlarmManager.AlarmClockInfo mNextAlarm;
-
- private int mCollapsedHeight;
- private int mExpandedHeight;
-
- private int mMultiUserExpandedMargin;
- private int mMultiUserCollapsedMargin;
-
- private int mClockMarginBottomExpanded;
- private int mClockMarginBottomCollapsed;
- private int mMultiUserSwitchWidthCollapsed;
- private int mMultiUserSwitchWidthExpanded;
-
- private int mClockCollapsedSize;
- private int mClockExpandedSize;
-
- /**
- * In collapsed QS, the clock and avatar are scaled down a bit post-layout to allow for a nice
- * transition. These values determine that factor.
- */
- private float mClockCollapsedScaleFactor;
- private float mAvatarCollapsedScaleFactor;
-
- private ActivityStarter mActivityStarter;
- private BatteryController mBatteryController;
- private NextAlarmController mNextAlarmController;
- private QSPanel mQSPanel;
-
- private final Rect mClipBounds = new Rect();
-
- private boolean mCaptureValues;
- private boolean mSignalClusterDetached;
- private final LayoutValues mCollapsedValues = new LayoutValues();
- private final LayoutValues mExpandedValues = new LayoutValues();
- private final LayoutValues mCurrentValues = new LayoutValues();
-
- private float mCurrentT;
- private boolean mShowingDetail;
- private boolean mDetailTransitioning;
-
- private boolean mAllowExpand = true;
-
- public StatusBarHeaderView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mSystemIconsSuperContainer = findViewById(R.id.system_icons_super_container);
- mSystemIconsContainer = (ViewGroup) findViewById(R.id.system_icons_container);
- mSystemIconsSuperContainer.setOnClickListener(this);
- mDateGroup = findViewById(R.id.date_group);
- mClock = findViewById(R.id.clock);
- mTime = (TextView) findViewById(R.id.time_view);
- mAmPm = (TextView) findViewById(R.id.am_pm_view);
- mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
- mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
- mDateCollapsed = (TextView) findViewById(R.id.date_collapsed);
- mDateExpanded = (TextView) findViewById(R.id.date_expanded);
- mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
- mSettingsContainer = findViewById(R.id.settings_button_container);
- mSettingsButton.setOnClickListener(this);
- mQsDetailHeader = findViewById(R.id.qs_detail_header);
- mQsDetailHeader.setAlpha(0);
- mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title);
- mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle);
- mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress);
- mEmergencyCallsOnly = (TextView) findViewById(R.id.header_emergency_calls_only);
- mBatteryLevel = (TextView) findViewById(R.id.battery_level);
- mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
- mAlarmStatus.setOnClickListener(this);
- mSignalCluster = findViewById(R.id.signal_cluster);
- mSystemIcons = (LinearLayout) findViewById(R.id.system_icons);
- loadDimens();
- updateVisibilities();
- updateClockScale();
- updateAvatarScale();
- addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right,
- int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
- if ((right - left) != (oldRight - oldLeft)) {
- // width changed, update clipping
- setClipping(getHeight());
- }
- boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
- mTime.setPivotX(rtl ? mTime.getWidth() : 0);
- mTime.setPivotY(mTime.getBaseline());
- updateAmPmTranslation();
- }
- });
- setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setRect(mClipBounds);
- }
- });
- requestCaptureValues();
-
- // RenderThread is doing more harm than good when touching the header (to expand quick
- // settings), so disable it for this view
- ((RippleDrawable) getBackground()).setForceSoftware(true);
- ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
- ((RippleDrawable) mSystemIconsSuperContainer.getBackground()).setForceSoftware(true);
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- if (mCaptureValues) {
- if (mExpanded) {
- captureLayoutValues(mExpandedValues);
- } else {
- captureLayoutValues(mCollapsedValues);
- }
- mCaptureValues = false;
- updateLayoutValues(mCurrentT);
- }
- mAlarmStatus.setX(mDateGroup.getLeft() + mDateCollapsed.getRight());
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- FontSizeUtils.updateFontSize(mBatteryLevel, R.dimen.battery_level_text_size);
- FontSizeUtils.updateFontSize(mEmergencyCallsOnly,
- R.dimen.qs_emergency_calls_only_text_size);
- FontSizeUtils.updateFontSize(mDateCollapsed, R.dimen.qs_date_collapsed_size);
- FontSizeUtils.updateFontSize(mDateExpanded, R.dimen.qs_date_collapsed_size);
- FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
- FontSizeUtils.updateFontSize(this, android.R.id.title, R.dimen.qs_detail_header_text_size);
- FontSizeUtils.updateFontSize(this, android.R.id.toggle, R.dimen.qs_detail_header_text_size);
- FontSizeUtils.updateFontSize(mAmPm, R.dimen.qs_time_collapsed_size);
- FontSizeUtils.updateFontSize(this, R.id.empty_time_view, R.dimen.qs_time_expanded_size);
-
- mEmergencyCallsOnly.setText(com.android.internal.R.string.emergency_calls_only);
-
- mClockCollapsedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_collapsed_size);
- mClockExpandedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size);
- mClockCollapsedScaleFactor = (float) mClockCollapsedSize / (float) mClockExpandedSize;
-
- updateClockScale();
- updateClockCollapsedMargin();
- }
-
- private void updateClockCollapsedMargin() {
- Resources res = getResources();
- int padding = res.getDimensionPixelSize(R.dimen.clock_collapsed_bottom_margin);
- int largePadding = res.getDimensionPixelSize(
- R.dimen.clock_collapsed_bottom_margin_large_text);
- float largeFactor = (MathUtils.constrain(getResources().getConfiguration().fontScale, 1.0f,
- FontSizeUtils.LARGE_TEXT_SCALE) - 1f) / (FontSizeUtils.LARGE_TEXT_SCALE - 1f);
- mClockMarginBottomCollapsed = Math.round((1 - largeFactor) * padding + largeFactor * largePadding);
- requestLayout();
- }
-
- private void requestCaptureValues() {
- mCaptureValues = true;
- requestLayout();
- }
-
- private void loadDimens() {
- mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_header_height);
- mExpandedHeight = getResources().getDimensionPixelSize(
- R.dimen.status_bar_header_height_expanded);
- mMultiUserExpandedMargin =
- getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin);
- mMultiUserCollapsedMargin =
- getResources().getDimensionPixelSize(R.dimen.multi_user_switch_collapsed_margin);
- mClockMarginBottomExpanded =
- getResources().getDimensionPixelSize(R.dimen.clock_expanded_bottom_margin);
- updateClockCollapsedMargin();
- mMultiUserSwitchWidthCollapsed =
- getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_collapsed);
- mMultiUserSwitchWidthExpanded =
- getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_expanded);
- mAvatarCollapsedScaleFactor =
- getResources().getDimensionPixelSize(R.dimen.multi_user_avatar_collapsed_size)
- / (float) mMultiUserAvatar.getLayoutParams().width;
- mClockCollapsedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_collapsed_size);
- mClockExpandedSize = getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size);
- mClockCollapsedScaleFactor = (float) mClockCollapsedSize / (float) mClockExpandedSize;
-
- }
-
- public void setActivityStarter(ActivityStarter activityStarter) {
- mActivityStarter = activityStarter;
- }
-
- public void setBatteryController(BatteryController batteryController) {
- mBatteryController = batteryController;
- ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController);
- }
-
- public void setNextAlarmController(NextAlarmController nextAlarmController) {
- mNextAlarmController = nextAlarmController;
- }
-
- public int getCollapsedHeight() {
- return mCollapsedHeight;
- }
-
- public int getExpandedHeight() {
- return mAllowExpand ? mExpandedHeight : mCollapsedHeight;
- }
-
- public void setListening(boolean listening) {
- if (listening == mListening) {
- return;
- }
- mListening = listening;
- updateListeners();
- }
-
- public void setExpanded(boolean expanded) {
- if (!mAllowExpand) {
- expanded = false;
- }
- boolean changed = expanded != mExpanded;
- mExpanded = expanded;
- if (changed) {
- updateEverything();
- }
- }
-
- public void updateEverything() {
- updateHeights();
- updateVisibilities();
- updateSystemIconsLayoutParams();
- updateClickTargets();
- updateMultiUserSwitch();
- updateClockScale();
- updateAvatarScale();
- updateClockLp();
- requestCaptureValues();
- }
-
- private void updateHeights() {
- int height = mExpanded ? mExpandedHeight : mCollapsedHeight;
- ViewGroup.LayoutParams lp = getLayoutParams();
- if (lp.height != height) {
- lp.height = height;
- setLayoutParams(lp);
- }
- }
-
- private void updateVisibilities() {
- mDateCollapsed.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
- mDateExpanded.setVisibility(mExpanded && mAlarmShowing ? View.INVISIBLE : View.VISIBLE);
- mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
- mSettingsContainer.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
- mQsDetailHeader.setVisibility(mExpanded && mShowingDetail? View.VISIBLE : View.INVISIBLE);
- if (mSignalCluster != null) {
- updateSignalClusterDetachment();
- }
- mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE);
- mBatteryLevel.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
- mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
- TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
- }
-
- private void updateSignalClusterDetachment() {
- boolean detached = mExpanded;
- if (detached != mSignalClusterDetached) {
- if (detached) {
- getOverlay().add(mSignalCluster);
- } else {
- reattachSignalCluster();
- }
- }
- mSignalClusterDetached = detached;
- }
-
- private void reattachSignalCluster() {
- getOverlay().remove(mSignalCluster);
- mSystemIcons.addView(mSignalCluster, 1);
- }
-
- private void updateSystemIconsLayoutParams() {
- RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsSuperContainer.getLayoutParams();
- int rule = mExpanded
- ? mSettingsContainer.getId()
- : mMultiUserSwitch.getId();
- if (rule != lp.getRules()[RelativeLayout.START_OF]) {
- lp.addRule(RelativeLayout.START_OF, rule);
- mSystemIconsSuperContainer.setLayoutParams(lp);
- }
- }
-
- private void updateListeners() {
- if (mListening) {
- mBatteryController.addStateChangedCallback(this);
- mNextAlarmController.addStateChangedCallback(this);
- } else {
- mBatteryController.removeStateChangedCallback(this);
- mNextAlarmController.removeStateChangedCallback(this);
- }
- }
-
- private void updateAvatarScale() {
- if (mExpanded) {
- mMultiUserAvatar.setScaleX(1f);
- mMultiUserAvatar.setScaleY(1f);
- } else {
- mMultiUserAvatar.setScaleX(mAvatarCollapsedScaleFactor);
- mMultiUserAvatar.setScaleY(mAvatarCollapsedScaleFactor);
- }
- }
-
- private void updateClockScale() {
- mTime.setTextSize(TypedValue.COMPLEX_UNIT_PX, mExpanded
- ? mClockExpandedSize
- : mClockCollapsedSize);
- mTime.setScaleX(1f);
- mTime.setScaleY(1f);
- updateAmPmTranslation();
- }
-
- private void updateAmPmTranslation() {
- boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
- mAmPm.setTranslationX((rtl ? 1 : -1) * mTime.getWidth() * (1 - mTime.getScaleX()));
- }
-
- @Override
- public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
- mBatteryLevel.setText(percentage);
- }
-
- @Override
- public void onPowerSaveChanged(boolean isPowerSave) {
- // could not care less
- }
-
- @Override
- public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
- mNextAlarm = nextAlarm;
- if (nextAlarm != null) {
- mAlarmStatus.setText(KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm));
- }
- mAlarmShowing = nextAlarm != null;
- updateEverything();
- requestCaptureValues();
- }
-
- private void updateClickTargets() {
- mMultiUserSwitch.setClickable(mExpanded);
- mMultiUserSwitch.setFocusable(mExpanded);
- mSystemIconsSuperContainer.setClickable(mExpanded);
- mSystemIconsSuperContainer.setFocusable(mExpanded);
- mAlarmStatus.setClickable(mNextAlarm != null && mNextAlarm.getShowIntent() != null);
- }
-
- private void updateClockLp() {
- int marginBottom = mExpanded
- ? mClockMarginBottomExpanded
- : mClockMarginBottomCollapsed;
- LayoutParams lp = (LayoutParams) mDateGroup.getLayoutParams();
- if (marginBottom != lp.bottomMargin) {
- lp.bottomMargin = marginBottom;
- mDateGroup.setLayoutParams(lp);
- }
- }
-
- private void updateMultiUserSwitch() {
- int marginEnd;
- int width;
- if (mExpanded) {
- marginEnd = mMultiUserExpandedMargin;
- width = mMultiUserSwitchWidthExpanded;
- } else {
- marginEnd = mMultiUserCollapsedMargin;
- width = mMultiUserSwitchWidthCollapsed;
- }
- MarginLayoutParams lp = (MarginLayoutParams) mMultiUserSwitch.getLayoutParams();
- if (marginEnd != lp.getMarginEnd() || lp.width != width) {
- lp.setMarginEnd(marginEnd);
- lp.width = width;
- mMultiUserSwitch.setLayoutParams(lp);
- }
- }
-
- public void setExpansion(float t) {
- if (!mExpanded) {
- t = 0f;
- }
- mCurrentT = t;
- float height = mCollapsedHeight + t * (mExpandedHeight - mCollapsedHeight);
- if (height < mCollapsedHeight) {
- height = mCollapsedHeight;
- }
- if (height > mExpandedHeight) {
- height = mExpandedHeight;
- }
- setClipping(height);
- updateLayoutValues(t);
- }
-
- private void updateLayoutValues(float t) {
- if (mCaptureValues) {
- return;
- }
- mCurrentValues.interpoloate(mCollapsedValues, mExpandedValues, t);
- applyLayoutValues(mCurrentValues);
- }
-
- private void setClipping(float height) {
- mClipBounds.set(getPaddingLeft(), 0, getWidth() - getPaddingRight(), (int) height);
- setClipBounds(mClipBounds);
- invalidateOutline();
- }
-
- public void setUserInfoController(UserInfoController userInfoController) {
- userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() {
- @Override
- public void onUserInfoChanged(String name, Drawable picture) {
- mMultiUserAvatar.setImageDrawable(picture);
- }
- });
- }
-
- @Override
- public void setCallback(Callback qsPanelCallback) {
- }
-
- @Override
- public void onClick(View v) {
- if (v == mSettingsButton) {
- if (mSettingsButton.isTunerClick()) {
- if (TunerService.isTunerEnabled(mContext)) {
- TunerService.showResetRequest(mContext, new Runnable() {
- @Override
- public void run() {
- // Relaunch settings so that the tuner disappears.
- startSettingsActivity();
- }
- });
- } else {
- Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show();
- TunerService.setTunerEnabled(mContext, true);
- }
- }
- startSettingsActivity();
- } else if (v == mSystemIconsSuperContainer) {
- startBatteryActivity();
- } else if (v == mAlarmStatus && mNextAlarm != null) {
- PendingIntent showIntent = mNextAlarm.getShowIntent();
- if (showIntent != null) {
- mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
- }
- }
- }
-
- private void startSettingsActivity() {
- mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
- true /* dismissShade */);
- }
-
- private void startBatteryActivity() {
- mActivityStarter.startActivity(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY),
- true /* dismissShade */);
- }
-
- public void setQSPanel(QSPanel qsp) {
- mQSPanel = qsp;
- if (mQSPanel != null) {
- mQSPanel.setCallback(mQsPanelCallback);
- }
- mMultiUserSwitch.setQsPanel(qsp);
- }
-
- @Override
- public boolean shouldDelayChildPressedState() {
- return true;
- }
-
- @Override
- public void setEmergencyCallsOnly(boolean show) {
- boolean changed = show != mShowEmergencyCallsOnly;
- if (changed) {
- mShowEmergencyCallsOnly = show;
- if (mExpanded) {
- updateEverything();
- requestCaptureValues();
- }
- }
- }
-
- @Override
- protected void dispatchSetPressed(boolean pressed) {
- // We don't want that everything lights up when we click on the header, so block the request
- // here.
- }
-
- private void captureLayoutValues(LayoutValues target) {
- target.timeScale = mExpanded ? 1f : mClockCollapsedScaleFactor;
- target.clockY = mClock.getBottom();
- target.dateY = mDateGroup.getTop();
- target.emergencyCallsOnlyAlpha = getAlphaForVisibility(mEmergencyCallsOnly);
- target.alarmStatusAlpha = getAlphaForVisibility(mAlarmStatus);
- target.dateCollapsedAlpha = getAlphaForVisibility(mDateCollapsed);
- target.dateExpandedAlpha = getAlphaForVisibility(mDateExpanded);
- target.avatarScale = mMultiUserAvatar.getScaleX();
- target.avatarX = mMultiUserSwitch.getLeft() + mMultiUserAvatar.getLeft();
- target.avatarY = mMultiUserSwitch.getTop() + mMultiUserAvatar.getTop();
- if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
- target.batteryX = mSystemIconsSuperContainer.getLeft()
- + mSystemIconsContainer.getRight();
- } else {
- target.batteryX = mSystemIconsSuperContainer.getLeft()
- + mSystemIconsContainer.getLeft();
- }
- target.batteryY = mSystemIconsSuperContainer.getTop() + mSystemIconsContainer.getTop();
- target.batteryLevelAlpha = getAlphaForVisibility(mBatteryLevel);
- target.settingsAlpha = getAlphaForVisibility(mSettingsContainer);
- target.settingsTranslation = mExpanded
- ? 0
- : mMultiUserSwitch.getLeft() - mSettingsContainer.getLeft();
- target.signalClusterAlpha = mSignalClusterDetached ? 0f : 1f;
- target.settingsRotation = !mExpanded ? 90f : 0f;
- }
-
- private float getAlphaForVisibility(View v) {
- return v == null || v.getVisibility() == View.VISIBLE ? 1f : 0f;
- }
-
- private void applyAlpha(View v, float alpha) {
- if (v == null || v.getVisibility() == View.GONE) {
- return;
- }
- if (alpha == 0f) {
- v.setVisibility(View.INVISIBLE);
- } else {
- v.setVisibility(View.VISIBLE);
- v.setAlpha(alpha);
- }
- }
-
- private void applyLayoutValues(LayoutValues values) {
- mTime.setScaleX(values.timeScale);
- mTime.setScaleY(values.timeScale);
- mClock.setY(values.clockY - mClock.getHeight());
- mDateGroup.setY(values.dateY);
- mAlarmStatus.setY(values.dateY - mAlarmStatus.getPaddingTop());
- mMultiUserAvatar.setScaleX(values.avatarScale);
- mMultiUserAvatar.setScaleY(values.avatarScale);
- mMultiUserAvatar.setX(values.avatarX - mMultiUserSwitch.getLeft());
- mMultiUserAvatar.setY(values.avatarY - mMultiUserSwitch.getTop());
- if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
- mSystemIconsSuperContainer.setX(values.batteryX - mSystemIconsContainer.getRight());
- } else {
- mSystemIconsSuperContainer.setX(values.batteryX - mSystemIconsContainer.getLeft());
- }
- mSystemIconsSuperContainer.setY(values.batteryY - mSystemIconsContainer.getTop());
- if (mSignalCluster != null && mExpanded) {
- if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
- mSignalCluster.setX(mSystemIconsSuperContainer.getX()
- - mSignalCluster.getWidth());
- } else {
- mSignalCluster.setX(mSystemIconsSuperContainer.getX()
- + mSystemIconsSuperContainer.getWidth());
- }
- mSignalCluster.setY(
- mSystemIconsSuperContainer.getY() + mSystemIconsSuperContainer.getHeight()/2
- - mSignalCluster.getHeight()/2);
- } else if (mSignalCluster != null) {
- mSignalCluster.setTranslationX(0f);
- mSignalCluster.setTranslationY(0f);
- }
- if (!mSettingsButton.isAnimating()) {
- mSettingsContainer.setTranslationY(mSystemIconsSuperContainer.getTranslationY());
- mSettingsContainer.setTranslationX(values.settingsTranslation);
- mSettingsButton.setRotation(values.settingsRotation);
- }
- applyAlpha(mEmergencyCallsOnly, values.emergencyCallsOnlyAlpha);
- if (!mShowingDetail && !mDetailTransitioning) {
- // Otherwise it needs to stay invisible
- applyAlpha(mAlarmStatus, values.alarmStatusAlpha);
- }
- applyAlpha(mDateCollapsed, values.dateCollapsedAlpha);
- applyAlpha(mDateExpanded, values.dateExpandedAlpha);
- applyAlpha(mBatteryLevel, values.batteryLevelAlpha);
- applyAlpha(mSettingsContainer, values.settingsAlpha);
- applyAlpha(mSignalCluster, values.signalClusterAlpha);
- if (!mExpanded) {
- mTime.setScaleX(1f);
- mTime.setScaleY(1f);
- }
- updateAmPmTranslation();
- }
-
- /**
- * Captures all layout values (position, visibility) for a certain state. This is used for
- * animations.
- */
- private static final class LayoutValues {
-
- float dateExpandedAlpha;
- float dateCollapsedAlpha;
- float emergencyCallsOnlyAlpha;
- float alarmStatusAlpha;
- float timeScale = 1f;
- float clockY;
- float dateY;
- float avatarScale;
- float avatarX;
- float avatarY;
- float batteryX;
- float batteryY;
- float batteryLevelAlpha;
- float settingsAlpha;
- float settingsTranslation;
- float signalClusterAlpha;
- float settingsRotation;
-
- public void interpoloate(LayoutValues v1, LayoutValues v2, float t) {
- timeScale = v1.timeScale * (1 - t) + v2.timeScale * t;
- clockY = v1.clockY * (1 - t) + v2.clockY * t;
- dateY = v1.dateY * (1 - t) + v2.dateY * t;
- avatarScale = v1.avatarScale * (1 - t) + v2.avatarScale * t;
- avatarX = v1.avatarX * (1 - t) + v2.avatarX * t;
- avatarY = v1.avatarY * (1 - t) + v2.avatarY * t;
- batteryX = v1.batteryX * (1 - t) + v2.batteryX * t;
- batteryY = v1.batteryY * (1 - t) + v2.batteryY * t;
- settingsTranslation = v1.settingsTranslation * (1 - t) + v2.settingsTranslation * t;
-
- float t1 = Math.max(0, t - 0.5f) * 2;
- settingsRotation = v1.settingsRotation * (1 - t1) + v2.settingsRotation * t1;
- emergencyCallsOnlyAlpha =
- v1.emergencyCallsOnlyAlpha * (1 - t1) + v2.emergencyCallsOnlyAlpha * t1;
-
- float t2 = Math.min(1, 2 * t);
- signalClusterAlpha = v1.signalClusterAlpha * (1 - t2) + v2.signalClusterAlpha * t2;
-
- float t3 = Math.max(0, t - 0.7f) / 0.3f;
- batteryLevelAlpha = v1.batteryLevelAlpha * (1 - t3) + v2.batteryLevelAlpha * t3;
- settingsAlpha = v1.settingsAlpha * (1 - t3) + v2.settingsAlpha * t3;
- dateExpandedAlpha = v1.dateExpandedAlpha * (1 - t3) + v2.dateExpandedAlpha * t3;
- dateCollapsedAlpha = v1.dateCollapsedAlpha * (1 - t3) + v2.dateCollapsedAlpha * t3;
- alarmStatusAlpha = v1.alarmStatusAlpha * (1 - t3) + v2.alarmStatusAlpha * t3;
- }
- }
-
- private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
- private boolean mScanState;
-
- @Override
- public void onToggleStateChanged(final boolean state) {
- post(new Runnable() {
- @Override
- public void run() {
- handleToggleStateChanged(state);
- }
- });
- }
-
- @Override
- public void onShowingDetail(final DetailAdapter detail, int x, int y) {
- mDetailTransitioning = true;
- post(new Runnable() {
- @Override
- public void run() {
- handleShowingDetail(detail);
- }
- });
- }
-
- @Override
- public void onScanStateChanged(final boolean state) {
- post(new Runnable() {
- @Override
- public void run() {
- handleScanStateChanged(state);
- }
- });
- }
-
- private void handleToggleStateChanged(boolean state) {
- mQsDetailHeaderSwitch.setChecked(state);
- }
-
- private void handleScanStateChanged(boolean state) {
- if (mScanState == state) return;
- mScanState = state;
- final Animatable anim = (Animatable) mQsDetailHeaderProgress.getDrawable();
- if (state) {
- mQsDetailHeaderProgress.animate().alpha(1f);
- anim.start();
- } else {
- mQsDetailHeaderProgress.animate().alpha(0f);
- anim.stop();
- }
- }
-
- private void handleShowingDetail(final QSTile.DetailAdapter detail) {
- final boolean showingDetail = detail != null;
- transition(mClock, !showingDetail);
- transition(mDateGroup, !showingDetail);
- if (mAlarmShowing) {
- transition(mAlarmStatus, !showingDetail);
- }
- transition(mQsDetailHeader, showingDetail);
- mShowingDetail = showingDetail;
- if (showingDetail) {
- mQsDetailHeaderTitle.setText(detail.getTitle());
- final Boolean toggleState = detail.getToggleState();
- if (toggleState == null) {
- mQsDetailHeaderSwitch.setVisibility(INVISIBLE);
- mQsDetailHeader.setClickable(false);
- } else {
- mQsDetailHeaderSwitch.setVisibility(VISIBLE);
- mQsDetailHeaderSwitch.setChecked(toggleState);
- mQsDetailHeader.setClickable(true);
- mQsDetailHeader.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- boolean checked = !mQsDetailHeaderSwitch.isChecked();
- mQsDetailHeaderSwitch.setChecked(checked);
- detail.setToggleState(checked);
- }
- });
- }
- } else {
- mQsDetailHeader.setClickable(false);
- }
- }
-
- private void transition(final View v, final boolean in) {
- if (in) {
- v.bringToFront();
- v.setVisibility(VISIBLE);
- }
- if (v.hasOverlappingRendering()) {
- v.animate().withLayer();
- }
- v.animate()
- .alpha(in ? 1 : 0)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- if (!in) {
- v.setVisibility(INVISIBLE);
- }
- mDetailTransitioning = false;
- }
- })
- .start();
- }
- };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 6439bea104e6..014cc4944a74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -40,7 +40,6 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
private static final String TAG = "BluetoothController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
private final LocalBluetoothManager mLocalBluetoothManager;
private final UserManager mUserManager;
private final int mCurrentUser;
@@ -78,7 +77,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
pw.print(" mEnabled="); pw.println(mEnabled);
pw.print(" mConnectionState="); pw.println(stateToString(mConnectionState));
pw.print(" mLastDevice="); pw.println(mLastDevice);
- pw.print(" mCallbacks.size="); pw.println(mCallbacks.size());
+ pw.print(" mCallbacks.size="); pw.println(mHandler.mCallbacks.size());
pw.println(" Bluetooth Devices:");
for (CachedBluetoothDevice device :
mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()) {
@@ -106,13 +105,13 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
@Override
public void addStateChangedCallback(Callback cb) {
- mCallbacks.add(cb);
+ mHandler.obtainMessage(H.MSG_ADD_CALLBACK, cb).sendToTarget();
mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
}
@Override
public void removeStateChangedCallback(Callback cb) {
- mCallbacks.remove(cb);
+ mHandler.obtainMessage(H.MSG_REMOVE_CALLBACK, cb).sendToTarget();
}
@Override
@@ -236,8 +235,12 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
}
private final class H extends Handler {
+ private final ArrayList<BluetoothController.Callback> mCallbacks = new ArrayList<>();
+
private static final int MSG_PAIRED_DEVICES_CHANGED = 1;
private static final int MSG_STATE_CHANGED = 2;
+ private static final int MSG_ADD_CALLBACK = 3;
+ private static final int MSG_REMOVE_CALLBACK = 4;
@Override
public void handleMessage(Message msg) {
@@ -248,6 +251,12 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
case MSG_STATE_CHANGED:
fireStateChange();
break;
+ case MSG_ADD_CALLBACK:
+ mCallbacks.add((BluetoothController.Callback) msg.obj);
+ break;
+ case MSG_REMOVE_CALLBACK:
+ mCallbacks.remove((BluetoothController.Callback) msg.obj);
+ break;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 904134141f94..4664851053d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -16,12 +16,14 @@
package com.android.systemui.statusbar.policy;
+import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
+import android.os.UserManager;
import android.util.Log;
import java.io.FileDescriptor;
@@ -49,7 +51,8 @@ public class HotspotControllerImpl implements HotspotController {
@Override
public boolean isHotspotSupported() {
return mConnectivityManager.isTetheringSupported()
- && mConnectivityManager.getTetherableWifiRegexs().length != 0;
+ && mConnectivityManager.getTetherableWifiRegexs().length != 0
+ && UserManager.get(mContext).isUserAdmin(ActivityManager.getCurrentUser());
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 83e25ebd7497..ac3246d5ff6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -197,8 +197,11 @@ public class MobileSignalController extends SignalController<
if (mConfig.show4gForLte) {
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA,
+ TelephonyIcons.FOUR_G_PLUS);
} else {
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, TelephonyIcons.LTE);
}
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index b27bfcb311cf..7a042af7f42e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -781,6 +781,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
datatype.equals("1x") ? TelephonyIcons.ONE_X :
datatype.equals("3g") ? TelephonyIcons.THREE_G :
datatype.equals("4g") ? TelephonyIcons.FOUR_G :
+ datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
datatype.equals("e") ? TelephonyIcons.E :
datatype.equals("g") ? TelephonyIcons.G :
datatype.equals("h") ? TelephonyIcons.H :
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 6ff8f77bff4e..d91b3329d1ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -182,6 +182,19 @@ class TelephonyIcons {
static final int QS_DATA_4G = R.drawable.ic_qs_signal_4g;
+ static final int[][] DATA_4G_PLUS = {
+ { R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus },
+ { R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus,
+ R.drawable.stat_sys_data_fully_connected_4g_plus }
+ };
+
+ static final int QS_DATA_4G_PLUS = R.drawable.ic_qs_signal_4g_plus;
+
// LTE branded "LTE"
static final int[][] DATA_LTE = {
{ R.drawable.stat_sys_data_fully_connected_lte,
@@ -204,6 +217,7 @@ class TelephonyIcons {
static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h;
static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g;
static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g;
+ static final int ICON_4G_PLUS = R.drawable.stat_sys_data_fully_connected_4g_plus;
static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
static final int ICON_CARRIER_NETWORK_CHANGE =
R.drawable.stat_sys_signal_carrier_network_change_animation;
@@ -213,6 +227,7 @@ class TelephonyIcons {
static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte;
static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g;
static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g;
+ static final int QS_ICON_4G_PLUS = R.drawable.ic_qs_signal_4g_plus;
static final int QS_ICON_1X = R.drawable.ic_qs_signal_1x;
static final int QS_ICON_CARRIER_NETWORK_CHANGE =
R.drawable.ic_qs_signal_carrier_network_change_animation;
@@ -348,6 +363,21 @@ class TelephonyIcons {
TelephonyIcons.QS_DATA_4G
);
+ static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
+ "4G+",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0,0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_4g_plus,
+ TelephonyIcons.ICON_4G_PLUS,
+ true,
+ TelephonyIcons.QS_DATA_4G_PLUS
+ );
+
static final MobileIconGroup LTE = new MobileIconGroup(
"LTE",
TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 415b7a18e553..379ad53c6dba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -51,6 +51,7 @@ import com.android.internal.util.UserIcons;
import com.android.settingslib.RestrictedLockUtils;
import com.android.systemui.GuestResumeSessionReceiver;
import com.android.systemui.R;
+import com.android.systemui.SystemUI;
import com.android.systemui.SystemUISecondaryUserService;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.tiles.UserDetailView;
@@ -380,6 +381,18 @@ public class UserSwitcherController {
Log.e(TAG, "Couldn't switch to user, id=" + userId);
}
+ public int getSwitchableUserCount() {
+ int count = 0;
+ final int N = mUsers.size();
+ for (int i = 0; i < N; ++i) {
+ UserRecord record = mUsers.get(i);
+ if (record.info != null && record.info.supportsSwitchTo()) {
+ count++;
+ }
+ }
+ return count;
+ }
+
private void switchToUserId(int id) {
try {
pauseRefreshUsers();
@@ -523,7 +536,7 @@ public class UserSwitcherController {
private void showLogoutNotification(int userId) {
PendingIntent logoutPI = PendingIntent.getBroadcastAsUser(mContext,
0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
- Notification notification = new Notification.Builder(mContext)
+ Notification.Builder builder = new Notification.Builder(mContext)
.setVisibility(Notification.VISIBILITY_SECRET)
.setPriority(Notification.PRIORITY_MIN)
.setSmallIcon(R.drawable.ic_person)
@@ -534,10 +547,10 @@ public class UserSwitcherController {
.setShowWhen(false)
.addAction(R.drawable.ic_delete,
mContext.getString(R.string.user_logout_notification_action),
- logoutPI)
- .build();
+ logoutPI);
+ SystemUI.overrideNotificationAppName(mContext, builder);
NotificationManager.from(mContext).notifyAsUser(TAG_LOGOUT_USER, ID_LOGOUT_USER,
- notification, new UserHandle(userId));
+ builder.build(), new UserHandle(userId));
}
};
@@ -547,7 +560,7 @@ public class UserSwitcherController {
PendingIntent removeGuestPI = canSwitchUsers ? PendingIntent.getBroadcastAsUser(mContext,
0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM) : null;
- Notification notification = new Notification.Builder(mContext)
+ Notification.Builder builder = new Notification.Builder(mContext)
.setVisibility(Notification.VISIBILITY_SECRET)
.setPriority(Notification.PRIORITY_MIN)
.setSmallIcon(R.drawable.ic_person)
@@ -557,10 +570,10 @@ public class UserSwitcherController {
.setShowWhen(false)
.addAction(R.drawable.ic_delete,
mContext.getString(R.string.guest_notification_remove_action),
- removeGuestPI)
- .build();
+ removeGuestPI);
+ SystemUI.overrideNotificationAppName(mContext, builder);
NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
- notification, new UserHandle(guestUserId));
+ builder.build(), new UserHandle(guestUserId));
}
private final Runnable mUnpauseRefreshUsers = new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index ba191cd1d31e..3c9373bd46a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -856,14 +856,6 @@ public class NotificationChildrenContainer extends ViewGroup {
mNotificationParent.getNotificationColor());
}
- public void setRemoved() {
- int childCount = mChildren.size();
- for (int i = 0; i < childCount; i++) {
- ExpandableNotificationRow child = mChildren.get(i);
- child.setRemoved();
- }
- }
-
public int getPositionInLinearLayout(View childInGroup) {
int position = mNotificationHeaderMargin + mNotificatonTopPadding;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 43f847c23f81..7de38797adcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1961,8 +1961,7 @@ public class NotificationStackScrollLayout extends ViewGroup
// we're ending up at the same location as we are now, lets just skip the animation
bottom = finalBottom;
} else {
- bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight()
- - lastView.getExtraBottomPadding());
+ bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight());
bottom = Math.min(bottom, getHeight());
}
} else {
@@ -3690,6 +3689,9 @@ public class NotificationStackScrollLayout extends ViewGroup
if (mAnimationsEnabled) {
mHeadsUpChangeAnimations.add(new Pair<>(row, isHeadsUp));
mNeedsAnimation = true;
+ if (!mIsExpanded && !isHeadsUp) {
+ row.setHeadsupDisappearRunning(true);
+ }
requestChildrenUpdate();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index c8c7d3d4c7cb..87e87c8e9bb3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -152,8 +152,10 @@ public class StackScrollAlgorithm {
float newYTranslation = state.yTranslation;
float newHeight = state.height;
float newNotificationEnd = newYTranslation + newHeight;
-
- if (newYTranslation < previousNotificationEnd) {
+ boolean isHeadsUp = (child instanceof ExpandableNotificationRow)
+ && ((ExpandableNotificationRow) child).isPinned();
+ if (newYTranslation < previousNotificationEnd
+ && (!isHeadsUp || ambientState.isShadeExpanded())) {
// The previous view is overlapping on top, clip!
float overlapAmount = previousNotificationEnd - newYTranslation;
state.clipTopAmount = (int) overlapAmount;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 7ac0d803e24e..659eaf7e209c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -225,16 +225,22 @@ public class StackStateAnimator {
// start height animation
if (heightChanging) {
startHeightAnimation(child, viewState, duration, delay);
+ } else {
+ abortAnimation(child, TAG_ANIMATOR_HEIGHT);
}
// start shadow alpha animation
if (shadowAlphaChanging) {
startShadowAlphaAnimation(child, viewState, duration, delay);
+ } else {
+ abortAnimation(child, TAG_ANIMATOR_SHADOW_ALPHA);
}
// start top inset animation
if (topInsetChanging) {
startInsetAnimation(child, viewState, duration, delay);
+ } else {
+ abortAnimation(child, TAG_ANIMATOR_TOP_INSET);
}
// start dimmed animation
@@ -286,16 +292,29 @@ public class StackStateAnimator {
// start translationY animation
if (yTranslationChanging) {
startYTranslationAnimation(child, viewState, duration, delay);
+ } else {
+ abortAnimation(child, TAG_ANIMATOR_TRANSLATION_Y);
}
// start translationZ animation
if (zTranslationChanging) {
startZTranslationAnimation(child, viewState, duration, delay);
+ } else {
+ abortAnimation(child, TAG_ANIMATOR_TRANSLATION_Z);
}
// start alpha animation
if (alphaChanging && child.getTranslationX() == 0) {
startAlphaAnimation(child, viewState, duration, delay);
+ } else {
+ abortAnimation(child, TAG_ANIMATOR_ALPHA);
+ }
+ }
+
+ private void abortAnimation(View child, int animatorTag) {
+ Animator previousAnimator = getChildTag(child, animatorTag);
+ if (previousAnimator != null) {
+ previousAnimator.cancel();
}
}
@@ -413,7 +432,8 @@ public class StackStateAnimator {
animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
long newDuration = cancelAnimatorAndGetNewDuration(duration, previousAnimator);
animator.setDuration(newDuration);
- if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) {
+ if (delay > 0 && (previousAnimator == null
+ || previousAnimator.getAnimatedFraction() == 0)) {
animator.setStartDelay(delay);
}
animator.addListener(getGlobalAnimationFinishedListener());
@@ -472,7 +492,8 @@ public class StackStateAnimator {
animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
long newDuration = cancelAnimatorAndGetNewDuration(duration, previousAnimator);
animator.setDuration(newDuration);
- if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) {
+ if (delay > 0 && (previousAnimator == null
+ || previousAnimator.getAnimatedFraction() == 0)) {
animator.setStartDelay(delay);
}
animator.addListener(getGlobalAnimationFinishedListener());
@@ -548,7 +569,8 @@ public class StackStateAnimator {
animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
long newDuration = cancelAnimatorAndGetNewDuration(duration, previousAnimator);
animator.setDuration(newDuration);
- if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) {
+ if (delay > 0 && (previousAnimator == null
+ || previousAnimator.getAnimatedFraction() == 0)) {
animator.setStartDelay(delay);
}
animator.addListener(getGlobalAnimationFinishedListener());
@@ -630,7 +652,8 @@ public class StackStateAnimator {
});
long newDuration = cancelAnimatorAndGetNewDuration(duration, previousAnimator);
animator.setDuration(newDuration);
- if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) {
+ if (delay > 0 && (previousAnimator == null
+ || previousAnimator.getAnimatedFraction() == 0)) {
animator.setStartDelay(delay);
}
animator.addListener(getGlobalAnimationFinishedListener());
@@ -674,7 +697,8 @@ public class StackStateAnimator {
animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
long newDuration = cancelAnimatorAndGetNewDuration(duration, previousAnimator);
animator.setDuration(newDuration);
- if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) {
+ if (delay > 0 && (previousAnimator == null
+ || previousAnimator.getAnimatedFraction() == 0)) {
animator.setStartDelay(delay);
}
animator.addListener(getGlobalAnimationFinishedListener());
@@ -729,10 +753,12 @@ public class StackStateAnimator {
animator.setInterpolator(interpolator);
long newDuration = cancelAnimatorAndGetNewDuration(duration, previousAnimator);
animator.setDuration(newDuration);
- if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) {
+ if (delay > 0 && (previousAnimator == null
+ || previousAnimator.getAnimatedFraction() == 0)) {
animator.setStartDelay(delay);
}
animator.addListener(getGlobalAnimationFinishedListener());
+ final boolean isHeadsUpDisappear = mHeadsUpDisappearChildren.contains(child);
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
@Override
@@ -741,6 +767,9 @@ public class StackStateAnimator {
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, null);
child.setTag(TAG_START_TRANSLATION_Y, null);
child.setTag(TAG_END_TRANSLATION_Y, null);
+ if (isHeadsUpDisappear) {
+ ((ExpandableNotificationRow) child).setHeadsupDisappearRunning(false);
+ }
}
});
startAnimator(animator);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 27726afdafa3..2d4900b36890 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -257,4 +257,9 @@ public class TvStatusBar extends BaseStatusBar {
} catch (RemoteException ex) {
}
}
+
+ @Override
+ public void handleSystemNavigationKey(int arg1) {
+ // Not implemented
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 36dd72793428..97d5e1078312 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -198,7 +198,7 @@ public class StorageNotification extends SystemUI {
rec.getNickname());
final CharSequence text = mContext.getString(R.string.ext_media_missing_message);
- final Notification notif = new Notification.Builder(mContext)
+ Notification.Builder builder = new Notification.Builder(mContext)
.setSmallIcon(R.drawable.ic_sd_card_48dp)
.setColor(mContext.getColor(R.color.system_notification_accent_color))
.setContentTitle(title)
@@ -208,10 +208,11 @@ public class StorageNotification extends SystemUI {
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setLocalOnly(true)
.setCategory(Notification.CATEGORY_SYSTEM)
- .setDeleteIntent(buildSnoozeIntent(fsUuid))
- .build();
+ .setDeleteIntent(buildSnoozeIntent(fsUuid));
+ SystemUI.overrideNotificationAppName(mContext, builder);
- mNotificationManager.notifyAsUser(fsUuid, PRIVATE_ID, notif, UserHandle.ALL);
+ mNotificationManager.notifyAsUser(fsUuid, PRIVATE_ID, builder
+ .build(), UserHandle.ALL);
}
}
}
@@ -224,7 +225,7 @@ public class StorageNotification extends SystemUI {
final CharSequence text = mContext.getString(
R.string.ext_media_unsupported_notification_message, disk.getDescription());
- final Notification notif = new Notification.Builder(mContext)
+ Notification.Builder builder = new Notification.Builder(mContext)
.setSmallIcon(getSmallIcon(disk, VolumeInfo.STATE_UNMOUNTABLE))
.setColor(mContext.getColor(R.color.system_notification_accent_color))
.setContentTitle(title)
@@ -233,10 +234,11 @@ public class StorageNotification extends SystemUI {
.setStyle(new Notification.BigTextStyle().bigText(text))
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setLocalOnly(true)
- .setCategory(Notification.CATEGORY_ERROR)
- .build();
+ .setCategory(Notification.CATEGORY_ERROR);
+ SystemUI.overrideNotificationAppName(mContext, builder);
- mNotificationManager.notifyAsUser(disk.getId(), DISK_ID, notif, UserHandle.ALL);
+ mNotificationManager.notifyAsUser(disk.getId(), DISK_ID, builder.build(),
+ UserHandle.ALL);
} else {
// Yay, we have volumes!
@@ -471,7 +473,7 @@ public class StorageNotification extends SystemUI {
intent = buildWizardMigratePendingIntent(move);
}
- final Notification notif = new Notification.Builder(mContext)
+ Notification.Builder builder = new Notification.Builder(mContext)
.setSmallIcon(R.drawable.ic_sd_card_48dp)
.setColor(mContext.getColor(R.color.system_notification_accent_color))
.setContentTitle(title)
@@ -483,10 +485,11 @@ public class StorageNotification extends SystemUI {
.setCategory(Notification.CATEGORY_PROGRESS)
.setPriority(Notification.PRIORITY_LOW)
.setProgress(100, status, false)
- .setOngoing(true)
- .build();
+ .setOngoing(true);
+ SystemUI.overrideNotificationAppName(mContext, builder);
- mNotificationManager.notifyAsUser(move.packageName, MOVE_ID, notif, UserHandle.ALL);
+ mNotificationManager.notifyAsUser(move.packageName, MOVE_ID,
+ builder.build(), UserHandle.ALL);
}
private void onMoveFinished(MoveInfo move, int status) {
@@ -520,7 +523,7 @@ public class StorageNotification extends SystemUI {
intent = null;
}
- final Notification notif = new Notification.Builder(mContext)
+ Notification.Builder builder = new Notification.Builder(mContext)
.setSmallIcon(R.drawable.ic_sd_card_48dp)
.setColor(mContext.getColor(R.color.system_notification_accent_color))
.setContentTitle(title)
@@ -531,10 +534,11 @@ public class StorageNotification extends SystemUI {
.setLocalOnly(true)
.setCategory(Notification.CATEGORY_SYSTEM)
.setPriority(Notification.PRIORITY_LOW)
- .setAutoCancel(true)
- .build();
+ .setAutoCancel(true);
+ SystemUI.overrideNotificationAppName(mContext, builder);
- mNotificationManager.notifyAsUser(move.packageName, MOVE_ID, notif, UserHandle.ALL);
+ mNotificationManager.notifyAsUser(move.packageName, MOVE_ID, builder.build(),
+ UserHandle.ALL);
}
private int getSmallIcon(DiskInfo disk, int state) {
@@ -555,7 +559,7 @@ public class StorageNotification extends SystemUI {
private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
CharSequence text) {
- return new Notification.Builder(mContext)
+ Notification.Builder builder = new Notification.Builder(mContext)
.setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
.setColor(mContext.getColor(R.color.system_notification_accent_color))
.setContentTitle(title)
@@ -563,6 +567,8 @@ public class StorageNotification extends SystemUI {
.setStyle(new Notification.BigTextStyle().bigText(text))
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setLocalOnly(true);
+ overrideNotificationAppName(mContext, builder);
+ return builder;
}
private PendingIntent buildInitPendingIntent(DiskInfo disk) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 1973e058e3e9..af6fec2f6274 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -68,6 +68,7 @@ import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
+import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
@@ -152,7 +153,7 @@ public class VolumeDialog implements TunerService.Tunable {
mKeyguard = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mAccessibilityMgr = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
- mActiveSliderTint = loadColorStateList(R.color.system_accent_color);
+ mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive);
initDialog();
@@ -562,6 +563,14 @@ public class VolumeDialog implements TunerService.Tunable {
if (!mExpanded && mExpandButtonAnimationRunning) {
prepareForCollapse();
}
+ final Resources res = mContext.getResources();
+ int paddingTop = mExpanded
+ ? res.getDimensionPixelSize(R.dimen.volume_dialog_expanded_padding_top)
+ : res.getDimensionPixelSize(R.dimen.volume_dialog_collapsed_padding_top);
+ mDialogContentView.setPaddingRelative(mDialogContentView.getPaddingStart(),
+ paddingTop,
+ mDialogContentView.getPaddingEnd(),
+ mDialogContentView.getPaddingBottom());
updateRowsH();
if (mExpandButtonAnimationRunning) {
final Drawable d = mExpandButton.getDrawable();
@@ -622,7 +631,6 @@ public class VolumeDialog implements TunerService.Tunable {
Util.setVisOrGone(row.view, visible);
Util.setVisOrGone(row.space, visible && mExpanded);
updateVolumeRowHeaderVisibleH(row);
- row.header.setAlpha(mExpanded && isActive ? 1 : 0.5f);
updateVolumeRowSliderTintH(row, isActive);
}
}
@@ -740,21 +748,7 @@ public class VolumeDialog implements TunerService.Tunable {
updateVolumeRowHeaderVisibleH(row);
// update header text
- String text = ss.name;
- if (mShowHeaders) {
- if (isRingZenNone) {
- text = mContext.getString(R.string.volume_stream_muted_dnd, ss.name);
- } else if (isRingVibrate && isRingLimited) {
- text = mContext.getString(R.string.volume_stream_vibrate_dnd, ss.name);
- } else if (isRingVibrate) {
- text = mContext.getString(R.string.volume_stream_vibrate, ss.name);
- } else if (ss.muted || mAutomute && ss.level == 0) {
- text = mContext.getString(R.string.volume_stream_muted, ss.name);
- } else if (isRingLimited) {
- text = mContext.getString(R.string.volume_stream_limited_dnd, ss.name);
- }
- }
- Util.setText(row.header, text);
+ Util.setText(row.header, ss.name);
// update icon
final boolean iconEnabled = (mAutomute || ss.muteSupported) && !zenMuted;
@@ -823,7 +817,7 @@ public class VolumeDialog implements TunerService.Tunable {
private void updateVolumeRowHeaderVisibleH(VolumeRow row) {
final boolean dynamic = row.ss != null && row.ss.dynamic;
- final boolean showHeaders = mShowHeaders || mExpanded && dynamic;
+ final boolean showHeaders = mExpanded && (mShowHeaders || dynamic);
if (row.cachedShowHeaders != showHeaders) {
row.cachedShowHeaders = showHeaders;
Util.setVisOrGone(row.header, showHeaders);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index 3d338098fc2d..44a435e61acc 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -122,7 +122,6 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
private void applyConfiguration() {
mDialog.setStreamImportant(AudioManager.STREAM_ALARM, true);
mDialog.setStreamImportant(AudioManager.STREAM_SYSTEM, false);
- mDialog.setShowHeaders(false);
mDialog.setAutomute(true);
mDialog.setSilentMode(false);
mController.setVolumePolicy(mVolumePolicy);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java
index bbb70ed6bf47..04339eb8e802 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePrefs.java
@@ -43,7 +43,7 @@ public class VolumePrefs {
public static final String PREF_ADJUST_ALARMS = "pref_adjust_alarms";
public static final String PREF_ADJUST_NOTIFICATION = "pref_adjust_notification";
- public static final boolean DEFAULT_SHOW_HEADERS = false;
+ public static final boolean DEFAULT_SHOW_HEADERS = true;
public static final boolean DEFAULT_ENABLE_AUTOMUTE = true;
public static final boolean DEFAULT_ENABLE_SILENT_MODE = true;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 26888130c7f0..c820302268b1 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -228,22 +228,23 @@ public class VolumeUI extends SystemUI {
}
final Intent intent = new Intent(Receiver.DISABLE)
.putExtra(Receiver.EXTRA_COMPONENT, component);
+ Notification.Builder builder = new Notification.Builder(mContext)
+ .setSmallIcon(R.drawable.ic_volume_media)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setOngoing(true)
+ .setContentTitle(mContext.getString(
+ R.string.volumeui_notification_title, getAppLabel(component)))
+ .setContentText(mContext.getString(R.string.volumeui_notification_text))
+ .setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent,
+ PendingIntent.FLAG_UPDATE_CURRENT))
+ .setPriority(Notification.PRIORITY_MIN)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+ overrideNotificationAppName(mContext, builder);
mNotificationManager.notify(R.id.notification_volumeui,
- new Notification.Builder(mContext)
- .setSmallIcon(R.drawable.ic_volume_media)
- .setWhen(0)
- .setShowWhen(false)
- .setOngoing(true)
- .setContentTitle(mContext.getString(
- R.string.volumeui_notification_title, getAppLabel(component)))
- .setContentText(mContext.getString(R.string.volumeui_notification_text))
- .setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT))
- .setPriority(Notification.PRIORITY_MIN)
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setColor(mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color))
- .build());
+ builder.build());
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
index a30f50775f77..c93377a68f5d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTests.java
@@ -36,6 +36,8 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
import android.util.Log;
+import org.mockito.Mockito;
+
@SmallTest
public class TileLifecycleManagerTests extends AndroidTestCase {
public static final String TILE_UPDATE_BROADCAST = "com.android.systemui.tests.TILE_UPDATE";
@@ -54,8 +56,11 @@ public class TileLifecycleManagerTests extends AndroidTestCase {
mThread = new HandlerThread("TestThread");
mThread.start();
mHandler = new Handler(mThread.getLooper());
+ ComponentName component = new ComponentName(mContext, FakeTileService.class);
mStateManager = new TileLifecycleManager(mHandler, getContext(),
- new Intent(mContext, FakeTileService.class), new UserHandle(UserHandle.myUserId()));
+ Mockito.mock(IQSService.class), new Tile(component),
+ new Intent().setComponent(component),
+ new UserHandle(UserHandle.myUserId()));
mCallbacks.clear();
getContext().registerReceiver(mReceiver, new IntentFilter(TILE_UPDATE_BROADCAST));
}
@@ -251,16 +256,6 @@ public class TileLifecycleManagerTests extends AndroidTestCase {
@Override
public IBinder onBind(Intent intent) {
return new IQSTileService.Stub() {
-
- @Override
- public void setQSService(IQSService service) {
-
- }
-
- @Override
- public void setQSTile(Tile tile) throws RemoteException {
- }
-
@Override
public void onTileAdded() throws RemoteException {
sendCallback("onTileAdded");
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
index 94c98d6c5b9a..de3864dc1fef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java
@@ -17,6 +17,7 @@ package com.android.systemui.qs.external;
import android.content.ComponentName;
import android.os.Looper;
+import android.service.quicksettings.Tile;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.phone.QSTileHost;
@@ -109,7 +110,7 @@ public class TileServicesTests extends SysuiTestCase {
}
@Override
- protected TileServiceManager onCreateTileService(ComponentName component) {
+ protected TileServiceManager onCreateTileService(ComponentName component, Tile qsTile) {
TileServiceManager manager = Mockito.mock(TileServiceManager.class);
mManagers.add(manager);
return manager;
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index a3ea592ebe5d..47d1493e1574 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -92,6 +92,11 @@ public class WallpaperBackupAgent extends BackupAgent {
if (DEBUG) {
Slog.v(TAG, "Wallpaper is backup-eligible; linking & writing");
}
+
+ // In case of prior muddled state
+ infoStage.delete();
+ imageStage.delete();
+
Os.link(mWallpaperInfo.getCanonicalPath(), infoStage.getCanonicalPath());
fullBackupFile(infoStage, data);
Os.link(mWallpaperFile.getCanonicalPath(), imageStage.getCanonicalPath());
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 4ed0913a0038..a82d55f839cc 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2337,6 +2337,27 @@ message MetricsEvent {
// ACTION: Settings -> Select support tab.
ACTION_SELECT_SUPPORT_FRAGMENT = 477;
+ // ACTION: Settings -> Support -> Tips & tricks
+ ACTION_SUPPORT_TIPS_AND_TRICKS = 478;
+
+ // ACTION: Settings -> Support -> Help & feedback
+ ACTION_SUPPORT_HELP_AND_FEEDBACK = 479;
+
+ // ACTION: Settings -> Support -> Sign in
+ ACTION_SUPPORT_SIGN_IN = 480;
+
+ // ACTION: Settings -> Support -> Phone
+ ACTION_SUPPORT_PHONE = 481;
+
+ // ACTION: Settings -> Support -> Chat
+ ACTION_SUPPORT_CHAT = 482;
+
+ // ACTION: Settings -> Support -> Phone/Chat -> Disclaimer Cancel
+ ACTION_SUPPORT_DISCLAIMER_CANCEL = 483;
+
+ // ACTION: Settings -> Support -> Phone/Chat -> Disclaimer OK
+ ACTION_SUPPORT_DISCLAIMER_OK = 484;
+
// ---- End N-MR1 Constants, all N-MR1 constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/Android.mk b/services/Android.mk
index 1918db54a049..3385bed0ba8b 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -28,6 +28,7 @@ services := \
net \
print \
restrictions \
+ retaildemo \
usage \
usb \
voiceinteraction
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 7da969f8fb6e..60d33397368d 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2228,7 +2228,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
@Override
public void handleMessage(Message message) {
final int eventType = message.what;
- notifyAccessibilityEventInternal(eventType);
+ AccessibilityEvent event = (AccessibilityEvent) message.obj;
+ notifyAccessibilityEventInternal(eventType, event);
}
};
@@ -3130,16 +3131,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
// be modified to remove its source if the receiving service does
// not have permission to access the window content.
AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
- AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
- mPendingEvents.put(eventType, newEvent);
-
- final int what = eventType;
- if (oldEvent != null) {
- mEventDispatchHandler.removeMessages(what);
- oldEvent.recycle();
+ Message message;
+ if ((mNotificationTimeout > 0)
+ && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) {
+ // Allow at most one pending event
+ final AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
+ mPendingEvents.put(eventType, newEvent);
+ if (oldEvent != null) {
+ mEventDispatchHandler.removeMessages(eventType);
+ oldEvent.recycle();
+ }
+ message = mEventDispatchHandler.obtainMessage(eventType);
+ } else {
+ // Send all messages, bypassing mPendingEvents
+ message = mEventDispatchHandler.obtainMessage(eventType, newEvent);
}
- Message message = mEventDispatchHandler.obtainMessage(what);
mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
}
}
@@ -3149,9 +3156,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
*
* @param eventType The type of the event to dispatch.
*/
- private void notifyAccessibilityEventInternal(int eventType) {
+ private void notifyAccessibilityEventInternal(int eventType, AccessibilityEvent event) {
IAccessibilityServiceClient listener;
- AccessibilityEvent event;
synchronized (mLock) {
listener = mServiceInterface;
@@ -3162,28 +3168,32 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return;
}
- event = mPendingEvents.get(eventType);
-
- // Check for null here because there is a concurrent scenario in which this
- // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked
- // which posts a message for dispatching an event. 2) The message is pulled
- // from the queue by the handler on the service thread and the latter is
- // just about to acquire the lock and call this method. 3) Now another binder
- // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked
- // so the service thread waits for the lock; 4) The binder thread replaces
- // the event with a more recent one (assume the same event type) and posts a
- // dispatch request releasing the lock. 5) Now the main thread is unblocked and
- // dispatches the event which is removed from the pending ones. 6) And ... now
- // the service thread handles the last message posted by the last binder call
- // but the event is already dispatched and hence looking it up in the pending
- // ones yields null. This check is much simpler that keeping count for each
- // event type of each service to catch such a scenario since only one message
- // is processed at a time.
+ // There are two ways we notify for events, throttled and non-throttled. If we
+ // are not throttling, then messages come with events, which we handle with
+ // minimal fuss.
if (event == null) {
- return;
+ // We are throttling events, so we'll send the event for this type in
+ // mPendingEvents as long as it it's null. It can only null due to a race
+ // condition:
+ //
+ // 1) A binder thread calls notifyAccessibilityServiceDelayedLocked
+ // which posts a message for dispatching an event and stores the event
+ // in mPendingEvents.
+ // 2) The message is pulled from the queue by the handler on the service
+ // thread and this method is just about to acquire the lock.
+ // 3) Another binder thread acquires the lock in notifyAccessibilityEvent
+ // 4) notifyAccessibilityEvent recycles the event that this method was about
+ // to process, replaces it with a new one, and posts a second message
+ // 5) This method grabs the new event, processes it, and removes it from
+ // mPendingEvents
+ // 6) The second message dispatched in (4) arrives, but the event has been
+ // remvoved in (5).
+ event = mPendingEvents.get(eventType);
+ if (event == null) {
+ return;
+ }
+ mPendingEvents.remove(eventType);
}
-
- mPendingEvents.remove(eventType);
if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) {
event.setConnectionId(mId);
} else {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 930c151b1485..e6f99c15ab66 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -725,6 +725,19 @@ public class BackupManagerService {
return true;
}
+ /* adb backup: is this app only capable of doing key/value? We say otherwise if
+ * the app has a backup agent and does not say fullBackupOnly, *unless* it
+ * is a package that we know _a priori_ explicitly supports both key/value and
+ * full-data backup.
+ */
+ private static boolean appIsKeyValueOnly(PackageInfo pkg) {
+ if ("com.android.providers.settings".equals(pkg.packageName)) {
+ return false;
+ }
+
+ return !appGetsFullBackup(pkg);
+ }
+
// ----- Asynchronous backup/restore handler thread -----
private class BackupHandler extends Handler {
@@ -3446,8 +3459,8 @@ public class BackupManagerService {
Intent obbIntent = new Intent().setComponent(new ComponentName(
"com.android.sharedstoragebackup",
"com.android.sharedstoragebackup.ObbBackupService"));
- BackupManagerService.this.mContext.bindService(
- obbIntent, this, Context.BIND_AUTO_CREATE);
+ BackupManagerService.this.mContext.bindServiceAsUser(
+ obbIntent, this, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
}
public void tearDown() {
@@ -3965,7 +3978,7 @@ public class BackupManagerService {
}
// Full backup task variant used for adb backup
- class PerformAdbBackupTask extends FullBackupTask {
+ class PerformAdbBackupTask extends FullBackupTask implements BackupRestoreTask {
FullBackupEngine mBackupEngine;
final AtomicBoolean mLatch;
@@ -3979,6 +3992,7 @@ public class BackupManagerService {
boolean mIncludeSystem;
boolean mCompress;
ArrayList<String> mPackages;
+ PackageInfo mCurrentTarget;
String mCurrentPassword;
String mEncryptPassword;
@@ -4009,6 +4023,9 @@ public class BackupManagerService {
} else {
mEncryptPassword = encryptPassword;
}
+ if (MORE_DEBUG) {
+ Slog.w(TAG, "Encrypting backup with passphrase=" + mEncryptPassword);
+ }
mCompress = doCompress;
}
@@ -4165,7 +4182,9 @@ public class BackupManagerService {
Iterator<Entry<String, PackageInfo>> iter = packagesToBackup.entrySet().iterator();
while (iter.hasNext()) {
PackageInfo pkg = iter.next().getValue();
- if (!appIsEligibleForBackup(pkg.applicationInfo)) {
+ if (!appIsEligibleForBackup(pkg.applicationInfo)
+ || appIsStopped(pkg.applicationInfo)
+ || appIsKeyValueOnly(pkg)) {
iter.remove();
}
}
@@ -4267,9 +4286,11 @@ public class BackupManagerService {
final boolean isSharedStorage =
pkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
- mBackupEngine = new FullBackupEngine(out, null, pkg, mIncludeApks, null);
+ mBackupEngine = new FullBackupEngine(out, null, pkg, mIncludeApks, this);
sendOnBackupPackage(isSharedStorage ? "Shared storage" : pkg.packageName);
+
// Don't need to check preflight result as there is no preflight hook.
+ mCurrentTarget = pkg;
mBackupEngine.backupOnePackage();
// after the app's agent runs to handle its private filesystem
@@ -4308,6 +4329,28 @@ public class BackupManagerService {
mWakelock.release();
}
}
+
+ // BackupRestoreTask methods, used for timeout handling
+ @Override
+ public void execute() {
+ // Unused
+ }
+
+ @Override
+ public void operationComplete(long result) {
+ // Unused
+ }
+
+ @Override
+ public void handleTimeout() {
+ final PackageInfo target = mCurrentTarget;
+ if (DEBUG) {
+ Slog.w(TAG, "adb backup timeout of " + target);
+ }
+ if (target != null) {
+ tearDownAgentAndKill(mCurrentTarget.applicationInfo);
+ }
+ }
}
// Full backup task extension used for transport-oriented operation
@@ -5255,7 +5298,7 @@ public class BackupManagerService {
byte[] mWidgetData = null;
// Runner that can be placed in a separate thread to do in-process
- // invocations of the full restore API asynchronously
+ // invocations of the full restore API asynchronously. Used by adb restore.
class RestoreFileRunnable implements Runnable {
IBackupAgent mAgent;
FileMetadata mInfo;
@@ -6404,6 +6447,46 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// ***** end new engine class ***
+ // Used for synchronizing doRestoreFinished during adb restore
+ class AdbRestoreFinishedLatch implements BackupRestoreTask {
+ static final String TAG = "AdbRestoreFinishedLatch";
+ final CountDownLatch mLatch;
+
+ AdbRestoreFinishedLatch() {
+ mLatch = new CountDownLatch(1);
+ }
+
+ void await() {
+ boolean latched = false;
+ try {
+ latched = mLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ Slog.w(TAG, "Interrupted!");
+ }
+ }
+
+ @Override
+ public void execute() {
+ // Unused
+ }
+
+ @Override
+ public void operationComplete(long result) {
+ if (MORE_DEBUG) {
+ Slog.w(TAG, "adb onRestoreFinished() complete");
+ }
+ mLatch.countDown();
+ }
+
+ @Override
+ public void handleTimeout() {
+ if (DEBUG) {
+ Slog.w(TAG, "adb onRestoreFinished() timed out");
+ }
+ mLatch.countDown();
+ }
+ }
+
class PerformAdbRestoreTask implements Runnable {
ParcelFileDescriptor mInputFile;
String mCurrentPassword;
@@ -6419,6 +6502,27 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
long mBytes;
+ // Runner that can be placed on a separate thread to do in-process invocation
+ // of the "restore finished" API asynchronously. Used by adb restore.
+ class RestoreFinishedRunnable implements Runnable {
+ final IBackupAgent mAgent;
+ final int mToken;
+
+ RestoreFinishedRunnable(IBackupAgent agent, int token) {
+ mAgent = agent;
+ mToken = token;
+ }
+
+ @Override
+ public void run() {
+ try {
+ mAgent.doRestoreFinished(mToken, mBackupManagerBinder);
+ } catch (RemoteException e) {
+ // never happens; this is used only for local binder calls
+ }
+ }
+ }
+
// possible handling states for a given package in the restore dataset
final HashMap<String, RestorePolicy> mPackagePolicies
= new HashMap<String, RestorePolicy>();
@@ -6560,7 +6664,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
Slog.e(TAG, "Unable to read restore input");
} finally {
tearDownPipes();
- tearDownAgent(mTargetApp);
+ tearDownAgent(mTargetApp, true);
try {
if (rawDataIn != null) rawDataIn.close();
@@ -6714,7 +6818,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
if (DEBUG) Slog.d(TAG, "Saw new package; finalizing old one");
// Now we're really done
tearDownPipes();
- tearDownAgent(mTargetApp);
+ tearDownAgent(mTargetApp, true);
mTargetApp = null;
mAgentPackage = null;
}
@@ -6936,10 +7040,12 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// okay, if the remote end failed at any point, deal with
// it by ignoring the rest of the restore on it
if (!agentSuccess) {
+ if (DEBUG) {
+ Slog.d(TAG, "Agent failure restoring " + pkg + "; now ignoring");
+ }
mBackupHandler.removeMessages(MSG_TIMEOUT);
tearDownPipes();
- tearDownAgent(mTargetApp);
- mAgent = null;
+ tearDownAgent(mTargetApp, false);
mPackagePolicies.put(pkg, RestorePolicy.IGNORE);
}
}
@@ -6988,9 +7094,27 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
}
}
- void tearDownAgent(ApplicationInfo app) {
+ void tearDownAgent(ApplicationInfo app, boolean doRestoreFinished) {
if (mAgent != null) {
try {
+ // In the adb restore case, we do restore-finished here
+ if (doRestoreFinished) {
+ final int token = generateToken();
+ final AdbRestoreFinishedLatch latch = new AdbRestoreFinishedLatch();
+ prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL, latch);
+ if (mTargetApp.processName.equals("system")) {
+ if (MORE_DEBUG) {
+ Slog.d(TAG, "system agent - restoreFinished on thread");
+ }
+ Runnable runner = new RestoreFinishedRunnable(mAgent, token);
+ new Thread(runner, "restore-sys-finished-runner").start();
+ } else {
+ mAgent.doRestoreFinished(token, mBackupManagerBinder);
+ }
+
+ latch.await();
+ }
+
// unbind and tidy up even on timeout or failure, just in case
mActivityManager.unbindBackupAgent(app);
@@ -9354,7 +9478,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
"com.android.backupconfirm.BackupRestoreConfirmation");
confIntent.putExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, token);
confIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(confIntent);
+ mContext.startActivityAsUser(confIntent, UserHandle.SYSTEM);
} catch (ActivityNotFoundException e) {
return false;
}
@@ -9598,6 +9722,15 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
return list;
}
+ public String[] getTransportWhitelist() {
+ // No permission check, intentionally.
+ String[] whitelist = new String[mTransportWhitelist.size()];
+ for (int i = mTransportWhitelist.size() - 1; i >= 0; i--) {
+ whitelist[i] = mTransportWhitelist.valueAt(i).flattenToShortString();
+ }
+ return whitelist;
+ }
+
// Select which transport to use for the next backup operation.
public String selectBackupTransport(String transport) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index e74526338a8f..312b878b284c 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -275,6 +275,12 @@ public class Trampoline extends IBackupManager.Stub {
}
@Override
+ public String[] getTransportWhitelist() {
+ BackupManagerService svc = mService;
+ return (svc != null) ? svc.getTransportWhitelist() : null;
+ }
+
+ @Override
public String selectBackupTransport(String transport) throws RemoteException {
BackupManagerService svc = mService;
return (svc != null) ? svc.selectBackupTransport(transport) : null;
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 400c4a700a8e..312553a980b2 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -3074,9 +3074,6 @@ class AlarmManagerService extends SystemService {
if (alarm.workSource != null && alarm.workSource.size() > 0) {
for (int wi=0; wi<alarm.workSource.size(); wi++) {
final String wsName = alarm.workSource.getName(wi);
- if (wsName == null) {
- Slog.w(TAG, "Null worksource name for alarm " + alarm);
- }
ActivityManagerNative.noteWakeupAlarm(
alarm.operation, alarm.workSource.get(wi),
(wsName != null) ? wsName : alarm.packageName,
diff --git a/services/core/java/com/android/server/AttributeCache.java b/services/core/java/com/android/server/AttributeCache.java
index 57f18c086c56..58ec836547a7 100644
--- a/services/core/java/com/android/server/AttributeCache.java
+++ b/services/core/java/com/android/server/AttributeCache.java
@@ -25,23 +25,24 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.LruCache;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
-import java.lang.ref.WeakReference;
-
/**
* TODO: This should be better integrated into the system so it doesn't need
* special calls from the activity manager to clear it.
*/
public final class AttributeCache {
+ private static final int CACHE_SIZE = 4;
private static AttributeCache sInstance = null;
private final Context mContext;
@GuardedBy("this")
- private final ArrayMap<String, WeakReference<Package>> mPackages = new ArrayMap<>();
+ private final LruCache<String, Package> mPackages = new LruCache<>(CACHE_SIZE);
+
@GuardedBy("this")
private final Configuration mConfiguration = new Configuration();
@@ -86,15 +87,12 @@ public final class AttributeCache {
public void removePackage(String packageName) {
synchronized (this) {
- final WeakReference<Package> ref = mPackages.remove(packageName);
- final Package pkg = (ref != null) ? ref.get() : null;
+ final Package pkg = mPackages.remove(packageName);
if (pkg != null) {
- if (pkg.mMap != null) {
- for (int i = 0; i < pkg.mMap.size(); i++) {
- final ArrayMap<int[], Entry> map = pkg.mMap.valueAt(i);
- for (int j = 0; j < map.size(); j++) {
- map.valueAt(j).recycle();
- }
+ for (int i = 0; i < pkg.mMap.size(); i++) {
+ final ArrayMap<int[], Entry> map = pkg.mMap.valueAt(i);
+ for (int j = 0; j < map.size(); j++) {
+ map.valueAt(j).recycle();
}
}
@@ -113,15 +111,14 @@ public final class AttributeCache {
// The configurations being masked out are ones that commonly
// change so we don't want flushing the cache... all others
// will flush the cache.
- mPackages.clear();
+ mPackages.evictAll();
}
}
}
public Entry get(String packageName, int resId, int[] styleable, int userId) {
synchronized (this) {
- WeakReference<Package> ref = mPackages.get(packageName);
- Package pkg = (ref != null) ? ref.get() : null;
+ Package pkg = mPackages.get(packageName);
ArrayMap<int[], Entry> map = null;
Entry ent = null;
if (pkg != null) {
@@ -144,7 +141,7 @@ public final class AttributeCache {
return null;
}
pkg = new Package(context);
- mPackages.put(packageName, new WeakReference<>(pkg));
+ mPackages.put(packageName, pkg);
}
if (map == null) {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 71964d16ea44..8c5887f7a514 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -61,7 +61,7 @@ import java.util.Map;
class BluetoothManagerService extends IBluetoothManager.Stub {
private static final String TAG = "BluetoothManagerService";
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
@@ -1171,8 +1171,27 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);
mEnable = true;
+
+ // Use service interface to get the exact state
+ try {
+ mBluetoothLock.readLock().lock();
+ if (mBluetooth != null) {
+ int state = mBluetooth.getState();
+ if (state == BluetoothAdapter.STATE_BLE_ON) {
+ Slog.w(TAG, "BT is in BLE_ON State");
+ mBluetooth.onLeServiceUp();
+ break;
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "", e);
+ } finally {
+ mBluetoothLock.readLock().unlock();
+ }
+
+ mQuietEnable = (msg.arg1 == 1);
if (mBluetooth == null) {
- handleEnable(msg.arg1 == 1);
+ handleEnable(mQuietEnable);
} else {
//
// We need to wait until transitioned to STATE_OFF and
@@ -1190,7 +1209,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
// on the order of (2 * SERVICE_RESTART_TIME_MS).
//
waitForOnOff(false, true);
- mQuietEnable = (msg.arg1 == 1);
Message restartMsg = mHandler.obtainMessage(
MESSAGE_RESTART_BLUETOOTH_SERVICE);
mHandler.sendMessageDelayed(restartMsg,
@@ -1353,17 +1371,30 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
// handle error state transition case from TURNING_ON to OFF
// unbind and rebind bluetooth service and enable bluetooth
if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_ON) &&
- (newState == BluetoothAdapter.STATE_OFF) &&
- (mBluetooth != null) && mEnable) {
+ (newState == BluetoothAdapter.STATE_OFF) &&
+ (mBluetooth != null) && mEnable) {
recoverBluetoothServiceFromError();
}
if ((prevState == BluetoothAdapter.STATE_TURNING_ON) &&
- (newState == BluetoothAdapter.STATE_BLE_ON) &&
- (mBluetooth != null) && mEnable) {
+ (newState == BluetoothAdapter.STATE_BLE_ON) &&
+ (mBluetooth != null) && mEnable) {
recoverBluetoothServiceFromError();
}
+ // If we tried to enable BT while BT was in the process of shutting down,
+ // wait for the BT process to fully tear down and then force a restart
+ // here. This is a bit of a hack (b/29363429).
+ if ((prevState == BluetoothAdapter.STATE_BLE_TURNING_OFF) &&
+ (newState == BluetoothAdapter.STATE_OFF)) {
+ if (mEnable) {
+ Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting.");
+ waitForOnOff(false, true);
+ Message restartMsg = mHandler.obtainMessage(
+ MESSAGE_RESTART_BLUETOOTH_SERVICE);
+ mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS);
+ }
+ }
if (newState == BluetoothAdapter.STATE_ON ||
- newState == BluetoothAdapter.STATE_BLE_ON) {
+ newState == BluetoothAdapter.STATE_BLE_ON) {
// bluetooth is working, reset the counter
if (mErrorRecoveryRetryCounter != 0) {
Slog.w(TAG, "bluetooth is recovered from error");
@@ -1406,7 +1437,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
// Send BT state broadcast to update
// the BT icon correctly
if ((mState == BluetoothAdapter.STATE_TURNING_ON) ||
- (mState == BluetoothAdapter.STATE_ON)) {
+ (mState == BluetoothAdapter.STATE_ON)) {
bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
BluetoothAdapter.STATE_TURNING_OFF);
mState = BluetoothAdapter.STATE_TURNING_OFF;
@@ -1481,7 +1512,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
BluetoothAdapter.STATE_TURNING_OFF);
- waitForOnOff(false, true);
+ boolean didDisableTimeout = !waitForOnOff(false, true);
bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF,
BluetoothAdapter.STATE_OFF);
@@ -1499,7 +1530,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mBluetoothLock.writeLock().unlock();
}
- SystemClock.sleep(100);
+ //
+ // If disabling Bluetooth times out, wait for an
+ // additional amount of time to ensure the process is
+ // shut down completely before attempting to restart.
+ //
+ if (didDisableTimeout) {
+ SystemClock.sleep(3000);
+ } else {
+ SystemClock.sleep(100);
+ }
mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
mState = BluetoothAdapter.STATE_OFF;
@@ -1639,8 +1679,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
boolean isStandardBroadcast = true;
if (prevState != newState) {
//Notify all proxy objects first of adapter state change
- if (newState == BluetoothAdapter.STATE_BLE_ON
- || newState == BluetoothAdapter.STATE_OFF) {
+ if (newState == BluetoothAdapter.STATE_BLE_ON ||
+ newState == BluetoothAdapter.STATE_OFF) {
boolean intermediate_off = (prevState == BluetoothAdapter.STATE_TURNING_OFF
&& newState == BluetoothAdapter.STATE_BLE_ON);
@@ -1685,13 +1725,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
sendBluetoothStateCallback(isUp);
sendBleStateChanged(prevState, newState);
- } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON
- || newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) {
+ } else if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON ||
+ newState == BluetoothAdapter.STATE_BLE_TURNING_OFF ) {
sendBleStateChanged(prevState, newState);
isStandardBroadcast = false;
- } else if (newState == BluetoothAdapter.STATE_TURNING_ON
- || newState == BluetoothAdapter.STATE_TURNING_OFF) {
+ } else if (newState == BluetoothAdapter.STATE_TURNING_ON ||
+ newState == BluetoothAdapter.STATE_TURNING_OFF) {
sendBleStateChanged(prevState, newState);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index e65b50c894f9..1a7a2bf88a88 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -30,8 +30,6 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
-import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
-import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
@@ -78,6 +76,7 @@ import android.net.RouteInfo;
import android.net.UidRange;
import android.net.Uri;
import android.net.metrics.DefaultNetworkEvent;
+import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.os.Binder;
import android.os.Build;
@@ -456,6 +455,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
+
/**
* Implements support for the legacy "one network per network type" model.
*
@@ -489,8 +490,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
*
* The actual lists are populated when we scan the network types that
* are supported on this device.
+ *
+ * Threading model:
+ * - addSupportedType() is only called in the constructor
+ * - add(), update(), remove() are only called from the ConnectivityService handler thread.
+ * They are therefore not thread-safe with respect to each other.
+ * - getNetworkForType() can be called at any time on binder threads. It is synchronized
+ * on mTypeLists to be thread-safe with respect to a concurrent remove call.
+ * - dump is thread-safe with respect to concurrent add and remove calls.
*/
- private ArrayList<NetworkAgentInfo> mTypeLists[];
+ private final ArrayList<NetworkAgentInfo> mTypeLists[];
public LegacyTypeTracker() {
mTypeLists = (ArrayList<NetworkAgentInfo>[])
@@ -510,11 +519,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
public NetworkAgentInfo getNetworkForType(int type) {
- if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
- return mTypeLists[type].get(0);
- } else {
- return null;
+ synchronized (mTypeLists) {
+ if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
+ return mTypeLists[type].get(0);
+ }
}
+ return null;
}
private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
@@ -537,12 +547,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (list.contains(nai)) {
return;
}
-
- list.add(nai);
+ synchronized (mTypeLists) {
+ list.add(nai);
+ }
// Send a broadcast if this is the first network of its type or if it's the default.
final boolean isDefaultNetwork = isDefaultNetwork(nai);
- if (list.size() == 1 || isDefaultNetwork) {
+ if ((list.size() == 1) || isDefaultNetwork) {
maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork);
sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type);
}
@@ -554,11 +565,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (list == null || list.isEmpty()) {
return;
}
-
final boolean wasFirstNetwork = list.get(0).equals(nai);
- if (!list.remove(nai)) {
- return;
+ synchronized (mTypeLists) {
+ if (!list.remove(nai)) {
+ return;
+ }
}
final DetailedState state = DetailedState.DISCONNECTED;
@@ -593,8 +605,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
for (int type = 0; type < mTypeLists.length; type++) {
final ArrayList<NetworkAgentInfo> list = mTypeLists[type];
final boolean contains = (list != null && list.contains(nai));
- final boolean isFirst = (list != null && list.size() > 0 && nai == list.get(0));
- if (isFirst || (contains && isDefault)) {
+ final boolean isFirst = contains && (nai == list.get(0));
+ if (isFirst || contains && isDefault) {
maybeLogBroadcast(nai, state, type, isDefault);
sendLegacyNetworkBroadcast(nai, state, type);
}
@@ -619,10 +631,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.println();
pw.println("Current state:");
pw.increaseIndent();
- for (int type = 0; type < mTypeLists.length; type++) {
- if (mTypeLists[type] == null|| mTypeLists[type].size() == 0) continue;
- for (NetworkAgentInfo nai : mTypeLists[type]) {
- pw.println(type + " " + naiToString(nai));
+ synchronized (mTypeLists) {
+ for (int type = 0; type < mTypeLists.length; type++) {
+ if (mTypeLists[type] == null || mTypeLists[type].isEmpty()) continue;
+ for (NetworkAgentInfo nai : mTypeLists[type]) {
+ pw.println(type + " " + naiToString(nai));
+ }
}
}
pw.decreaseIndent();
@@ -932,7 +946,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Networks aren't blocked when ignoring blocked status
if (ignoreBlocked) return false;
// Networks are never blocked for system services
- if (uid < Process.FIRST_APPLICATION_UID) return false;
+ if (isSystem(uid)) return false;
final boolean networkMetered;
final int uidRules;
@@ -2194,7 +2208,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void linger(NetworkAgentInfo nai) {
nai.lingering = true;
- NetworkEvent.logEvent(nai.network.netId, NetworkEvent.NETWORK_LINGER);
+ logNetworkEvent(nai, NetworkEvent.NETWORK_LINGER);
nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_LINGER);
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING);
}
@@ -2208,7 +2222,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
nai.networkLingered.clear();
if (!nai.lingering) return;
nai.lingering = false;
- NetworkEvent.logEvent(nai.network.netId, NetworkEvent.NETWORK_UNLINGER);
+ logNetworkEvent(nai, NetworkEvent.NETWORK_UNLINGER);
if (VDBG) log("Canceling linger of " + nai.name());
nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
}
@@ -4046,12 +4060,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
return false;
}
+ private boolean isSystem(int uid) {
+ return uid < Process.FIRST_APPLICATION_UID;
+ }
private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
+ final int uid = Binder.getCallingUid();
+ if (isSystem(uid)) {
+ return;
+ }
// if UID is restricted, don't allow them to bring up metered APNs
if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED) == false) {
final int uidRules;
- final int uid = Binder.getCallingUid();
synchronized(mRulesLock) {
uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
}
@@ -5225,7 +5245,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
return new NetworkMonitor(context, handler, nai, defaultRequest);
}
- private static void logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai) {
+ private void logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai) {
int newNetid = NETID_UNSET;
int prevNetid = NETID_UNSET;
int[] transports = new int[0];
@@ -5243,6 +5263,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
hadIPv6 = lp.hasGlobalIPv6Address() && lp.hasIPv6DefaultRoute();
}
- DefaultNetworkEvent.logEvent(newNetid, transports, prevNetid, hadIPv4, hadIPv6);
+ mMetricsLog.log(new DefaultNetworkEvent(newNetid, transports, prevNetid, hadIPv4, hadIPv6));
+ }
+
+ private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
+ mMetricsLog.log(new NetworkEvent(nai.network.netId, evtype));
}
}
diff --git a/services/core/java/com/android/server/InputContentUriTokenHandler.java b/services/core/java/com/android/server/InputContentUriTokenHandler.java
new file mode 100644
index 000000000000..3f4972babf6e
--- /dev/null
+++ b/services/core/java/com/android/server/InputContentUriTokenHandler.java
@@ -0,0 +1,121 @@
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package com.android.server;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.app.ActivityManagerNative;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.IInputContentUriToken;
+
+final class InputContentUriTokenHandler extends IInputContentUriToken.Stub {
+
+ @NonNull
+ private final Uri mUri;
+ private final int mSourceUid;
+ @NonNull
+ private final String mTargetPackage;
+ @UserIdInt
+ private final int mSourceUserId;
+ @UserIdInt
+ private final int mTargetUserId;
+
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private IBinder mPermissionOwnerToken = null;
+
+ InputContentUriTokenHandler(@NonNull Uri contentUri, int sourceUid,
+ @NonNull String targetPackage, @UserIdInt int sourceUserId,
+ @UserIdInt int targetUserId) {
+ mUri = contentUri;
+ mSourceUid = sourceUid;
+ mTargetPackage = targetPackage;
+ mSourceUserId = sourceUserId;
+ mTargetUserId = targetUserId;
+ }
+
+ @Override
+ public void take() {
+ synchronized (mLock) {
+ if (mPermissionOwnerToken != null) {
+ // Permission is already granted.
+ return;
+ }
+
+ try {
+ mPermissionOwnerToken = ActivityManagerNative.getDefault()
+ .newUriPermissionOwner("InputContentUriTokenHandler");
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+
+ doTakeLocked(mPermissionOwnerToken);
+ }
+ }
+
+ private void doTakeLocked(@NonNull IBinder permissionOwner) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ try {
+ ActivityManagerNative.getDefault().grantUriPermissionFromOwner(
+ permissionOwner, mSourceUid, mTargetPackage, mUri,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION, mSourceUserId, mTargetUserId);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ @Override
+ public void release() {
+ synchronized (mLock) {
+ if (mPermissionOwnerToken == null) {
+ return;
+ }
+ try {
+ ActivityManagerNative.getDefault().revokeUriPermissionFromOwner(
+ mPermissionOwnerToken, mUri,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION, mSourceUserId);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ } finally {
+ mPermissionOwnerToken = null;
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ release();
+ } finally {
+ super.finalize();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 5d8fe7c68fe8..e0d89f2fe6d3 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -18,6 +18,7 @@ package com.android.server;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
import com.android.internal.inputmethod.InputMethodUtils;
@@ -137,6 +138,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.nio.charset.StandardCharsets;
+import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -3911,6 +3913,52 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
@Override
+ public IInputContentUriToken createInputContentUriToken(@Nullable IBinder token,
+ @Nullable Uri contentUri, @Nullable String packageName) {
+ if (!calledFromValidUser()) {
+ return null;
+ }
+
+ if (token == null) {
+ throw new NullPointerException("token");
+ }
+ if (packageName == null) {
+ throw new NullPointerException("packageName");
+ }
+ if (contentUri == null) {
+ throw new NullPointerException("contentUri");
+ }
+ final String contentUriScheme = contentUri.getScheme();
+ if (!"content".equals(contentUriScheme)) {
+ throw new InvalidParameterException("contentUri must have content scheme");
+ }
+
+ synchronized (mMethodMap) {
+ final int uid = Binder.getCallingUid();
+ if (mCurMethodId == null) {
+ return null;
+ }
+ if (mCurToken != token) {
+ Slog.e(TAG, "Ignoring createInputContentUriToken mCurToken=" + mCurToken
+ + " token=" + token);
+ return null;
+ }
+ // We cannot simply distinguish a bad IME that reports an arbitrary package name from
+ // an unfortunate IME whose internal state is already obsolete due to the asynchronous
+ // nature of our system. Let's compare it with our internal record.
+ if (!TextUtils.equals(mCurAttribute.packageName, packageName)) {
+ Slog.e(TAG, "Ignoring createInputContentUriToken mCurAttribute.packageName="
+ + mCurAttribute.packageName + " packageName=" + packageName);
+ return null;
+ }
+ final int imeUserId = UserHandle.getUserId(uid);
+ final int appUserId = UserHandle.getUserId(mCurClient.uid);
+ return new InputContentUriTokenHandler(contentUri, uid, packageName, imeUserId,
+ appUserId);
+ }
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index ef7b78789b2e..d64fe32cca55 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -423,6 +423,9 @@ public class LockSettingsService extends ILockSettings.Stub {
if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
// Notify keystore that a new user was added.
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+ if (userHandle > UserHandle.USER_SYSTEM) {
+ removeUser(userHandle, /* unknownUser= */ true);
+ }
final KeyStore ks = KeyStore.getInstance();
final UserInfo parentInfo = mUserManager.getProfileParent(userHandle);
final int parentHandle = parentInfo != null ? parentInfo.id : -1;
@@ -433,7 +436,7 @@ public class LockSettingsService extends ILockSettings.Stub {
} else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
if (userHandle > 0) {
- removeUser(userHandle);
+ removeUser(userHandle, /* unknownUser= */ false);
}
}
}
@@ -1465,7 +1468,7 @@ public class LockSettingsService extends ILockSettings.Stub {
return false;
}
- private void removeUser(int userId) {
+ private void removeUser(int userId, boolean unknownUser) {
mStorage.removeUser(userId);
mStrongAuth.removeUser(userId);
@@ -1480,7 +1483,7 @@ public class LockSettingsService extends ILockSettings.Stub {
} catch (RemoteException ex) {
Slog.w(TAG, "unable to clear GK secure user id");
}
- if (mUserManager.getUserInfo(userId).isManagedProfile()) {
+ if (unknownUser || mUserManager.getUserInfo(userId).isManagedProfile()) {
removeKeystoreProfileKey(userId);
}
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 9c75a009d7af..cdd977be29ed 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -827,8 +827,9 @@ class MountService extends IMountService.Stub
if (provider != null) {
final IActivityManager am = ActivityManagerNative.getDefault();
try {
- am.killApplicationWithAppId(provider.applicationInfo.packageName,
- UserHandle.getAppId(provider.applicationInfo.uid), "vold reset");
+ am.killApplication(provider.applicationInfo.packageName,
+ UserHandle.getAppId(provider.applicationInfo.uid),
+ UserHandle.USER_ALL, "vold reset");
// We only need to run this once. It will kill all users' media processes.
break;
} catch (RemoteException e) {
@@ -2030,6 +2031,9 @@ class MountService extends IMountService.Stub
enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
waitForReady();
+ final VolumeInfo from;
+ final VolumeInfo to;
+
synchronized (mLock) {
if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) {
throw new IllegalArgumentException("Primary storage already at " + volumeUuid);
@@ -2049,10 +2053,11 @@ class MountService extends IMountService.Stub
onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED);
onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED);
mHandler.obtainMessage(H_RESET).sendToTarget();
+ return;
} else {
- final VolumeInfo from = findStorageForUuid(mPrimaryStorageUuid);
- final VolumeInfo to = findStorageForUuid(volumeUuid);
+ from = findStorageForUuid(mPrimaryStorageUuid);
+ to = findStorageForUuid(volumeUuid);
if (from == null) {
Slog.w(TAG, "Failing move due to missing from volume " + mPrimaryStorageUuid);
@@ -2063,14 +2068,14 @@ class MountService extends IMountService.Stub
onMoveStatusLocked(PackageManager.MOVE_FAILED_INTERNAL_ERROR);
return;
}
-
- try {
- mConnector.execute("volume", "move_storage", from.id, to.id);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
- }
}
}
+
+ try {
+ mConnector.execute("volume", "move_storage", from.id, to.id);
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
+ }
}
@Override
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index ecc69e90b7a3..90f507c146bf 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -156,12 +156,15 @@ public class SystemServiceManager {
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStartUser "
+ + service.getClass().getName());
try {
service.onStartUser(userHandle);
} catch (Exception ex) {
Slog.wtf(TAG, "Failure reporting start of user " + userHandle
+ " to service " + service.getClass().getName(), ex);
}
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
@@ -169,12 +172,15 @@ public class SystemServiceManager {
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onUnlockUser "
+ + service.getClass().getName());
try {
service.onUnlockUser(userHandle);
} catch (Exception ex) {
Slog.wtf(TAG, "Failure reporting unlock of user " + userHandle
+ " to service " + service.getClass().getName(), ex);
}
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
@@ -182,12 +188,15 @@ public class SystemServiceManager {
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onSwitchUser "
+ + service.getClass().getName());
try {
service.onSwitchUser(userHandle);
} catch (Exception ex) {
Slog.wtf(TAG, "Failure reporting switch of user " + userHandle
+ " to service " + service.getClass().getName(), ex);
}
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
@@ -195,12 +204,15 @@ public class SystemServiceManager {
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onStopUser "
+ + service.getClass().getName());
try {
service.onStopUser(userHandle);
} catch (Exception ex) {
Slog.wtf(TAG, "Failure reporting stop of user " + userHandle
+ " to service " + service.getClass().getName(), ex);
}
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
@@ -208,12 +220,15 @@ public class SystemServiceManager {
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
+ Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "onCleanupUser "
+ + service.getClass().getName());
try {
service.onCleanupUser(userHandle);
} catch (Exception ex) {
Slog.wtf(TAG, "Failure reporting cleanup of user " + userHandle
+ " to service " + service.getClass().getName(), ex);
}
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 7f3eb15c6ebf..ab036c7163d3 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -487,7 +487,7 @@ public class VibratorService extends IVibratorService.Stub
private boolean shouldVibrateForRingtone() {
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- int ringerMode = audioManager.getRingerMode();
+ int ringerMode = audioManager.getRingerModeInternal();
// "Also vibrate for calls" Setting in Sound
if (Settings.System.getInt(
mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 0cf517274f30..f7bd04b08ede 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3538,7 +3538,7 @@ public class AccountManagerService
@Override
public void addSharedAccountsFromParentUser(int parentUserId, int userId) {
- checkManageUsersPermission("addSharedAccountsFromParentUser");
+ checkManageOrCreateUsersPermission("addSharedAccountsFromParentUser");
Account[] accounts = getAccountsAsUser(null, parentUserId, mContext.getOpPackageName());
for (Account account : accounts) {
addSharedAccountAsUser(account, userId);
@@ -5092,6 +5092,16 @@ public class AccountManagerService
}
}
+ private static void checkManageOrCreateUsersPermission(String message) {
+ if (ActivityManager.checkComponentPermission(android.Manifest.permission.MANAGE_USERS,
+ Binder.getCallingUid(), -1, true) != PackageManager.PERMISSION_GRANTED &&
+ ActivityManager.checkComponentPermission(android.Manifest.permission.CREATE_USERS,
+ Binder.getCallingUid(), -1, true) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("You need MANAGE_USERS or CREATE_USERS permission to: "
+ + message);
+ }
+ }
+
private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType,
int callerUid) {
if (callerUid == Process.SYSTEM_UID) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index dcd9b0c7e643..ee2fa51c8666 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -43,7 +43,6 @@ import android.os.TransactionTooLargeException;
import android.util.ArrayMap;
import android.util.ArraySet;
-import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ServiceState;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.TransferPipe;
@@ -751,6 +750,17 @@ public final class ActiveServices {
mAm.updateProcessForegroundLocked(proc, anyForeground, oomAdj);
}
+ private void updateWhitelistManagerLocked(ProcessRecord proc) {
+ proc.whitelistManager = false;
+ for (int i=proc.services.size()-1; i>=0; i--) {
+ ServiceRecord sr = proc.services.valueAt(i);
+ if (sr.whitelistManager) {
+ proc.whitelistManager = true;
+ break;
+ }
+ }
+ }
+
public void updateServiceConnectionActivitiesLocked(ProcessRecord clientProc) {
ArraySet<ProcessRecord> updatedProcesses = null;
for (int i = 0; i < clientProc.connections.size(); i++) {
@@ -997,6 +1007,9 @@ public final class ActiveServices {
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
+ if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
+ s.whitelistManager = true;
+ }
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
@@ -1019,6 +1032,9 @@ public final class ActiveServices {
if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
s.app.treatLikeActivity = true;
}
+ if (s.whitelistManager) {
+ s.app.whitelistManager = true;
+ }
// This could have made the service more important.
mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
|| s.app.treatLikeActivity, b.client);
@@ -1132,9 +1148,7 @@ public final class ActiveServices {
if (r.binding.service.app != null) {
if (r.binding.service.app.whitelistManager) {
- // Must reset flag here because on computeOomAdjLocked() the service
- // connection will be gone...
- r.binding.service.app.whitelistManager = false;
+ updateWhitelistManagerLocked(r.binding.service.app);
}
// This could have made the service less important.
if ((r.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
@@ -1443,6 +1457,12 @@ public final class ActiveServices {
boolean allowCancel) {
boolean canceled = false;
+ if (mAm.isShuttingDownLocked()) {
+ Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortName
+ + " - system is shutting down");
+ return false;
+ }
+
ServiceMap smap = getServiceMap(r.userId);
if (smap.mServicesByName.get(r.name) != r) {
ServiceRecord cur = smap.mServicesByName.get(r.name);
@@ -1801,6 +1821,10 @@ public final class ActiveServices {
}
}
+ if (r.whitelistManager) {
+ app.whitelistManager = true;
+ }
+
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
@@ -2012,6 +2036,9 @@ public final class ActiveServices {
r.stats.stopLaunchedLocked();
}
r.app.services.remove(r);
+ if (r.whitelistManager) {
+ updateWhitelistManagerLocked(r.app);
+ }
if (r.app.thread != null) {
updateServiceForegroundLocked(r.app, false);
try {
@@ -2079,6 +2106,14 @@ public final class ActiveServices {
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.updateHasAboveClientLocked();
}
+ // If this connection requested whitelist management, see if we should
+ // now clear that state.
+ if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
+ s.updateWhitelistManager();
+ if (!s.whitelistManager && s.app != null) {
+ updateWhitelistManagerLocked(s.app);
+ }
+ }
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
@@ -2278,6 +2313,9 @@ public final class ActiveServices {
if (finishing) {
if (r.app != null && !r.app.persistent) {
r.app.services.remove(r);
+ if (r.whitelistManager) {
+ updateWhitelistManagerLocked(r.app);
+ }
}
r.app = null;
}
@@ -2373,6 +2411,9 @@ public final class ActiveServices {
service.app.removed = killProcess;
if (!service.app.persistent) {
service.app.services.remove(service);
+ if (service.whitelistManager) {
+ updateWhitelistManagerLocked(service.app);
+ }
}
}
service.app = null;
@@ -2491,6 +2532,8 @@ public final class ActiveServices {
updateServiceConnectionActivitiesLocked(app);
app.connections.clear();
+ app.whitelistManager = false;
+
// Clear app state from services.
for (int i = app.services.size() - 1; i >= 0; i--) {
ServiceRecord sr = app.services.valueAt(i);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bfc98772b527..5893f9018631 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -63,6 +63,7 @@ import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
@@ -102,7 +103,6 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProfilerInfo;
import android.app.admin.DevicePolicyManager;
-import android.app.admin.DevicePolicyManagerInternal;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.backup.IBackupManager;
@@ -205,6 +205,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.DebugUtils;
+import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.Pair;
@@ -273,6 +274,10 @@ import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
+import static android.os.Process.PROC_CHAR;
+import static android.os.Process.PROC_OUT_LONG;
+import static android.os.Process.PROC_PARENS;
+import static android.os.Process.PROC_SPACE_TERM;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
@@ -500,7 +505,10 @@ public final class ActivityManagerService extends ActivityManagerNative
static final String[] EMPTY_STRING_ARRAY = new String[0];
// How many bytes to write into the dropbox log before truncating
- static final int DROPBOX_MAX_SIZE = 256 * 1024;
+ static final int DROPBOX_MAX_SIZE = 192 * 1024;
+ // Assumes logcat entries average around 100 bytes; that's not perfect stack traces count
+ // as one line, but close enough for now.
+ static final int RESERVED_BYTES_PER_LOGCAT_LINE = 100;
// Access modes for handleIncomingUser.
static final int ALLOW_NON_FULL = 0;
@@ -1513,6 +1521,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static final int NOTIFY_FORCED_RESIZABLE_MSG = 67;
static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 68;
static final int VR_MODE_APPLY_IF_NEEDED_MSG = 69;
+ static final int SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG = 70;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1523,6 +1532,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static KillHandler sKillHandler = null;
CompatModeDialog mCompatModeDialog;
+ UnsupportedDisplaySizeDialog mUnsupportedDisplaySizeDialog;
long mLastMemUsageReportTime = 0;
/**
@@ -1693,6 +1703,22 @@ public final class ActivityManagerService extends ActivityManagerNative
}
break;
}
+ case SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG: {
+ synchronized (ActivityManagerService.this) {
+ final ActivityRecord ar = (ActivityRecord) msg.obj;
+ if (mUnsupportedDisplaySizeDialog != null) {
+ mUnsupportedDisplaySizeDialog.dismiss();
+ mUnsupportedDisplaySizeDialog = null;
+ }
+ if (ar != null && mCompatModePackages.getPackageNotifyUnsupportedZoomLocked(
+ ar.packageName)) {
+ mUnsupportedDisplaySizeDialog = new UnsupportedDisplaySizeDialog(
+ ActivityManagerService.this, mContext, ar.info.applicationInfo);
+ mUnsupportedDisplaySizeDialog.show();
+ }
+ }
+ break;
+ }
case START_USER_SWITCH_UI_MSG: {
mUserController.showUserSwitchDialog((Pair<UserInfo, UserInfo>) msg.obj);
break;
@@ -1827,13 +1853,13 @@ public final class ActivityManagerService extends ActivityManagerNative
} break;
case KILL_APPLICATION_MSG: {
synchronized (ActivityManagerService.this) {
- int appid = msg.arg1;
- boolean restart = (msg.arg2 == 1);
+ final int appId = msg.arg1;
+ final int userId = msg.arg2;
Bundle bundle = (Bundle)msg.obj;
String pkg = bundle.getString("pkg");
String reason = bundle.getString("reason");
- forceStopPackageLocked(pkg, appid, restart, false, true, false,
- false, UserHandle.USER_ALL, reason);
+ forceStopPackageLocked(pkg, appId, false, false, true, false,
+ false, userId, reason);
}
} break;
case FINALIZE_PENDING_INTENT_MSG: {
@@ -3099,6 +3125,16 @@ public final class ActivityManagerService extends ActivityManagerNative
mUiHandler.sendMessage(msg);
}
+ final void showUnsupportedZoomDialogIfNeededLocked(ActivityRecord r) {
+ if (mConfiguration.densityDpi != DisplayMetrics.DENSITY_DEVICE_STABLE
+ && r.appInfo.requiresSmallestWidthDp > mConfiguration.smallestScreenWidthDp) {
+ final Message msg = Message.obtain();
+ msg.what = SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG;
+ msg.obj = r;
+ mUiHandler.sendMessage(msg);
+ }
+ }
+
private int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
String what, Object obj, ProcessRecord srcApp) {
app.lastActivityTime = now;
@@ -3492,13 +3528,11 @@ public final class ActivityManagerService extends ActivityManagerNative
// app launch boost for big.little configurations
// use cpusets to migrate freshly launched tasks to big cores
- synchronized(ActivityManagerService.this) {
- nativeMigrateToBoost();
- mIsBoosted = true;
- mBoostStartTime = SystemClock.uptimeMillis();
- Message msg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG);
- mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);
- }
+ nativeMigrateToBoost();
+ mIsBoosted = true;
+ mBoostStartTime = SystemClock.uptimeMillis();
+ Message msg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG);
+ mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);
// We don't have to do anything more if:
// (1) There is an existing application record; and
@@ -3511,7 +3545,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+ " thread=" + (app != null ? app.thread : null)
+ " pid=" + (app != null ? app.pid : -1));
if (app != null && app.pid > 0) {
- if (!knownToBeDead || app.thread == null) {
+ if ((!knownToBeDead && !app.killed) || app.thread == null) {
// We already have the app running, or are waiting for it to
// come up (we have a pid but not yet its thread), so keep it.
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
@@ -5389,10 +5423,10 @@ public final class ActivityManagerService extends ActivityManagerNative
IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
synchronized(this) {
- if (getPackageManagerInternalLocked().canPackageBeWiped(
+ if (getPackageManagerInternalLocked().isPackageDataProtected(
userId, packageName)) {
throw new SecurityException(
- "Cannot clear data for a device owner or a profile owner");
+ "Cannot clear data for a protected package: " + packageName);
}
try {
@@ -5687,12 +5721,12 @@ public final class ActivityManagerService extends ActivityManagerNative
* The pkg name and app id have to be specified.
*/
@Override
- public void killApplicationWithAppId(String pkg, int appid, String reason) {
+ public void killApplication(String pkg, int appId, int userId, String reason) {
if (pkg == null) {
return;
}
// Make sure the uid is valid.
- if (appid < 0) {
+ if (appId < 0) {
Slog.w(TAG, "Invalid appid specified for pkg : " + pkg);
return;
}
@@ -5701,8 +5735,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (UserHandle.getAppId(callerUid) == Process.SYSTEM_UID) {
// Post an aysnc message to kill the application
Message msg = mHandler.obtainMessage(KILL_APPLICATION_MSG);
- msg.arg1 = appid;
- msg.arg2 = 0;
+ msg.arg1 = appId;
+ msg.arg2 = userId;
Bundle bundle = new Bundle();
bundle.putString("pkg", pkg);
bundle.putString("reason", reason);
@@ -6386,7 +6420,7 @@ public final class ActivityManagerService extends ActivityManagerNative
EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
app.makeActive(thread, mProcessStats);
- app.curAdj = app.setAdj = ProcessList.INVALID_ADJ;
+ app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
@@ -8307,7 +8341,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final IPackageManager pm = AppGlobals.getPackageManager();
final String authority = grantUri.uri.getAuthority();
final ProviderInfo pi = getProviderInfoLocked(authority, grantUri.sourceUserId,
- MATCH_DEBUG_TRIAGED_MISSING);
+ MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
if (pi == null) {
Slog.w(TAG, "No content provider found for permission revoke: "
+ grantUri.toSafeString());
@@ -8405,7 +8439,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final String authority = uri.getAuthority();
final ProviderInfo pi = getProviderInfoLocked(authority, userId,
- MATCH_DEBUG_TRIAGED_MISSING);
+ MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE);
if (pi == null) {
Slog.w(TAG, "No content provider found for permission revoke: "
+ uri.toSafeString());
@@ -8802,10 +8836,11 @@ public final class ActivityManagerService extends ActivityManagerNative
Preconditions.checkNotNull(packageName, "packageName");
final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(callingUid);
final IPackageManager pm = AppGlobals.getPackageManager();
try {
- final int packageUid = pm.getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING,
- UserHandle.getUserId(callingUid));
+ final int packageUid = pm.getPackageUid(packageName,
+ MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, callingUserId);
if (packageUid != callingUid) {
throw new SecurityException(
"Package " + packageName + " does not belong to calling UID " + callingUid);
@@ -8822,30 +8857,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (perms == null) {
Slog.w(TAG, "No permission grants found for " + packageName);
} else {
- final int userId = UserHandle.getUserId(callingUid);
- Set<String> existingAuthorities = null;
-
for (UriPermission perm : perms.values()) {
if (packageName.equals(perm.targetPkg) && perm.persistedModeFlags != 0) {
- // Is this provider available in the current boot state? If the user
- // is not running and unlocked we check if the provider package exists.
- if (!mUserController.isUserRunningLocked(userId,
- ActivityManager.FLAG_AND_UNLOCKED)) {
- String authority = perm.uri.uri.getAuthority();
- if (existingAuthorities == null
- || !existingAuthorities.contains(authority)) {
- ProviderInfo providerInfo = getProviderInfoLocked(authority,
- userId, MATCH_DEBUG_TRIAGED_MISSING);
- if (providerInfo != null) {
- if (existingAuthorities == null) {
- existingAuthorities = new ArraySet<>();
- }
- existingAuthorities.add(authority);
- } else {
- continue;
- }
- }
- }
result.add(perm.buildPersistedPublicApiObject());
}
}
@@ -9234,9 +9247,6 @@ public final class ActivityManagerService extends ActivityManagerNative
// sense, so turn off auto-remove.
intent.addFlags(Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
}
- } else if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
- // Must be a new task.
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
if (!comp.equals(mLastAddedTaskComponent) || callingUid != mLastAddedTaskUid) {
mLastAddedTaskActivity = null;
@@ -10509,6 +10519,30 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ private static final int[] PROCESS_STATE_STATS_FORMAT = new int[] {
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM|PROC_PARENS,
+ PROC_SPACE_TERM|PROC_CHAR|PROC_OUT_LONG, // 3: process state
+ };
+
+ private final long[] mProcessStateStatsLongs = new long[1];
+
+ boolean isProcessAliveLocked(ProcessRecord proc) {
+ if (proc.procStatFile == null) {
+ proc.procStatFile = "/proc/" + proc.pid + "/stat";
+ }
+ mProcessStateStatsLongs[0] = 0;
+ if (!Process.readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
+ mProcessStateStatsLongs, null)) {
+ if (DEBUG_OOM_ADJ) Slog.d(TAG, "UNABLE TO RETRIEVE STATE FOR " + proc.procStatFile);
+ return false;
+ }
+ final long state = mProcessStateStatsLongs[0];
+ if (DEBUG_OOM_ADJ) Slog.d(TAG, "RETRIEVED STATE FOR " + proc.procStatFile + ": "
+ + (char)state);
+ return state != 'Z' && state != 'X' && state != 'x' && state != 'K';
+ }
+
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, boolean stable, int userId) {
ContentProviderRecord cpr;
@@ -10553,7 +10587,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- boolean providerRunning = cpr != null;
+ boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
if (providerRunning) {
cpi = cpr.info;
String msg;
@@ -10595,35 +10629,44 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- if (cpr.proc != null) {
- checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
- boolean success = updateOomAdjLocked(cpr.proc);
- maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
- checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
- if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
- // NOTE: there is still a race here where a signal could be
- // pending on the process even though we managed to update its
- // adj level. Not sure what to do about this, but at least
- // the race is now smaller.
- if (!success) {
- // Uh oh... it looks like the provider's process
- // has been killed on us. We need to wait for a new
- // process to be started, and make sure its death
- // doesn't kill our process.
- Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
- + " is crashing; detaching " + r);
- boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
- checkTime(startTime, "getContentProviderImpl: before appDied");
- appDiedLocked(cpr.proc);
- checkTime(startTime, "getContentProviderImpl: after appDied");
- if (!lastRef) {
- // This wasn't the last ref our process had on
- // the provider... we have now been killed, bail.
- return null;
- }
- providerRunning = false;
- conn = null;
+ checkTime(startTime, "getContentProviderImpl: before updateOomAdj");
+ final int verifiedAdj = cpr.proc.verifiedAdj;
+ boolean success = updateOomAdjLocked(cpr.proc);
+ // XXX things have changed so updateOomAdjLocked doesn't actually tell us
+ // if the process has been successfully adjusted. So to reduce races with
+ // it, we will check whether the process still exists. Note that this doesn't
+ // completely get rid of races with LMK killing the process, but should make
+ // them much smaller.
+ if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) {
+ success = false;
+ }
+ maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name);
+ checkTime(startTime, "getContentProviderImpl: after updateOomAdj");
+ if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success);
+ // NOTE: there is still a race here where a signal could be
+ // pending on the process even though we managed to update its
+ // adj level. Not sure what to do about this, but at least
+ // the race is now smaller.
+ if (!success) {
+ // Uh oh... it looks like the provider's process
+ // has been killed on us. We need to wait for a new
+ // process to be started, and make sure its death
+ // doesn't kill our process.
+ Slog.i(TAG, "Existing provider " + cpr.name.flattenToShortString()
+ + " is crashing; detaching " + r);
+ boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
+ checkTime(startTime, "getContentProviderImpl: before appDied");
+ appDiedLocked(cpr.proc);
+ checkTime(startTime, "getContentProviderImpl: after appDied");
+ if (!lastRef) {
+ // This wasn't the last ref our process had on
+ // the provider... we have now been killed, bail.
+ return null;
}
+ providerRunning = false;
+ conn = null;
+ } else {
+ cpr.proc.verifiedAdj = cpr.proc.setAdj;
}
Binder.restoreCallingIdentity(origId);
@@ -10767,7 +10810,7 @@ public final class ActivityManagerService extends ActivityManagerNative
checkTime(startTime, "getContentProviderImpl: looking for process record");
ProcessRecord proc = getProcessRecordLocked(
cpi.processName, cpr.appInfo.uid, false);
- if (proc != null && proc.thread != null) {
+ if (proc != null && proc.thread != null && !proc.killed) {
if (DEBUG_PROVIDER) Slog.d(TAG_PROVIDER,
"Installing in existing process " + proc);
if (!proc.pubProviders.containsKey(cpi.name)) {
@@ -11476,11 +11519,15 @@ public final class ActivityManagerService extends ActivityManagerNative
// Actually is sleeping or shutting down or whatever else in the future
// is an inactive state.
- public boolean isSleepingOrShuttingDown() {
- return isSleeping() || mShuttingDown;
+ boolean isSleepingOrShuttingDownLocked() {
+ return isSleepingLocked() || mShuttingDown;
}
- public boolean isSleeping() {
+ boolean isShuttingDownLocked() {
+ return mShuttingDown;
+ }
+
+ boolean isSleepingLocked() {
return mSleeping;
}
@@ -12850,7 +12897,7 @@ public final class ActivityManagerService extends ActivityManagerNative
proc.notCachedSinceIdle = true;
proc.initialIdlePss = 0;
proc.nextPssTime = ProcessList.computeNextPssTime(proc.setProcState, true,
- mTestPssMode, isSleeping(), now);
+ mTestPssMode, isSleepingLocked(), now);
}
}
@@ -13498,13 +13545,13 @@ public final class ActivityManagerService extends ActivityManagerNative
* @param parent activity related to the error, null if unknown
* @param subject line related to the error, null if absent
* @param report in long form describing the error, null if absent
- * @param logFile to include in the report, null if none
+ * @param dataFile text file to include in the report, null if none
* @param crashInfo giving an application stack trace, null if absent
*/
public void addErrorToDropBox(String eventType,
ProcessRecord process, String processName, ActivityRecord activity,
ActivityRecord parent, String subject,
- final String report, final File logFile,
+ final String report, final File dataFile,
final ApplicationErrorReport.CrashInfo crashInfo) {
// NOTE -- this must never acquire the ActivityManagerService lock,
// otherwise the watchdog may be prevented from resetting the system.
@@ -13559,20 +13606,24 @@ public final class ActivityManagerService extends ActivityManagerNative
if (report != null) {
sb.append(report);
}
- if (logFile != null) {
+
+ String setting = Settings.Global.ERROR_LOGCAT_PREFIX + dropboxTag;
+ int lines = Settings.Global.getInt(mContext.getContentResolver(), setting, 0);
+ int maxDataFileSize = DROPBOX_MAX_SIZE - sb.length()
+ - lines * RESERVED_BYTES_PER_LOGCAT_LINE;
+
+ if (dataFile != null && maxDataFileSize > 0) {
try {
- sb.append(FileUtils.readTextFile(logFile, DROPBOX_MAX_SIZE,
+ sb.append(FileUtils.readTextFile(dataFile, maxDataFileSize,
"\n\n[[TRUNCATED]]"));
} catch (IOException e) {
- Slog.e(TAG, "Error reading " + logFile, e);
+ Slog.e(TAG, "Error reading " + dataFile, e);
}
}
if (crashInfo != null && crashInfo.stackTrace != null) {
sb.append(crashInfo.stackTrace);
}
- String setting = Settings.Global.ERROR_LOGCAT_PREFIX + dropboxTag;
- int lines = Settings.Global.getInt(mContext.getContentResolver(), setting, 0);
if (lines > 0) {
sb.append("\n");
@@ -16568,7 +16619,8 @@ public final class ActivityManagerService extends ActivityManagerNative
&& capp.pid != MY_PID) {
capp.kill("depends on provider "
+ cpr.name.flattenToShortString()
- + " in dying proc " + (proc != null ? proc.processName : "??"), true);
+ + " in dying proc " + (proc != null ? proc.processName : "??")
+ + " (adj " + (proc != null ? proc.setAdj : "??") + ")", true);
}
} else if (capp.thread != null && conn.provider.provider != null) {
try {
@@ -17763,6 +17815,14 @@ public final class ActivityManagerService extends ActivityManagerNative
removeUriPermissionsForPackageLocked(ssp, userId, true);
removeTasksByPackageNameLocked(ssp, userId);
+
+ // Hide the "unsupported display" dialog if necessary.
+ if (mUnsupportedDisplaySizeDialog != null && ssp.equals(
+ mUnsupportedDisplaySizeDialog.getPackageName())) {
+ mUnsupportedDisplaySizeDialog.dismiss();
+ mUnsupportedDisplaySizeDialog = null;
+ }
+ mCompatModePackages.handlePackageUninstalledLocked(ssp);
mBatteryStatsService.notePackageUninstalled(ssp);
}
} else {
@@ -17834,6 +17894,21 @@ public final class ActivityManagerService extends ActivityManagerNative
}
break;
}
+ case Intent.ACTION_PACKAGE_DATA_CLEARED:
+ {
+ Uri data = intent.getData();
+ String ssp;
+ if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
+ // Hide the "unsupported display" dialog if necessary.
+ if (mUnsupportedDisplaySizeDialog != null && ssp.equals(
+ mUnsupportedDisplaySizeDialog.getPackageName())) {
+ mUnsupportedDisplaySizeDialog.dismiss();
+ mUnsupportedDisplaySizeDialog = null;
+ }
+ mCompatModePackages.handlePackageDataClearedLocked(ssp);
+ }
+ break;
+ }
case Intent.ACTION_TIMEZONE_CHANGED:
// If this is the time zone changed action, queue up a message that will reset
// the timezone of all currently running processes. This message will get
@@ -17865,6 +17940,19 @@ public final class ActivityManagerService extends ActivityManagerNative
// Apps should use JobScehduler to monitor for media provider changes.
Slog.w(TAG, action + " no longer allowed; dropping from "
+ UserHandle.formatUid(callingUid));
+ if (resultTo != null) {
+ final BroadcastQueue queue = broadcastQueueForIntent(intent);
+ try {
+ queue.performReceiveLocked(callerApp, resultTo, intent,
+ Activity.RESULT_CANCELED, null, null,
+ false, false, userId);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failure ["
+ + queue.mQueueName + "] sending broadcast result of "
+ + intent, e);
+
+ }
+ }
// Lie; we don't want to crash the app.
return ActivityManager.BROADCAST_SUCCESS;
}
@@ -18656,6 +18744,9 @@ public final class ActivityManagerService extends ActivityManagerNative
final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
if (isDensityChange) {
+ // Reset the unsupported display size dialog.
+ mUiHandler.sendEmptyMessage(SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG);
+
killAllBackgroundProcessesExcept(Build.VERSION_CODES.N,
ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
}
@@ -18725,7 +18816,7 @@ public final class ActivityManagerService extends ActivityManagerNative
starting = mainStack.topRunningActivityLocked();
}
- if (starting != null && starting.state != ActivityState.STOPPED) {
+ if (starting != null) {
kept = mainStack.ensureActivityConfigurationLocked(starting, changes, false);
// And we need to make sure at this point that all other activities
// are made visible with the correct configuration.
@@ -19243,8 +19334,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- app.whitelistManager = false;
-
for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
@@ -19263,9 +19352,6 @@ public final class ActivityManagerService extends ActivityManagerNative
// Binding to ourself is not interesting.
continue;
}
- if ((cr.flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
- app.whitelistManager = true;
- }
if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
ProcessRecord client = cr.binding.client;
@@ -19758,7 +19844,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (memLowered || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) {
app.pssProcState = app.setProcState;
app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
- mTestPssMode, isSleeping(), now);
+ mTestPssMode, isSleepingLocked(), now);
mPendingPssProcesses.add(app);
}
}
@@ -19806,7 +19892,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
return !processingBroadcasts
- && (isSleeping() || mStackSupervisor.allResumedActivitiesIdle());
+ && (isSleepingLocked() || mStackSupervisor.allResumedActivitiesIdle());
}
/**
@@ -20016,6 +20102,7 @@ public final class ActivityManagerService extends ActivityManagerNative
"Set " + app.pid + " " + app.processName + " adj " + app.curAdj + ": "
+ app.adjType);
app.setAdj = app.curAdj;
+ app.verifiedAdj = ProcessList.INVALID_ADJ;
}
if (app.setSchedGroup != app.curSchedGroup) {
@@ -20097,7 +20184,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
app.lastStateTime = now;
app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
- mTestPssMode, isSleeping(), now);
+ mTestPssMode, isSleepingLocked(), now);
if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from "
+ ProcessList.makeProcStateString(app.setProcState) + " to "
+ ProcessList.makeProcStateString(app.curProcState) + " next pss in "
@@ -20108,7 +20195,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mTestPssMode)))) {
requestPssLocked(app, app.setProcState);
app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
- mTestPssMode, isSleeping(), now);
+ mTestPssMode, isSleepingLocked(), now);
} else if (false && DEBUG_PSS) Slog.d(TAG_PSS,
"Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
}
@@ -20634,7 +20721,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
mLastMemoryLevel = memFactor;
mLastNumProcesses = mLruProcesses.size();
- boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);
+ boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleepingLocked(), now);
final int trackerMemFactor = mProcessStats.getMemFactorLocked();
if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
if (mLowRamStartTime == 0) {
@@ -21291,8 +21378,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public void registerUserSwitchObserver(IUserSwitchObserver observer) {
- mUserController.registerUserSwitchObserver(observer);
+ public void registerUserSwitchObserver(IUserSwitchObserver observer, String name) {
+ mUserController.registerUserSwitchObserver(observer, name);
}
@Override
@@ -21566,6 +21653,16 @@ public final class ActivityManagerService extends ActivityManagerNative
}
((PendingIntentRecord) target).setWhitelistDuration(duration);
}
+
+ @Override
+ public void updatePersistentConfigurationForUser(@NonNull Configuration values,
+ int userId) {
+ Preconditions.checkNotNull(values, "Configuration must not be null");
+ Preconditions.checkArgumentNonnegative(userId, "userId " + userId + " not supported");
+ synchronized (ActivityManagerService.this) {
+ updateConfigurationLocked(values, null, false, true, userId);
+ }
+ }
}
private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 3ccac9e2f1e4..50b6c0c7502f 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -444,10 +444,17 @@ final class ActivityRecord {
return;
}
try {
+ // Make sure fontScale is always equal to global. For fullscreen apps, config is
+ // the shared EMPTY config, which has default fontScale of 1.0. We don't want it
+ // to be applied as an override config.
+ Configuration overrideConfig = new Configuration(config);
+ overrideConfig.fontScale = service.mConfiguration.fontScale;
+
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + " " +
- "reportToActivity=" + reportToActivity + " and config: " + config);
+ "reportToActivity=" + reportToActivity + " and config: " + overrideConfig);
+
app.thread.scheduleActivityConfigurationChanged(
- appToken, new Configuration(config), reportToActivity);
+ appToken, overrideConfig, reportToActivity);
} catch (RemoteException e) {
// If process died, whatever.
}
@@ -931,7 +938,7 @@ final class ActivityRecord {
final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
boolean unsent = true;
if ((state == ActivityState.RESUMED
- || (service.isSleeping() && task.stack != null
+ || (service.isSleepingLocked() && task.stack != null
&& task.stack.topRunningActivityLocked() == this))
&& app != null && app.thread != null) {
try {
@@ -1150,13 +1157,6 @@ final class ActivityRecord {
public void reportFullyDrawnLocked() {
final long curTime = SystemClock.uptimeMillis();
- // Normally launch time counts from the point when the activity is resumed, to when the
- // first window is drawn. However the activity could become visible before it is resumed,
- // due to some other activity in the same task being launched. In this case we still need
- // to report launch time to unblock ActivityStarter.startActivityMayWait().
- if (displayStartTime == 0 && task != null && task.isLaunching) {
- displayStartTime = curTime;
- }
if (displayStartTime != 0) {
reportLaunchTimeLocked(curTime);
}
@@ -1222,22 +1222,13 @@ final class ActivityRecord {
//service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
}
displayStartTime = 0;
- task.isLaunching = false;
stack.mLaunchStartTime = 0;
}
void windowsDrawnLocked() {
mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn();
- final long curTime = SystemClock.uptimeMillis();
- // Normally launch time counts from the point when the activity is resumed, to when the
- // first window is drawn. However the activity could become visible before it is resumed,
- // due to some other activity in the same task being launched. In this case we still need
- // to report launch time to unblock ActivityStarter.startActivityMayWait().
- if (displayStartTime == 0 && task != null && task.isLaunching) {
- displayStartTime = curTime;
- }
if (displayStartTime != 0) {
- reportLaunchTimeLocked(curTime);
+ reportLaunchTimeLocked(SystemClock.uptimeMillis());
}
mStackSupervisor.sendWaitingVisibleReportLocked(this);
startTime = 0;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 0513b1ad8a8a..6d229466ebf9 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -825,7 +825,8 @@ final class ActivityStack {
* is the same as the given activity. Returns null if no such activity
* is found.
*/
- ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
+ ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
+ boolean compareIntentFilters) {
ComponentName cls = intent.getComponent();
if (info.targetActivity != null) {
cls = new ComponentName(info.packageName, info.targetActivity);
@@ -843,8 +844,16 @@ final class ActivityStack {
if (notCurrentUserTask && (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) == 0) {
continue;
}
- if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId == userId) {
- return r;
+ if (!r.finishing && r.userId == userId) {
+ if (compareIntentFilters) {
+ if (r.intent.filterEquals(intent)) {
+ return r;
+ }
+ } else {
+ if (r.intent.getComponent().equals(cls)) {
+ return r;
+ }
+ }
}
}
}
@@ -924,9 +933,6 @@ final class ActivityStack {
void setLaunchTime(ActivityRecord r) {
if (r.displayStartTime == 0) {
r.fullyDrawnStartTime = r.displayStartTime = SystemClock.uptimeMillis();
- if (r.task != null) {
- r.task.isLaunching = true;
- }
if (mLaunchStartTime == 0) {
startLaunchTraces(r.packageName);
mLaunchStartTime = mFullyDrawnStartTime = r.displayStartTime;
@@ -941,9 +947,6 @@ final class ActivityStack {
// Make sure that there is no activity waiting for this to launch.
if (mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
r.displayStartTime = r.fullyDrawnStartTime = 0;
- if (r.task != null) {
- r.task.isLaunching = false;
- }
} else {
mStackSupervisor.removeTimeoutsForActivityLocked(r);
mStackSupervisor.scheduleIdleTimeoutLocked(r);
@@ -1075,7 +1078,7 @@ final class ActivityStack {
if (mPausingActivity != null) {
Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+ " state=" + mPausingActivity.state);
- if (!mService.isSleeping()) {
+ if (!mService.isSleepingLocked()) {
// Avoid recursion among check for sleep and complete pause during sleeping.
// Because activity will be paused immediately after resume, just let pause
// be completed by the order of activity paused from clients.
@@ -1139,7 +1142,7 @@ final class ActivityStack {
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
- if (!uiSleeping && !mService.isSleepingOrShuttingDown()) {
+ if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
mStackSupervisor.acquireLaunchWakelock();
}
@@ -1292,7 +1295,7 @@ final class ActivityStack {
// We don't need to schedule another stop, we only need to let it happen.
prev.state = ActivityState.STOPPING;
} else if ((!prev.visible && !hasVisibleBehindActivity())
- || mService.isSleepingOrShuttingDown()) {
+ || mService.isSleepingOrShuttingDownLocked()) {
// If we were visible then resumeTopActivities will release resources before
// stopping.
addToStopping(prev, true /* immediate */);
@@ -1310,7 +1313,7 @@ final class ActivityStack {
if (resumeNext) {
final ActivityStack topStack = mStackSupervisor.getFocusedStack();
- if (!mService.isSleepingOrShuttingDown()) {
+ if (!mService.isSleepingOrShuttingDownLocked()) {
mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
} else {
mStackSupervisor.checkReadyForSleepLocked();
@@ -1398,6 +1401,7 @@ final class ActivityStack {
if (next.nowVisible) {
// We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now.
+ mStackSupervisor.reportActivityVisibleLocked(next);
mStackSupervisor.notifyActivityDrawnForKeyguard();
}
@@ -1702,7 +1706,8 @@ final class ActivityStack {
final boolean stackInvisible = stackVisibility != STACK_VISIBLE;
final boolean stackVisibleBehind = stackVisibility == STACK_VISIBLE_ACTIVITY_BEHIND;
boolean behindFullscreenActivity = stackInvisible;
- boolean resumeNextActivity = isFocusable() && (isInStackLocked(starting) == null);
+ boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
+ && (isInStackLocked(starting) == null);
boolean behindTranslucentActivity = false;
final ActivityRecord visibleBehind = getVisibleBehindActivity();
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -1820,8 +1825,7 @@ final class ActivityStack {
boolean stackVisibleBehind, ActivityRecord visibleBehind,
boolean behindFullscreenActivity) {
- if (!okToShowLocked(r)
- || (mService.isSleepingOrShuttingDown() && r.voiceSession == null)) {
+ if (!okToShowLocked(r)) {
return false;
}
@@ -2196,7 +2200,7 @@ final class ActivityStack {
// If we are sleeping, and there is no resumed activity, and the top
// activity is paused, well that is the state we want.
- if (mService.isSleepingOrShuttingDown()
+ if (mService.isSleepingOrShuttingDownLocked()
&& mLastPausedActivity == next
&& mStackSupervisor.allPausedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
@@ -2278,7 +2282,7 @@ final class ActivityStack {
// If the most recent activity was noHistory but was only stopped rather
// than stopped+finished because the device went to sleep, we need to make
// sure to finish it as we're making a new activity topmost.
- if (mService.isSleeping() && mLastNoHistoryActivity != null &&
+ if (mService.isSleepingLocked() && mLastNoHistoryActivity != null &&
!mLastNoHistoryActivity.finishing) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"no-history finish of " + mLastNoHistoryActivity + " on new resume");
@@ -2481,6 +2485,7 @@ final class ActivityStack {
System.identityHashCode(next), next.task.taskId, next.shortComponentName);
next.sleeping = false;
+ mService.showUnsupportedZoomDialogIfNeededLocked(next);
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(mService.mTopProcessState);
@@ -3212,7 +3217,7 @@ final class ActivityStack {
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
if (!r.finishing) {
- if (!mService.isSleeping()) {
+ if (!mService.isSleepingLocked()) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r);
if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
"stop-no-history", false)) {
@@ -3244,7 +3249,7 @@ final class ActivityStack {
EventLogTags.writeAmStopActivity(
r.userId, System.identityHashCode(r), r.shortComponentName);
r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
- if (mService.isSleepingOrShuttingDown()) {
+ if (mService.isSleepingOrShuttingDownLocked()) {
r.setSleeping(true);
}
Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
@@ -3755,6 +3760,10 @@ final class ActivityStack {
if (getVisibleBehindActivity() == r) {
mStackSupervisor.requestVisibleBehindLocked(r, false);
}
+
+ // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
+ // manager so it can update its bookkeeping.
+ mWindowManager.notifyAppRelaunchesCleared(r.appToken);
}
private void removeTimeoutsForActivityLocked(ActivityRecord r) {
@@ -4448,7 +4457,7 @@ final class ActivityStack {
}
}
if (updatedConfig) {
- // Ensure the resumed state of the focus activity if we updated the confiugaration of
+ // Ensure the resumed state of the focus activity if we updated the configuration of
// any activity.
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
@@ -4468,6 +4477,15 @@ final class ActivityStack {
return true;
}
+ // TODO: We could probably make the condition below just check that the activity state is
+ // stopped, but also checking the sleep state for now to reduce change impact late in
+ // development cycle.
+ if (mService.isSleepingOrShuttingDownLocked() && r.state == ActivityState.STOPPED) {
+ if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
+ "Skipping config check (stopped while sleeping): " + r);
+ return true;
+ }
+
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Ensuring correct configuration: " + r);
@@ -4728,6 +4746,8 @@ final class ActivityStack {
r.results = null;
r.newIntents = null;
}
+ mService.showUnsupportedZoomDialogIfNeededLocked(r);
+ mService.showAskCompatModeDialogLocked(r);
} else {
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
r.state = ActivityState.PAUSED;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f78fa8d3006e..82668e45812f 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -111,6 +111,7 @@ import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.ActivityManager.RESIZE_MODE_FORCED;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
+import static android.app.ActivityManager.START_TASK_TO_FRONT;
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;
@@ -1004,6 +1005,24 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
}
+ void reportTaskToFrontNoLaunch(ActivityRecord r) {
+ boolean changed = false;
+ for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
+ WaitResult w = mWaitingActivityLaunched.remove(i);
+ if (w.who == null) {
+ changed = true;
+ // Set result to START_TASK_TO_FRONT so that startActivityMayWait() knows that
+ // the starting activity ends up moving another activity to front, and it should
+ // wait for this new activity to become visible instead.
+ // Do not modify other fields.
+ w.result = START_TASK_TO_FRONT;
+ }
+ }
+ if (changed) {
+ mService.notifyAll();
+ }
+ }
+
void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
long thisTime, long totalTime) {
boolean changed = false;
@@ -1017,6 +1036,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
w.thisTime = thisTime;
w.totalTime = totalTime;
+ // Do not modify w.result.
}
}
if (changed) {
@@ -1219,6 +1239,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
r.sleeping = false;
r.forceNewConfig = false;
+ mService.showUnsupportedZoomDialogIfNeededLocked(r);
mService.showAskCompatModeDialogLocked(r);
r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
ProfilerInfo profilerInfo = null;
@@ -2620,11 +2641,13 @@ public final class ActivityStackSupervisor implements DisplayListener {
return mTmpFindTaskResult.r;
}
- ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
+ ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
+ boolean compareIntentFilters) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord ar = stacks.get(stackNdx).findActivityLocked(intent, info);
+ final ActivityRecord ar = stacks.get(stackNdx)
+ .findActivityLocked(intent, info, compareIntentFilters);
if (ar != null) {
return ar;
}
@@ -2709,7 +2732,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
void checkReadyForSleepLocked() {
- if (!mService.isSleepingOrShuttingDown()) {
+ if (!mService.isSleepingOrShuttingDownLocked()) {
// Do not care.
return;
}
@@ -3027,8 +3050,9 @@ public final class ActivityStackSupervisor implements DisplayListener {
/** Checks whether the activity should be shown for current user. */
boolean okToShowLocked(ActivityRecord r) {
- return r != null && (isCurrentProfileLocked(r.userId)
- || (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
+ return r != null && ((r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
+ || (isCurrentProfileLocked(r.userId)
+ && !mService.mUserController.isUserStoppingOrShuttingDownLocked(r.userId)));
}
final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
@@ -3052,7 +3076,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
mWindowManager.setAppVisibility(s.appToken, false);
}
}
- if ((!waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
+ if ((!waitingVisible || mService.isSleepingOrShuttingDownLocked()) && remove) {
if (DEBUG_STATES) Slog.v(TAG, "Ready to stop: " + s);
if (stops == null) {
stops = new ArrayList<>();
@@ -3776,7 +3800,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
} break;
case SLEEP_TIMEOUT_MSG: {
synchronized (mService) {
- if (mService.isSleepingOrShuttingDown()) {
+ if (mService.isSleepingOrShuttingDownLocked()) {
Slog.w(TAG, "Sleep timeout! Sleeping now.");
mSleepTimeout = true;
checkReadyForSleepLocked();
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index a5a7db9adef0..77b450fe1fd4 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -555,6 +555,13 @@ class ActivityStarter {
return;
}
+ // We're waiting for an activity launch to finish, but that activity simply
+ // brought another activity to front. Let startActivityMayWait() know about
+ // this, so it waits for the new activity to become visible instead.
+ if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
+ mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
+ }
+
int startedActivityStackId = INVALID_STACK_ID;
if (r.task != null && r.task.stack != null) {
startedActivityStackId = r.task.stack.mStackId;
@@ -842,8 +849,13 @@ class ActivityStarter {
mService.wait();
} catch (InterruptedException e) {
}
- } while (!outResult.timeout && outResult.who == null);
- } else if (res == START_TASK_TO_FRONT) {
+ } while (outResult.result != START_TASK_TO_FRONT
+ && !outResult.timeout && outResult.who == null);
+ if (outResult.result == START_TASK_TO_FRONT) {
+ res = START_TASK_TO_FRONT;
+ }
+ }
+ if (res == START_TASK_TO_FRONT) {
ActivityRecord r = stack.topRunningActivityLocked();
if (r.nowVisible && r.state == RESUMED) {
outResult.timeout = false;
@@ -1438,11 +1450,12 @@ class ActivityStarter {
if (mLaunchSingleInstance) {
// There can be one and only one instance of single instance activity in the
// history, and it is always in its own unique task, so we do a special search.
- intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info);
+ intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
} else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
// For the launch adjacent case we only want to put the activity in an existing
// task if the activity already exists in the history.
- intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info);
+ intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
+ !mLaunchSingleTask);
} else {
// Otherwise find the best task to put the activity in.
intentActivity = mSupervisor.findTaskLocked(mStartActivity);
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 88645c1e8afd..a279290a34be 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -456,7 +456,7 @@ public final class BroadcastQueue {
}
}
- private void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
+ void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
// Send the intent to the receiver asynchronously using one-way binder calls.
diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
index 26264e5da147..a54df4bf069d 100644
--- a/services/core/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -57,6 +57,8 @@ public final class CompatModePackages {
public static final int COMPAT_FLAG_DONT_ASK = 1<<0;
// Compatibility state: compatibility mode is enabled.
public static final int COMPAT_FLAG_ENABLED = 1<<1;
+ // Unsupported zoom state: don't warn the user about unsupported zoom mode.
+ public static final int UNSUPPORTED_ZOOM_FLAG_DONT_NOTIFY = 1<<2;
private final HashMap<String, Integer> mPackages = new HashMap<String, Integer>();
@@ -147,6 +149,24 @@ public final class CompatModePackages {
return flags != null ? flags : 0;
}
+ public void handlePackageDataClearedLocked(String packageName) {
+ // User has explicitly asked to clear all associated data.
+ removePackage(packageName);
+ }
+
+ public void handlePackageUninstalledLocked(String packageName) {
+ // Clear settings when app is uninstalled since this is an explicit
+ // signal from the user to remove the app and all associated data.
+ removePackage(packageName);
+ }
+
+ private void removePackage(String packageName) {
+ if (mPackages.containsKey(packageName)) {
+ mPackages.remove(packageName);
+ scheduleWrite();
+ }
+ }
+
public void handlePackageAddedLocked(String packageName, boolean updated) {
ApplicationInfo ai = null;
try {
@@ -165,13 +185,17 @@ public final class CompatModePackages {
// any current settings for it.
if (!mayCompat && mPackages.containsKey(packageName)) {
mPackages.remove(packageName);
- mHandler.removeMessages(MSG_WRITE);
- Message msg = mHandler.obtainMessage(MSG_WRITE);
- mHandler.sendMessageDelayed(msg, 10000);
+ scheduleWrite();
}
}
}
+ private void scheduleWrite() {
+ mHandler.removeMessages(MSG_WRITE);
+ Message msg = mHandler.obtainMessage(MSG_WRITE);
+ mHandler.sendMessageDelayed(msg, 10000);
+ }
+
public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
CompatibilityInfo ci = new CompatibilityInfo(ai, mService.mConfiguration.screenLayout,
mService.mConfiguration.smallestScreenWidthDp,
@@ -207,6 +231,10 @@ public final class CompatModePackages {
return (getPackageFlags(packageName)&COMPAT_FLAG_DONT_ASK) == 0;
}
+ public boolean getPackageNotifyUnsupportedZoomLocked(String packageName) {
+ return (getPackageFlags(packageName)&UNSUPPORTED_ZOOM_FLAG_DONT_NOTIFY) == 0;
+ }
+
public void setFrontActivityAskCompatModeLocked(boolean ask) {
ActivityRecord r = mService.getFocusedStack().topRunningActivityLocked();
if (r != null) {
@@ -223,9 +251,21 @@ public final class CompatModePackages {
} else {
mPackages.remove(packageName);
}
- mHandler.removeMessages(MSG_WRITE);
- Message msg = mHandler.obtainMessage(MSG_WRITE);
- mHandler.sendMessageDelayed(msg, 10000);
+ scheduleWrite();
+ }
+ }
+
+ public void setPackageNotifyUnsupportedZoomLocked(String packageName, boolean notify) {
+ final int curFlags = getPackageFlags(packageName);
+ final int newFlags = notify ? (curFlags&~UNSUPPORTED_ZOOM_FLAG_DONT_NOTIFY) :
+ (curFlags|UNSUPPORTED_ZOOM_FLAG_DONT_NOTIFY);
+ if (curFlags != newFlags) {
+ if (newFlags != 0) {
+ mPackages.put(packageName, newFlags);
+ } else {
+ mPackages.remove(packageName);
+ }
+ scheduleWrite();
}
}
@@ -321,9 +361,7 @@ public final class CompatModePackages {
// Need to get compatibility info in new state.
ci = compatibilityInfoForPackageLocked(ai);
- mHandler.removeMessages(MSG_WRITE);
- Message msg = mHandler.obtainMessage(MSG_WRITE);
- mHandler.sendMessageDelayed(msg, 10000);
+ scheduleWrite();
final ActivityStack stack = mService.getFocusedStack();
ActivityRecord starting = stack.restartPackage(packageName);
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index 1f3ccf530f71..3ed3d9a29c69 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -19,17 +19,23 @@ package com.android.server.am;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.content.ComponentName;
+import android.content.Context;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
import android.os.Process;
import android.os.UserHandle;
import android.util.Slog;
import com.android.internal.R;
import com.android.internal.util.ProgressReporter;
+import com.android.server.UiThread;
import java.util.List;
@@ -61,16 +67,20 @@ public abstract class PreBootBroadcaster extends IIntentReceiver.Stub {
mTargets = mService.mContext.getPackageManager().queryBroadcastReceiversAsUser(mIntent,
MATCH_SYSTEM_ONLY, UserHandle.of(userId));
+
+ mHandler.obtainMessage(MSG_SHOW).sendToTarget();
}
public void sendNext() {
if (mIndex >= mTargets.size()) {
+ mHandler.obtainMessage(MSG_HIDE).sendToTarget();
onFinished();
return;
}
if (!mService.isUserRunning(mUserId, 0)) {
Slog.i(TAG, "User " + mUserId + " is no longer running; skipping remaining receivers");
+ mHandler.obtainMessage(MSG_HIDE).sendToTarget();
onFinished();
return;
}
@@ -100,5 +110,44 @@ public abstract class PreBootBroadcaster extends IIntentReceiver.Stub {
sendNext();
}
+ private static final int MSG_SHOW = 1;
+ private static final int MSG_HIDE = 2;
+
+ private Handler mHandler = new Handler(UiThread.get().getLooper(), null, true) {
+ @Override
+ public void handleMessage(Message msg) {
+ final Context context = mService.mContext;
+ final NotificationManager notifManager = context
+ .getSystemService(NotificationManager.class);
+
+ switch (msg.what) {
+ case MSG_SHOW:
+ final CharSequence title = context
+ .getText(R.string.android_upgrading_notification_title);
+ final CharSequence message = context
+ .getText(R.string.android_upgrading_notification_body);
+ final Notification notif = new Notification.Builder(mService.mContext)
+ .setSmallIcon(R.drawable.stat_sys_adb)
+ .setWhen(0)
+ .setOngoing(true)
+ .setTicker(title)
+ .setDefaults(0)
+ .setPriority(Notification.PRIORITY_MAX)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(message)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .build();
+ notifManager.notifyAsUser(TAG, 0, notif, UserHandle.of(mUserId));
+ break;
+
+ case MSG_HIDE:
+ notifManager.cancelAsUser(TAG, 0, UserHandle.of(mUserId));
+ break;
+ }
+ }
+ };
+
public abstract void onFinished();
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 691fd2abe0b3..8911a3e94979 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -75,6 +75,7 @@ final class ProcessRecord {
ProcessState baseProcessTracker;
BatteryStatsImpl.Uid.Proc curProcBatteryStats;
int pid; // The process of this application; 0 if none
+ String procStatFile; // path to /proc/<pid>/stat
int[] gids; // The gids this process was launched with
String requiredAbi; // The ABI this process was launched with
String instructionSet; // The instruction set this process was launched with
@@ -93,6 +94,7 @@ final class ProcessRecord {
int setRawAdj; // Last set OOM unlimited adjustment for this process
int curAdj; // Current OOM adjustment for this process
int setAdj; // Last set OOM adjustment for this process
+ int verifiedAdj; // The last adjustment that was verified as actually being set
int curSchedGroup; // Currently desired scheduling class
int setSchedGroup; // Last set to background scheduling class
int trimMemoryLevel; // Last selected memory trimming level
@@ -441,7 +443,7 @@ final class ProcessRecord {
pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.versionCode));
maxAdj = ProcessList.UNKNOWN_ADJ;
curRawAdj = setRawAdj = ProcessList.INVALID_ADJ;
- curAdj = setAdj = ProcessList.INVALID_ADJ;
+ curAdj = setAdj = verifiedAdj = ProcessList.INVALID_ADJ;
persistent = false;
removed = false;
lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
@@ -449,6 +451,7 @@ final class ProcessRecord {
public void setPid(int _pid) {
pid = _pid;
+ procStatFile = null;
shortStringName = null;
stringName = null;
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 0a081e9809ea..2bfc4021f887 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -90,6 +90,7 @@ final class ServiceRecord extends Binder {
ProcessRecord isolatedProc; // keep track of isolated process, if requested
ServiceState tracker; // tracking service execution, may be null
ServiceState restartTracker; // tracking service restart
+ boolean whitelistManager; // any bindings to this service have BIND_ALLOW_WHITELIST_MANAGEMENT?
boolean delayed; // are we waiting to start this service in the background?
boolean isForeground; // is service currently in foreground mode?
int foregroundId; // Notification ID of last foreground req.
@@ -225,6 +226,9 @@ final class ServiceRecord extends Binder {
if (isolatedProc != null) {
pw.print(prefix); pw.print("isolatedProc="); pw.println(isolatedProc);
}
+ if (whitelistManager) {
+ pw.print(prefix); pw.print("whitelistManager="); pw.println(whitelistManager);
+ }
if (delayed) {
pw.print(prefix); pw.print("delayed="); pw.println(delayed);
}
@@ -391,6 +395,19 @@ final class ServiceRecord extends Binder {
return false;
}
+ public void updateWhitelistManager() {
+ whitelistManager = false;
+ for (int conni=connections.size()-1; conni>=0; conni--) {
+ ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
+ for (int i=0; i<cr.size(); i++) {
+ if ((cr.get(i).flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
+ whitelistManager = true;
+ return;
+ }
+ }
+ }
+ }
+
public void resetRestartCounter() {
restartCount = 0;
restartDelay = 0;
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index c84aaacd8aff..3f6db990a5b5 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -154,7 +154,6 @@ final class TaskRecord {
long lastActiveTime; // Last time this task was active, including sleep.
boolean inRecents; // Actually in the recents list?
boolean isAvailable; // Is the activity available to be launched?
- boolean isLaunching; // Is an activity in this task launching?
boolean rootWasReset; // True if the intent at the root of the task had
// the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
boolean autoRemoveRecents; // If true, we should automatically remove the task from
diff --git a/services/core/java/com/android/server/am/UnsupportedDisplaySizeDialog.java b/services/core/java/com/android/server/am/UnsupportedDisplaySizeDialog.java
new file mode 100644
index 000000000000..501cd6bbba6d
--- /dev/null
+++ b/services/core/java/com/android/server/am/UnsupportedDisplaySizeDialog.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.internal.R;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+
+public class UnsupportedDisplaySizeDialog {
+ private final AlertDialog mDialog;
+ private final String mPackageName;
+
+ public UnsupportedDisplaySizeDialog(final ActivityManagerService service, Context context,
+ ApplicationInfo appInfo) {
+ mPackageName = appInfo.packageName;
+
+ final PackageManager pm = context.getPackageManager();
+ final CharSequence label = appInfo.loadSafeLabel(pm);
+ final CharSequence message = context.getString(
+ R.string.unsupported_display_size_message, label);
+
+ mDialog = new AlertDialog.Builder(context)
+ .setPositiveButton(R.string.ok, null)
+ .setMessage(message)
+ .setView(R.layout.unsupported_display_size_dialog_content)
+ .create();
+
+ // Ensure the content view is prepared.
+ mDialog.create();
+
+ final Window window = mDialog.getWindow();
+ window.setType(WindowManager.LayoutParams.TYPE_PHONE);
+
+ // DO NOT MODIFY. Used by CTS to verify the dialog is displayed.
+ window.getAttributes().setTitle("UnsupportedDisplaySizeDialog");
+
+ final CheckBox alwaysShow = (CheckBox) mDialog.findViewById(R.id.ask_checkbox);
+ alwaysShow.setChecked(true);
+ alwaysShow.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ synchronized (service) {
+ service.mCompatModePackages.setPackageNotifyUnsupportedZoomLocked(
+ mPackageName, isChecked);
+ }
+ });
+ }
+
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ public void show() {
+ mDialog.show();
+ }
+
+ public void dismiss() {
+ mDialog.dismiss();
+ }
+}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 2375d7addb7f..d25f2cb76d74 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -76,6 +76,7 @@ import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
+import android.util.ArraySet;
import android.util.IntArray;
import android.util.Pair;
import android.util.Slog;
@@ -86,6 +87,7 @@ import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerService;
@@ -97,6 +99,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Helper class for {@link ActivityManagerService} responsible for multi-user functionality.
@@ -151,9 +154,9 @@ final class UserController {
= new RemoteCallbackList<>();
/**
- * Currently active user switch.
+ * Currently active user switch callbacks.
*/
- Object mCurUserSwitchCallback;
+ private volatile ArraySet<String> mCurWaitingUserSwitchCallbacks;
private volatile UserManagerService mUserManager;
@@ -1040,7 +1043,8 @@ final class UserController {
void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) {
synchronized (mService) {
- Slog.wtf(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId);
+ Slog.wtf(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId
+ + ". Observers that didn't send results: " + mCurWaitingUserSwitchCallbacks);
sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
}
}
@@ -1049,28 +1053,37 @@ final class UserController {
Slog.d(TAG, "Dispatch onUserSwitching oldUser #" + oldUserId + " newUser #" + newUserId);
final int observerCount = mUserSwitchObservers.beginBroadcast();
if (observerCount > 0) {
- final IRemoteCallback callback = new IRemoteCallback.Stub() {
- int mCount = 0;
- @Override
- public void sendResult(Bundle data) throws RemoteException {
- synchronized (mService) {
- if (mCurUserSwitchCallback == this) {
- mCount++;
- if (mCount == observerCount) {
- sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
- }
- }
- }
- }
- };
+ final ArraySet<String> curWaitingUserSwitchCallbacks = new ArraySet<>();
synchronized (mService) {
uss.switching = true;
- mCurUserSwitchCallback = callback;
+ mCurWaitingUserSwitchCallbacks = curWaitingUserSwitchCallbacks;
}
+ final AtomicInteger waitingCallbacksCount = new AtomicInteger(observerCount);
for (int i = 0; i < observerCount; i++) {
try {
- mUserSwitchObservers.getBroadcastItem(i).onUserSwitching(
- newUserId, callback);
+ // Prepend with unique prefix to guarantee that keys are unique
+ final String name = "#" + i + " " + mUserSwitchObservers.getBroadcastCookie(i);
+ synchronized (mService) {
+ curWaitingUserSwitchCallbacks.add(name);
+ }
+ final IRemoteCallback callback = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) throws RemoteException {
+ synchronized (mService) {
+ // Early return if this session is no longer valid
+ if (curWaitingUserSwitchCallbacks
+ != mCurWaitingUserSwitchCallbacks) {
+ return;
+ }
+ curWaitingUserSwitchCallbacks.remove(name);
+ // Continue switching if all callbacks have been notified
+ if (waitingCallbacksCount.decrementAndGet() == 0) {
+ sendContinueUserSwitchLocked(uss, oldUserId, newUserId);
+ }
+ }
+ }
+ };
+ mUserSwitchObservers.getBroadcastItem(i).onUserSwitching(newUserId, callback);
} catch (RemoteException e) {
}
}
@@ -1083,7 +1096,7 @@ final class UserController {
}
void sendContinueUserSwitchLocked(UserState uss, int oldUserId, int newUserId) {
- mCurUserSwitchCallback = null;
+ mCurWaitingUserSwitchCallbacks = null;
mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
mHandler.sendMessage(mHandler.obtainMessage(ActivityManagerService.CONTINUE_USER_SWITCH_MSG,
oldUserId, newUserId, uss));
@@ -1248,7 +1261,8 @@ final class UserController {
? getCurrentUserIdLocked(): userId;
}
- void registerUserSwitchObserver(IUserSwitchObserver observer) {
+ void registerUserSwitchObserver(IUserSwitchObserver observer, String name) {
+ Preconditions.checkNotNull(name, "Observer name cannot be null");
if (mService.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) {
final String msg = "Permission Denial: registerUserSwitchObserver() from pid="
@@ -1258,8 +1272,7 @@ final class UserController {
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
-
- mUserSwitchObservers.register(observer);
+ mUserSwitchObservers.register(observer, name);
}
void unregisterUserSwitchObserver(IUserSwitchObserver observer) {
@@ -1336,6 +1349,15 @@ final class UserController {
return mStartedUserArray;
}
+ boolean isUserStoppingOrShuttingDownLocked(int userId) {
+ UserState state = getStartedUserStateLocked(userId);
+ if (state == null) {
+ return false;
+ }
+ return state.state == UserState.STATE_STOPPING
+ || state.state == UserState.STATE_SHUTDOWN;
+ }
+
boolean isUserRunningLocked(int userId, int flags) {
UserState state = getStartedUserStateLocked(userId);
if (state == null) {
diff --git a/services/core/java/com/android/server/connectivity/DnsEventListenerService.java b/services/core/java/com/android/server/connectivity/DnsEventListenerService.java
index 18ab73100b81..8d206ef90b94 100644
--- a/services/core/java/com/android/server/connectivity/DnsEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/DnsEventListenerService.java
@@ -17,15 +17,17 @@
package com.android.server.connectivity;
import android.content.Context;
-import android.net.metrics.DnsEvent;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkRequest;
+import android.net.metrics.DnsEvent;
import android.net.metrics.IDnsEventListener;
+import android.net.metrics.IpConnectivityLog;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import java.io.PrintWriter;
@@ -45,12 +47,13 @@ public class DnsEventListenerService extends IDnsEventListener.Stub {
private static final boolean DBG = true;
private static final boolean VDBG = false;
+ // TODO: read this constant from system property
private static final int MAX_LOOKUPS_PER_DNS_EVENT = 100;
// Stores the results of a number of consecutive DNS lookups on the same network.
// This class is not thread-safe and it is the responsibility of the service to call its methods
// on one thread at a time.
- private static class DnsEventBatch {
+ private class DnsEventBatch {
private final int mNetId;
private final byte[] mEventTypes = new byte[MAX_LOOKUPS_PER_DNS_EVENT];
@@ -82,7 +85,7 @@ public class DnsEventListenerService extends IDnsEventListener.Stub {
byte[] eventTypes = Arrays.copyOf(mEventTypes, mEventCount);
byte[] returnCodes = Arrays.copyOf(mReturnCodes, mEventCount);
int[] latenciesMs = Arrays.copyOf(mLatenciesMs, mEventCount);
- DnsEvent.logEvent(mNetId, eventTypes, returnCodes, latenciesMs);
+ mMetricsLog.log(new DnsEvent(mNetId, eventTypes, returnCodes, latenciesMs));
maybeLog(String.format("Logging %d results for netId %d", mEventCount, mNetId));
mEventCount = 0;
}
@@ -96,13 +99,14 @@ public class DnsEventListenerService extends IDnsEventListener.Stub {
// Only sorted for ease of debugging. Because we only typically have a handful of networks up
// at any given time, performance is not a concern.
@GuardedBy("this")
- private SortedMap<Integer, DnsEventBatch> mEventBatches = new TreeMap<>();
+ private final SortedMap<Integer, DnsEventBatch> mEventBatches = new TreeMap<>();
// We register a NetworkCallback to ensure that when a network disconnects, we flush the DNS
// queries we've logged on that network. Because we do not do this periodically, we might lose
// up to MAX_LOOKUPS_PER_DNS_EVENT lookup stats on each network when the system is shutting
// down. We believe this to be sufficient for now.
private final ConnectivityManager mCm;
+ private final IpConnectivityLog mMetricsLog;
private final NetworkCallback mNetworkCallback = new NetworkCallback() {
@Override
public void onLost(Network network) {
@@ -116,11 +120,15 @@ public class DnsEventListenerService extends IDnsEventListener.Stub {
};
public DnsEventListenerService(Context context) {
+ this(context.getSystemService(ConnectivityManager.class), new IpConnectivityLog());
+ }
+
+ @VisibleForTesting
+ public DnsEventListenerService(ConnectivityManager cm, IpConnectivityLog log) {
// We are started when boot is complete, so ConnectivityService should already be running.
- final NetworkRequest request = new NetworkRequest.Builder()
- .clearCapabilities()
- .build();
- mCm = context.getSystemService(ConnectivityManager.class);
+ mCm = cm;
+ mMetricsLog = log;
+ final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
mCm.registerNetworkCallback(request, mNetworkCallback);
}
diff --git a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
index 69ef30fbe66a..05f1a6e6a3a4 100644
--- a/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
+++ b/services/core/java/com/android/server/connectivity/MetricsLoggerService.java
@@ -16,6 +16,7 @@
package com.android.server.connectivity;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.SystemService;
import android.app.PendingIntent;
@@ -60,17 +61,11 @@ public class MetricsLoggerService extends SystemService {
}
}
- // TODO: read from system property
- private final int MAX_NUMBER_OF_EVENTS = 1000;
-
- // TODO: read from system property
- private final int EVENTS_NOTIFICATION_THRESHOLD = 300;
-
- // TODO: read from system property
- private final int THROTTLING_TIME_INTERVAL_MILLIS = 60 * 60 * 1000; // 1 hour
-
- // TODO: read from system property
+ // TODO: read these constants from system property
+ private final int EVENTS_NOTIFICATION_THRESHOLD = 300;
+ private final int MAX_NUMBER_OF_EVENTS = 1000;
private final int THROTTLING_MAX_NUMBER_OF_MESSAGES_PER_COMPONENT = 1000;
+ private final long THROTTLING_TIME_INTERVAL_MILLIS = DateUtils.HOUR_IN_MILLIS;
private int mEventCounter = 0;
@@ -127,10 +122,13 @@ public class MetricsLoggerService extends SystemService {
mEvents.addLast(e);
}
+ @VisibleForTesting
+ final MetricsLoggerImpl mBinder = new MetricsLoggerImpl();
+
/**
* Implementation of the IConnectivityMetricsLogger interface.
*/
- private final IConnectivityMetricsLogger.Stub mBinder = new IConnectivityMetricsLogger.Stub() {
+ final class MetricsLoggerImpl extends IConnectivityMetricsLogger.Stub {
private final ArrayList<PendingIntent> mPendingIntents = new ArrayList<>();
@@ -223,7 +221,9 @@ public class MetricsLoggerService extends SystemService {
}
pw.println();
- mDnsListener.dump(pw);
+ if (mDnsListener != null) {
+ mDnsListener.dump(pw);
+ }
}
public long logEvent(ConnectivityMetricsEvent event) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index ddaebfa0e747..eeddff53e8ce 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -34,8 +34,9 @@ import android.net.NetworkRequest;
import android.net.ProxyInfo;
import android.net.TrafficStats;
import android.net.Uri;
-import android.net.metrics.ValidationProbeEvent;
+import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
+import android.net.metrics.ValidationProbeEvent;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.util.Stopwatch;
@@ -230,6 +231,7 @@ public class NetworkMonitor extends StateMachine {
private final WifiManager mWifiManager;
private final AlarmManager mAlarmManager;
private final NetworkRequest mDefaultRequest;
+ private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
private boolean mIsCaptivePortalCheckEnabled;
private boolean mUseHttps;
@@ -311,11 +313,11 @@ public class NetworkMonitor extends StateMachine {
transitionTo(mLingeringState);
return HANDLED;
case CMD_NETWORK_CONNECTED:
- NetworkEvent.logEvent(mNetId, NetworkEvent.NETWORK_CONNECTED);
+ logNetworkEvent(NetworkEvent.NETWORK_CONNECTED);
transitionTo(mEvaluatingState);
return HANDLED;
case CMD_NETWORK_DISCONNECTED:
- NetworkEvent.logEvent(mNetId, NetworkEvent.NETWORK_DISCONNECTED);
+ logNetworkEvent(NetworkEvent.NETWORK_DISCONNECTED);
if (mLaunchCaptivePortalAppBroadcastReceiver != null) {
mContext.unregisterReceiver(mLaunchCaptivePortalAppBroadcastReceiver);
mLaunchCaptivePortalAppBroadcastReceiver = null;
@@ -380,10 +382,7 @@ public class NetworkMonitor extends StateMachine {
private class ValidatedState extends State {
@Override
public void enter() {
- if (mEvaluationTimer.isRunning()) {
- NetworkEvent.logValidated(mNetId, mEvaluationTimer.stop());
- mEvaluationTimer.reset();
- }
+ maybeLogEvaluationResult(NetworkEvent.NETWORK_VALIDATED);
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
NETWORK_TEST_RESULT_VALID, mNetworkAgentInfo.network.netId, null));
}
@@ -530,7 +529,7 @@ public class NetworkMonitor extends StateMachine {
} else {
final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
sendMessageDelayed(msg, mReevaluateDelayMs);
- NetworkEvent.logEvent(mNetId, NetworkEvent.NETWORK_VALIDATION_FAILED);
+ logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
mConnectivityServiceHandler.sendMessage(obtainMessage(
EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, mNetId,
probeResult.mRedirectUrl));
@@ -590,10 +589,7 @@ public class NetworkMonitor extends StateMachine {
@Override
public void enter() {
- if (mEvaluationTimer.isRunning()) {
- NetworkEvent.logCaptivePortalFound(mNetId, mEvaluationTimer.stop());
- mEvaluationTimer.reset();
- }
+ maybeLogEvaluationResult(NetworkEvent.NETWORK_CAPTIVE_PORTAL_FOUND);
// Don't annoy user with sign-in notifications.
if (mDontDisplaySigninNotification) return;
// Create a CustomIntentReceiver that sends us a
@@ -758,11 +754,12 @@ public class NetworkMonitor extends StateMachine {
if (!TextUtils.isEmpty(hostToResolve)) {
String probeName = ValidationProbeEvent.getProbeName(ValidationProbeEvent.PROBE_DNS);
final Stopwatch dnsTimer = new Stopwatch().start();
+ int dnsResult;
+ long dnsLatency;
try {
InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(hostToResolve);
- long dnsLatency = dnsTimer.stop();
- ValidationProbeEvent.logEvent(mNetId, dnsLatency,
- ValidationProbeEvent.PROBE_DNS, ValidationProbeEvent.DNS_SUCCESS);
+ dnsResult = ValidationProbeEvent.DNS_SUCCESS;
+ dnsLatency = dnsTimer.stop();
final StringBuffer connectInfo = new StringBuffer(", " + hostToResolve + "=");
for (InetAddress address : addresses) {
connectInfo.append(address.getHostAddress());
@@ -770,11 +767,11 @@ public class NetworkMonitor extends StateMachine {
}
validationLog(probeName + " OK " + dnsLatency + "ms" + connectInfo);
} catch (UnknownHostException e) {
- long dnsLatency = dnsTimer.stop();
- ValidationProbeEvent.logEvent(mNetId, dnsLatency,
- ValidationProbeEvent.PROBE_DNS, ValidationProbeEvent.DNS_FAILURE);
+ dnsResult = ValidationProbeEvent.DNS_FAILURE;
+ dnsLatency = dnsTimer.stop();
validationLog(probeName + " FAIL " + dnsLatency + "ms, " + hostToResolve);
}
+ logValidationProbe(dnsLatency, ValidationProbeEvent.PROBE_DNS, dnsResult);
}
CaptivePortalProbeResult result;
@@ -855,7 +852,7 @@ public class NetworkMonitor extends StateMachine {
urlConnection.disconnect();
}
}
- ValidationProbeEvent.logEvent(mNetId, probeTimer.stop(), probeType, httpResponseCode);
+ logValidationProbe(probeTimer.stop(), probeType, httpResponseCode);
return new CaptivePortalProbeResult(httpResponseCode, redirectUrl);
}
@@ -1012,4 +1009,19 @@ public class NetworkMonitor extends StateMachine {
protected WakeupMessage makeWakeupMessage(Context c, Handler h, String s, int i) {
return new WakeupMessage(c, h, s, i);
}
+
+ private void logNetworkEvent(int evtype) {
+ mMetricsLog.log(new NetworkEvent(mNetId, evtype));
+ }
+
+ private void maybeLogEvaluationResult(int evtype) {
+ if (mEvaluationTimer.isRunning()) {
+ mMetricsLog.log(new NetworkEvent(mNetId, evtype, mEvaluationTimer.stop()));
+ mEvaluationTimer.reset();
+ }
+ }
+
+ private void logValidationProbe(long durationMs, int probeType, int probeResult) {
+ mMetricsLog.log(new ValidationProbeEvent(mNetId, durationMs, probeType, probeResult));
+ }
}
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 9220aa388f3e..01b23939815c 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -394,18 +394,9 @@ public final class ContentService extends IContentService.Stub {
for (int i=0; i<numCalls; i++) {
ObserverCall oc = calls.get(i);
try {
- // If the uri does not belong to the same user as the observer: we must add
- // the userId to the uri. Otherewise the observer would think the uri belongs
- // to his user.
- final Uri tempUri;
- if (oc.mObserverUserId != userHandle) {
- tempUri = ContentProvider.maybeAddUserId(uri, userHandle);
- } else {
- tempUri = uri;
- }
- oc.mObserver.onChange(oc.mSelfChange, tempUri, userHandle);
+ oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at "
- + tempUri);
+ + uri);
} catch (RemoteException ex) {
synchronized (mRootNode) {
Log.w(TAG, "Found dead observer, removing");
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 493fc4a4bb8c..39ddc3a98317 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1355,7 +1355,11 @@ public class SyncManager {
operation.extras.remove(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF);
}
- if (operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)) {
+ if (operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)
+ && !syncResult.syncAlreadyInProgress) {
+ // syncAlreadyInProgress flag is set by AbstractThreadedSyncAdapter. The sync adapter
+ // has no way of knowing that a sync error occured. So we DO retry if the error is
+ // syncAlreadyInProgress.
if (isLoggable) {
Log.d(TAG, "not retrying sync operation because SYNC_EXTRAS_DO_NOT_RETRY was specified "
+ operation);
@@ -2445,6 +2449,10 @@ public class SyncManager {
if (op.isPeriodic) {
scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
} else {
+ // mSyncJobService.callJobFinished is async, so cancel the job to ensure we don't
+ // find the this job in the pending jobs list while looking for duplicates
+ // before scheduling it at a later time.
+ getJobScheduler().cancel(op.jobId);
scheduleSyncOperationH(op, delay);
}
}
@@ -2886,6 +2894,14 @@ public class SyncManager {
String historyMessage;
int downstreamActivity;
int upstreamActivity;
+
+ if (!syncOperation.isPeriodic) {
+ // mSyncJobService.jobFinidhed is async, we need to ensure that this job is
+ // removed from JobScheduler's pending jobs list before moving forward and
+ // potentially rescheduling all pending jobs to respect new backoff values.
+ getJobScheduler().cancel(syncOperation.jobId);
+ }
+
if (syncResult != null) {
if (isLoggable) {
Slog.v(TAG, "runSyncFinishedOrCanceled [finished]: "
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index 804be4ea1ae7..c371f9705285 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -197,7 +197,7 @@ public class SyncOperation {
} else if (value instanceof Boolean) {
syncExtrasBundle.putBoolean(key, (Boolean) value);
} else if (value instanceof Float) {
- syncExtrasBundle.putDouble(key, (Double) value);
+ syncExtrasBundle.putDouble(key, (double) (float) value);
} else if (value instanceof Double) {
syncExtrasBundle.putDouble(key, (Double) value);
} else if (value instanceof String) {
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 1f6616ee0735..a783fa25ed45 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -20,6 +20,7 @@ import static android.Manifest.permission.BIND_DREAM_SERVICE;
import com.android.internal.util.DumpUtils;
import com.android.server.FgThread;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import android.Manifest;
@@ -32,6 +33,8 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
+import android.database.ContentObserver;
+import android.hardware.input.InputManagerInternal;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
@@ -111,11 +114,16 @@ public final class DreamManagerService extends SystemService {
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ writePulseGestureEnabled();
synchronized (mLock) {
stopDreamLocked(false /*immediate*/);
}
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.DOZE_ENABLED), false,
+ mDozeEnabledObserver, UserHandle.USER_ALL);
+ writePulseGestureEnabled();
}
}
@@ -414,6 +422,12 @@ public final class DreamManagerService extends SystemService {
}
}
+ private void writePulseGestureEnabled() {
+ ComponentName name = getDozeComponent();
+ boolean dozeEnabled = validateDream(name);
+ LocalServices.getService(InputManagerInternal.class).setPulseGestureEnabled(dozeEnabled);
+ }
+
private static String componentsToString(ComponentName[] componentNames) {
StringBuilder names = new StringBuilder();
if (componentNames != null) {
@@ -450,6 +464,13 @@ public final class DreamManagerService extends SystemService {
}
};
+ private final ContentObserver mDozeEnabledObserver = new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange) {
+ writePulseGestureEnabled();
+ }
+ };
+
/**
* Handler for asynchronous operations performed by the dream manager.
* Ensures operations to {@link DreamController} are single-threaded.
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index cc556c7e45b3..be8e300c9352 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -1013,20 +1013,18 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
public void onForegroundProfileSwitch(int newProfileId) {
// Ignore.
}
- });
+ }, TAG);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to listen for user switching event" ,e);
}
}
+ /***
+ * @param opPackageName the name of the calling package
+ * @return authenticator id for the current user
+ */
public long getAuthenticatorId(String opPackageName) {
- if (canUseFingerprint(opPackageName, false /* foregroundOnly */,
- Binder.getCallingUid(), Binder.getCallingPid())) {
- return mCurrentAuthenticatorId;
- } else {
- Slog.w(TAG, "Client isn't current, returning authenticator_id=0");
- }
- return 0;
+ return mCurrentAuthenticatorId;
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index aa1d73fe832e..74095acca16a 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -18,7 +18,9 @@ package com.android.server.input;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Build;
import android.os.LocaleList;
+import android.util.Log;
import android.view.Display;
import com.android.internal.inputmethod.InputMethodSubtypeHandle;
import com.android.internal.os.SomeArgs;
@@ -98,8 +100,11 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileReader;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -109,6 +114,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import libcore.io.IoUtils;
import libcore.io.Streams;
import libcore.util.Objects;
@@ -136,6 +142,8 @@ public class InputManagerService extends IInputManager.Stub
private final Context mContext;
private final InputManagerHandler mHandler;
+ private final File mDoubleTouchGestureEnableFile;
+
private WindowManagerCallbacks mWindowManagerCallbacks;
private WiredAccessoryCallbacks mWiredAccessoryCallbacks;
private boolean mSystemReady;
@@ -301,6 +309,11 @@ public class InputManagerService extends IInputManager.Stub
+ mUseDevInputEventForAudioJack);
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
+ String doubleTouchGestureEnablePath = context.getResources().getString(
+ R.string.config_doubleTouchGestureEnableFile);
+ mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
+ new File(doubleTouchGestureEnablePath);
+
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
@@ -2279,5 +2292,20 @@ public class InputManagerService extends IInputManager.Stub
public void toggleCapsLock(int deviceId) {
nativeToggleCapsLock(mPtr, deviceId);
}
+
+ @Override
+ public void setPulseGestureEnabled(boolean enabled) {
+ if (mDoubleTouchGestureEnableFile != null) {
+ FileWriter writer = null;
+ try {
+ writer = new FileWriter(mDoubleTouchGestureEnableFile);
+ writer.write(enabled ? "1" : "0");
+ } catch (IOException e) {
+ Log.wtf(TAG, "Unable to setPulseGestureEnabled", e);
+ } finally {
+ IoUtils.closeQuietly(writer);
+ }
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/job/controllers/ContentObserverController.java b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
index 26660e82e841..a42d0cd4c831 100644
--- a/services/core/java/com/android/server/job/controllers/ContentObserverController.java
+++ b/services/core/java/com/android/server/job/controllers/ContentObserverController.java
@@ -22,6 +22,7 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
+import android.util.Slog;
import android.util.TimeUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -40,6 +41,7 @@ import java.util.List;
*/
public class ContentObserverController extends StateController {
private static final String TAG = "JobScheduler.Content";
+ private static final boolean DEBUG = false;
/**
* Maximum number of changing URIs we will batch together to report.
@@ -57,7 +59,7 @@ public class ContentObserverController extends StateController {
private static volatile ContentObserverController sController;
final private List<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
- ArrayMap<Uri, ObserverInstance> mObservers = new ArrayMap<>();
+ ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> mObservers = new ArrayMap<>();
final Handler mHandler;
public static ContentObserverController get(JobSchedulerService taskManagerService) {
@@ -88,6 +90,9 @@ public class ContentObserverController extends StateController {
if (taskStatus.contentObserverJobInstance == null) {
taskStatus.contentObserverJobInstance = new JobInstance(taskStatus);
}
+ if (DEBUG) {
+ Slog.i(TAG, "Tracking content-trigger job " + taskStatus);
+ }
mTrackedTasks.add(taskStatus);
boolean havePendingUris = false;
// If there is a previous job associated with the new job, propagate over
@@ -175,6 +180,9 @@ public class ContentObserverController extends StateController {
taskStatus.contentObserverJobInstance = null;
}
}
+ if (DEBUG) {
+ Slog.i(TAG, "No longer tracking job " + taskStatus);
+ }
mTrackedTasks.remove(taskStatus);
}
}
@@ -194,16 +202,20 @@ public class ContentObserverController extends StateController {
}
final class ObserverInstance extends ContentObserver {
- final Uri mUri;
+ final JobInfo.TriggerContentUri mUri;
final ArraySet<JobInstance> mJobs = new ArraySet<>();
- public ObserverInstance(Handler handler, Uri uri) {
+ public ObserverInstance(Handler handler, JobInfo.TriggerContentUri uri) {
super(handler);
mUri = uri;
}
@Override
public void onChange(boolean selfChange, Uri uri) {
+ if (DEBUG) {
+ Slog.i(TAG, "onChange(self=" + selfChange + ") for " + uri
+ + " when mUri=" + mUri);
+ }
synchronized (mLock) {
final int N = mJobs.size();
for (int i=0; i<N; i++) {
@@ -253,16 +265,27 @@ public class ContentObserverController extends StateController {
final JobInfo.TriggerContentUri[] uris = jobStatus.getJob().getTriggerContentUris();
if (uris != null) {
for (JobInfo.TriggerContentUri uri : uris) {
- ObserverInstance obs = mObservers.get(uri.getUri());
+ ObserverInstance obs = mObservers.get(uri);
if (obs == null) {
- obs = new ObserverInstance(mHandler, uri.getUri());
- mObservers.put(uri.getUri(), obs);
+ obs = new ObserverInstance(mHandler, uri);
+ mObservers.put(uri, obs);
+ final boolean andDescendants = (uri.getFlags() &
+ JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS) != 0;
+ if (DEBUG) {
+ Slog.v(TAG, "New observer " + obs + " for " + uri.getUri()
+ + " andDescendants=" + andDescendants);
+ }
mContext.getContentResolver().registerContentObserver(
uri.getUri(),
- (uri.getFlags() &
- JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS)
- != 0,
+ andDescendants,
obs);
+ } else {
+ if (DEBUG) {
+ final boolean andDescendants = (uri.getFlags() &
+ JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS) != 0;
+ Slog.v(TAG, "Reusing existing observer " + obs + " for " + uri.getUri()
+ + " andDescendants=" + andDescendants);
+ }
}
obs.mJobs.add(this);
mMyObservers.add(obs);
@@ -315,6 +338,9 @@ public class ContentObserverController extends StateController {
final ObserverInstance obs = mMyObservers.get(i);
obs.mJobs.remove(this);
if (obs.mJobs.size() == 0) {
+ if (DEBUG) {
+ Slog.i(TAG, "Unregistering observer " + obs + " for " + obs.mUri.getUri());
+ }
mContext.getContentResolver().unregisterContentObserver(obs);
mObservers.remove(obs.mUri);
}
@@ -355,7 +381,10 @@ public class ContentObserverController extends StateController {
continue;
}
pw.print(" ");
- pw.print(mObservers.keyAt(i));
+ JobInfo.TriggerContentUri trigger = mObservers.keyAt(i);
+ pw.print(trigger.getUri());
+ pw.print(" 0x");
+ pw.print(Integer.toHexString(trigger.getFlags()));
pw.print(" (");
pw.print(System.identityHashCode(obs));
pw.println("):");
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 6b916be9d0fe..173f76fa52f5 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -899,6 +899,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
// hold wake lock while task runs
mWakeLock.acquire();
+ Log.i(TAG, "WakeLock acquired by handleInjectNtpTime()");
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
@Override
public void run() {
@@ -951,6 +952,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
// release wake lock held by task
mWakeLock.release();
+ Log.i(TAG, "WakeLock released by handleInjectNtpTime()");
}
});
}
@@ -969,6 +971,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
// hold wake lock while task runs
mWakeLock.acquire();
+ Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
@Override
public void run() {
@@ -991,6 +994,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
// release wake lock held by task
mWakeLock.release();
+ Log.i(TAG, "WakeLock released by handleDownloadXtraData()");
}
});
}
@@ -1192,7 +1196,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
}
if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
- if (mProviderRequest.reportLocation && !mDisableGps) {
+ if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) {
// update client uids
updateClientUids(mWorkSource);
@@ -2040,6 +2044,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
// note that this assumes the message will not be removed from the queue before
// it is handled (otherwise the wake lock would be leaked).
mWakeLock.acquire();
+ Log.i(TAG, "WakeLock acquired by sendMessage(" + message + ", " + arg + ", " + obj + ")");
mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
}
@@ -2099,6 +2104,8 @@ public class GnssLocationProvider implements LocationProviderInterface {
if (msg.arg2 == 1) {
// wakelock was taken for this message, release it
mWakeLock.release();
+ Log.i(TAG, "WakeLock released by handleMessage(" + message + ", " + msg.arg1 + ", "
+ + msg.obj + ")");
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 67cd7c32483b..6648d1e1f1b2 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -89,6 +89,7 @@ import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.Manifest;
+import android.annotation.IntDef;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
@@ -162,6 +163,7 @@ import android.util.TrustedTime;
import android.util.Xml;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.util.ArrayUtils;
@@ -187,6 +189,8 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
@@ -199,6 +203,26 @@ import java.util.List;
* Derives active rules by combining a given policy with other system status,
* and delivers to listeners, such as {@link ConnectivityManager}, for
* enforcement.
+ *
+ * <p>
+ * This class uses 2-3 locks to synchronize state:
+ * <ul>
+ * <li>{@code mUidRulesFirstLock}: used to guard state related to individual UIDs (such as firewall
+ * rules).
+ * <li>{@code mNetworkPoliciesSecondLock}: used to guard state related to network interfaces (such
+ * as network policies).
+ * <li>{@code allLocks}: not a "real" lock, but an indication (through @GuardedBy) that all locks
+ * must be held.
+ * </ul>
+ *
+ * <p>
+ * As such, methods that require synchronization have the following prefixes:
+ * <ul>
+ * <li>{@code UL()}: require the "UID" lock ({@code mUidRulesFirstLock}).
+ * <li>{@code NL()}: require the "Network" lock ({@code mNetworkPoliciesSecondLock}).
+ * <li>{@code AL()}: require all locks, which must be obtained in order ({@code mUidRulesFirstLock}
+ * first, then {@code mNetworkPoliciesSecondLock}, then {@code mYetAnotherGuardThirdLock}, etc..
+ * </ul>
*/
public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
static final String TAG = "NetworkPolicy";
@@ -282,13 +306,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private PowerManagerInternal mPowerManagerInternal;
private IDeviceIdleController mDeviceIdleController;
- final Object mRulesLock = new Object();
+ // See main javadoc for instructions on how to use these locks.
+ final Object mUidRulesFirstLock = new Object();
+ final Object mNetworkPoliciesSecondLock = new Object();
- volatile boolean mSystemReady;
- volatile boolean mScreenOn;
- volatile boolean mRestrictBackground;
- volatile boolean mRestrictPower;
- volatile boolean mDeviceIdleMode;
+ @GuardedBy("allLocks") volatile boolean mSystemReady;
+
+ @GuardedBy("mUidRulesFirstLock") volatile boolean mScreenOn;
+ @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictBackground;
+ @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictPower;
+ @GuardedBy("mUidRulesFirstLock") volatile boolean mDeviceIdleMode;
private final boolean mSuppressDefaultPolicy;
@@ -298,15 +325,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<>();
/** Defined UID policies. */
- final SparseIntArray mUidPolicy = new SparseIntArray();
+ @GuardedBy("mUidRulesFirstLock") final SparseIntArray mUidPolicy = new SparseIntArray();
/** Currently derived rules for each UID. */
- final SparseIntArray mUidRules = new SparseIntArray();
+ @GuardedBy("mUidRulesFirstLock") final SparseIntArray mUidRules = new SparseIntArray();
+ @GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
+ @GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+ @GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
+ @GuardedBy("mUidRulesFirstLock")
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
/**
@@ -314,6 +345,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* in power save mode, except device idle (doze) still applies.
* TODO: An int array might be sufficient
*/
+ @GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
/**
@@ -321,18 +353,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* in power save mode.
* TODO: An int array might be sufficient
*/
+ @GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
+ @GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();
/**
* UIDs that have been white-listed to avoid restricted background.
*/
+ @GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mRestrictBackgroundWhitelistUids = new SparseBooleanArray();
/**
* UIDs that have been initially white-listed by system to avoid restricted background.
*/
+ @GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mDefaultRestrictBackgroundWhitelistUids =
new SparseBooleanArray();
@@ -340,18 +376,23 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* UIDs that have been initially white-listed by system to avoid restricted background,
* but later revoked by user.
*/
+ @GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mRestrictBackgroundWhitelistRevokedUids =
new SparseBooleanArray();
/** Set of ifaces that are metered. */
+ @GuardedBy("mNetworkPoliciesSecondLock")
private ArraySet<String> mMeteredIfaces = new ArraySet<>();
/** Set of over-limit templates that have been notified. */
+ @GuardedBy("mNetworkPoliciesSecondLock")
private final ArraySet<NetworkTemplate> mOverLimitNotified = new ArraySet<>();
/** Set of currently active {@link Notification} tags. */
+ @GuardedBy("mNetworkPoliciesSecondLock")
private final ArraySet<String> mActiveNotifs = new ArraySet<String>();
/** Foreground at UID granularity. */
+ @GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidState = new SparseIntArray();
/** Higher priority listener before general event dispatch */
@@ -362,6 +403,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final Handler mHandler;
+ @GuardedBy("allLocks")
private final AtomicFile mPolicyFile;
private final AppOpsManager mAppOps;
@@ -426,7 +468,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
}
- void updatePowerSaveWhitelistLocked() {
+ void updatePowerSaveWhitelistUL() {
try {
int[] whitelist = mDeviceIdleController.getAppIdWhitelistExceptIdle();
mPowerSaveWhitelistExceptIdleAppIds.clear();
@@ -452,19 +494,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
*
* @return whether any uid has been added to {@link #mRestrictBackgroundWhitelistUids}.
*/
- boolean addDefaultRestrictBackgroundWhitelistUidsLocked() {
+ boolean addDefaultRestrictBackgroundWhitelistUidsUL() {
final List<UserInfo> users = mUserManager.getUsers();
final int numberUsers = users.size();
boolean changed = false;
for (int i = 0; i < numberUsers; i++) {
final UserInfo user = users.get(i);
- changed = addDefaultRestrictBackgroundWhitelistUidsLocked(user.id) || changed;
+ changed = addDefaultRestrictBackgroundWhitelistUidsUL(user.id) || changed;
}
return changed;
}
- private boolean addDefaultRestrictBackgroundWhitelistUidsLocked(int userId) {
+ private boolean addDefaultRestrictBackgroundWhitelistUidsUL(int userId) {
final SystemConfig sysConfig = SystemConfig.getInstance();
final PackageManager pm = mContext.getPackageManager();
final ArraySet<String> allowDataUsage = sysConfig.getAllowInDataUsageSave();
@@ -502,7 +544,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return changed;
}
- void updatePowerSaveTempWhitelistLocked() {
+ void updatePowerSaveTempWhitelistUL() {
try {
// Clear the states of the current whitelist
final int N = mPowerSaveTempWhitelistAppIds.size();
@@ -523,7 +565,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/**
* Remove unnecessary entries in the temp whitelist
*/
- void purgePowerSaveTempWhitelistLocked() {
+ void purgePowerSaveTempWhitelistUL() {
final int N = mPowerSaveTempWhitelistAppIds.size();
for (int i = N - 1; i >= 0; i--) {
if (mPowerSaveTempWhitelistAppIds.valueAt(i) == false) {
@@ -542,36 +584,38 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
- synchronized (mRulesLock) {
- updatePowerSaveWhitelistLocked();
- mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
- mPowerManagerInternal.registerLowPowerModeObserver(
- new PowerManagerInternal.LowPowerModeListener() {
- @Override
- public void onLowPowerModeChanged(boolean enabled) {
- if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
- synchronized (mRulesLock) {
- if (mRestrictPower != enabled) {
- mRestrictPower = enabled;
- updateRulesForRestrictPowerLocked();
- updateRulesForGlobalChangeLocked(true);
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ updatePowerSaveWhitelistUL();
+ mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
+ mPowerManagerInternal.registerLowPowerModeObserver(
+ new PowerManagerInternal.LowPowerModeListener() {
+ @Override
+ public void onLowPowerModeChanged(boolean enabled) {
+ if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
+ synchronized (mUidRulesFirstLock) {
+ if (mRestrictPower != enabled) {
+ mRestrictPower = enabled;
+ updateRulesForRestrictPowerUL();
+ }
}
}
- }
- });
- mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
+ });
+ mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
- mSystemReady = true;
+ mSystemReady = true;
- // read policy from disk
- readPolicyLocked();
+ // read policy from disk
+ readPolicyAL();
- if (addDefaultRestrictBackgroundWhitelistUidsLocked()) {
- writePolicyLocked();
- }
+ if (addDefaultRestrictBackgroundWhitelistUidsUL()) {
+ writePolicyAL();
+ }
- updateRulesForGlobalChangeLocked(false);
- updateNotificationsLocked();
+ setRestrictBackgroundUL(mRestrictBackground);
+ updateRulesForGlobalChangeAL(false);
+ updateNotificationsNL();
+ }
}
updateScreenOn();
@@ -650,14 +694,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
- synchronized (mRulesLock) {
- updateUidStateLocked(uid, procState);
+ synchronized (mUidRulesFirstLock) {
+ updateUidStateUL(uid, procState);
}
}
@Override public void onUidGone(int uid) throws RemoteException {
- synchronized (mRulesLock) {
- removeUidStateLocked(uid);
+ synchronized (mUidRulesFirstLock) {
+ removeUidStateUL(uid);
}
}
@@ -672,9 +716,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
- synchronized (mRulesLock) {
- updatePowerSaveWhitelistLocked();
- updateRulesForGlobalChangeLocked(false);
+ synchronized (mUidRulesFirstLock) {
+ updatePowerSaveWhitelistUL();
+ updateRulesForRestrictPowerUL();
}
}
};
@@ -682,10 +726,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final private Runnable mTempPowerSaveChangedCallback = new Runnable() {
@Override
public void run() {
- synchronized (mRulesLock) {
- updatePowerSaveTempWhitelistLocked();
- updateRulesForTempWhitelistChangeLocked();
- purgePowerSaveTempWhitelistLocked();
+ synchronized (mUidRulesFirstLock) {
+ updatePowerSaveTempWhitelistUL();
+ updateRulesForTempWhitelistChangeUL();
+ purgePowerSaveTempWhitelistUL();
}
}
};
@@ -712,8 +756,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// update rules for UID, since it might be subject to
// global background data policy
if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
- synchronized (mRulesLock) {
- updateRestrictionRulesForUidLocked(uid);
+ synchronized (mUidRulesFirstLock) {
+ updateRestrictionRulesForUidUL(uid);
}
}
}
@@ -729,10 +773,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// remove any policy and update rules to clean up
if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
mUidPolicy.delete(uid);
- updateRestrictionRulesForUidLocked(uid);
- writePolicyLocked();
+ updateRestrictionRulesForUidUL(uid);
+ synchronized (mNetworkPoliciesSecondLock) {
+ writePolicyAL();
+ }
}
}
};
@@ -750,16 +796,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
switch (action) {
case ACTION_USER_REMOVED:
case ACTION_USER_ADDED:
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
// Remove any persistable state for the given user; both cleaning up after a
// USER_REMOVED, and one last sanity check during USER_ADDED
- removeUserStateLocked(userId, true);
+ removeUserStateUL(userId, true);
if (action == ACTION_USER_ADDED) {
// Add apps that are whitelisted by default.
- addDefaultRestrictBackgroundWhitelistUidsLocked(userId);
+ addDefaultRestrictBackgroundWhitelistUidsUL(userId);
}
// Update global restrict for that user
- updateRulesForGlobalChangeLocked(true);
+ synchronized (mNetworkPoliciesSecondLock) {
+ updateRulesForGlobalChangeAL(true);
+ }
}
break;
}
@@ -777,9 +825,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// READ_NETWORK_USAGE_HISTORY permission above.
maybeRefreshTrustedTime();
- synchronized (mRulesLock) {
- updateNetworkEnabledLocked();
- updateNotificationsLocked();
+ synchronized (mNetworkPoliciesSecondLock) {
+ updateNetworkEnabledNL();
+ updateNotificationsNL();
}
}
};
@@ -828,10 +876,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
EXTRA_WIFI_CONFIGURATION);
if (config.SSID != null) {
final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(config.SSID);
- synchronized (mRulesLock) {
- if (mNetworkPolicy.containsKey(template)) {
- mNetworkPolicy.remove(template);
- writePolicyLocked();
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ if (mNetworkPolicy.containsKey(template)) {
+ mNetworkPolicy.remove(template);
+ writePolicyAL();
+ }
}
}
}
@@ -857,13 +907,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final boolean meteredHint = info.getMeteredHint();
final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(info.getSSID());
- synchronized (mRulesLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
NetworkPolicy policy = mNetworkPolicy.get(template);
if (policy == null && meteredHint) {
// policy doesn't exist, and AP is hinting that it's
// metered: create an inferred policy.
policy = newWifiPolicy(template, meteredHint);
- addNetworkPolicyLocked(policy);
+ addNetworkPolicyNL(policy);
} else if (policy != null && policy.inferred) {
// policy exists, and was inferred: update its current
@@ -872,7 +922,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// since this is inferred for each wifi session, just update
// rules without persisting.
- updateNetworkRulesLocked();
+ updateNetworkRulesNL();
}
}
}
@@ -904,8 +954,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Check {@link NetworkPolicy} against current {@link INetworkStatsService}
* to show visible notifications as needed.
*/
- void updateNotificationsLocked() {
- if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
+ void updateNotificationsNL() {
+ if (LOGV) Slog.v(TAG, "updateNotificationsNL()");
// keep track of previously active notifications
final ArraySet<String> beforeNotifs = new ArraySet<String>(mActiveNotifs);
@@ -931,11 +981,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
} else {
enqueueNotification(policy, TYPE_LIMIT, totalBytes);
- notifyOverLimitLocked(policy.template);
+ notifyOverLimitNL(policy.template);
}
} else {
- notifyUnderLimitLocked(policy.template);
+ notifyUnderLimitNL(policy.template);
if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
enqueueNotification(policy, TYPE_WARNING, totalBytes);
@@ -983,14 +1033,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Notify that given {@link NetworkTemplate} is over
* {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
*/
- private void notifyOverLimitLocked(NetworkTemplate template) {
+ private void notifyOverLimitNL(NetworkTemplate template) {
if (!mOverLimitNotified.contains(template)) {
mContext.startActivity(buildNetworkOverLimitIntent(template));
mOverLimitNotified.add(template);
}
}
- private void notifyUnderLimitLocked(NetworkTemplate template) {
+ private void notifyUnderLimitNL(NetworkTemplate template) {
mOverLimitNotified.remove(template);
}
@@ -1142,12 +1192,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// permission above.
maybeRefreshTrustedTime();
- synchronized (mRulesLock) {
- ensureActiveMobilePolicyLocked();
- normalizePoliciesLocked();
- updateNetworkEnabledLocked();
- updateNetworkRulesLocked();
- updateNotificationsLocked();
+ synchronized (mNetworkPoliciesSecondLock) {
+ ensureActiveMobilePolicyNL();
+ normalizePoliciesNL();
+ updateNetworkEnabledNL();
+ updateNetworkRulesNL();
+ updateNotificationsNL();
}
}
};
@@ -1156,8 +1206,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Proactively control network data connections when they exceed
* {@link NetworkPolicy#limitBytes}.
*/
- void updateNetworkEnabledLocked() {
- if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()");
+ void updateNetworkEnabledNL() {
+ if (LOGV) Slog.v(TAG, "updateNetworkEnabledNL()");
// TODO: reset any policy-disabled networks when any policy is removed
// completely, which is currently rare case.
@@ -1198,8 +1248,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* {@link NetworkPolicy} that need to be enforced. When matches found, set
* remaining quota based on usage cycle and historical stats.
*/
- void updateNetworkRulesLocked() {
- if (LOGV) Slog.v(TAG, "updateNetworkRulesLocked()");
+ void updateNetworkRulesNL() {
+ if (LOGV) Slog.v(TAG, "updateNetworkRulesNL()");
final NetworkState[] states;
try {
@@ -1349,8 +1399,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
* have at least a default mobile policy defined.
*/
- private void ensureActiveMobilePolicyLocked() {
- if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
+ private void ensureActiveMobilePolicyNL() {
+ if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyNL()");
if (mSuppressDefaultPolicy) return;
final TelephonyManager tele = TelephonyManager.from(mContext);
@@ -1359,11 +1409,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int[] subIds = sub.getActiveSubscriptionIdList();
for (int subId : subIds) {
final String subscriberId = tele.getSubscriberId(subId);
- ensureActiveMobilePolicyLocked(subscriberId);
+ ensureActiveMobilePolicyNL(subscriberId);
}
}
- private void ensureActiveMobilePolicyLocked(String subscriberId) {
+ private void ensureActiveMobilePolicyNL(String subscriberId) {
// Poke around to see if we already have a policy
final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
@@ -1394,11 +1444,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
- addNetworkPolicyLocked(policy);
+ addNetworkPolicyNL(policy);
}
- private void readPolicyLocked() {
- if (LOGV) Slog.v(TAG, "readPolicyLocked()");
+ private void readPolicyAL() {
+ if (LOGV) Slog.v(TAG, "readPolicyAL()");
// clear any existing policy and read from disk
mNetworkPolicy.clear();
@@ -1498,7 +1548,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int policy = readIntAttribute(in, ATTR_POLICY);
if (UserHandle.isApp(uid)) {
- setUidPolicyUncheckedLocked(uid, policy, false);
+ setUidPolicyUncheckedUL(uid, policy, false);
} else {
Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
}
@@ -1510,7 +1560,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// app policy is deprecated so this is only used in pre system user split.
final int uid = UserHandle.getUid(UserHandle.USER_SYSTEM, appId);
if (UserHandle.isApp(uid)) {
- setUidPolicyUncheckedLocked(uid, policy, false);
+ setUidPolicyUncheckedUL(uid, policy, false);
} else {
Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
}
@@ -1533,7 +1583,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
} catch (FileNotFoundException e) {
// missing policy is okay, probably first boot
- upgradeLegacyBackgroundData();
+ upgradeLegacyBackgroundDataUL();
} catch (IOException e) {
Log.wtf(TAG, "problem reading network policy", e);
} catch (XmlPullParserException e) {
@@ -1547,7 +1597,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Upgrade legacy background data flags, notifying listeners of one last
* change to always-true.
*/
- private void upgradeLegacyBackgroundData() {
+ private void upgradeLegacyBackgroundDataUL() {
mRestrictBackground = Settings.Secure.getInt(
mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1;
@@ -1559,8 +1609,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- void writePolicyLocked() {
- if (LOGV) Slog.v(TAG, "writePolicyLocked()");
+ void writePolicyAL() {
+ if (LOGV) Slog.v(TAG, "writePolicyAL()");
FileOutputStream fos = null;
try {
@@ -1657,13 +1707,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (!UserHandle.isApp(uid)) {
throw new IllegalArgumentException("cannot apply policy to UID " + uid);
}
-
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
final long token = Binder.clearCallingIdentity();
try {
final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
if (oldPolicy != policy) {
- setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
+ setUidPolicyUncheckedUL(uid, oldPolicy, policy, true);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -1679,11 +1728,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
throw new IllegalArgumentException("cannot apply policy to UID " + uid);
}
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
policy |= oldPolicy;
if (oldPolicy != policy) {
- setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
+ setUidPolicyUncheckedUL(uid, oldPolicy, policy, true);
}
}
}
@@ -1696,17 +1745,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
throw new IllegalArgumentException("cannot apply policy to UID " + uid);
}
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
policy = oldPolicy & ~policy;
if (oldPolicy != policy) {
- setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
+ setUidPolicyUncheckedUL(uid, oldPolicy, policy, true);
}
}
}
- private void setUidPolicyUncheckedLocked(int uid, int oldPolicy, int policy, boolean persist) {
- setUidPolicyUncheckedLocked(uid, policy, persist);
+ private void setUidPolicyUncheckedUL(int uid, int oldPolicy, int policy, boolean persist) {
+ setUidPolicyUncheckedUL(uid, policy, persist);
final boolean isBlacklisted = policy == POLICY_REJECT_METERED_BACKGROUND;
mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_BLACKLIST_CHANGED, uid,
@@ -1721,13 +1770,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- private void setUidPolicyUncheckedLocked(int uid, int policy, boolean persist) {
+ private void setUidPolicyUncheckedUL(int uid, int policy, boolean persist) {
mUidPolicy.put(uid, policy);
// uid policy changed, recompute rules and persist policy.
- updateRulesForDataUsageRestrictionsLocked(uid);
+ updateRulesForDataUsageRestrictionsUL(uid);
if (persist) {
- writePolicyLocked();
+ synchronized (mNetworkPoliciesSecondLock) {
+ writePolicyAL();
+ }
}
}
@@ -1735,7 +1786,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public int getUidPolicy(int uid) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
return mUidPolicy.get(uid, POLICY_NONE);
}
}
@@ -1745,7 +1796,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
int[] uids = new int[0];
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
for (int i = 0; i < mUidPolicy.size(); i++) {
final int uid = mUidPolicy.keyAt(i);
final int uidPolicy = mUidPolicy.valueAt(i);
@@ -1761,9 +1812,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Removes any persistable state associated with given {@link UserHandle}, persisting
* if any changes that are made.
*/
- boolean removeUserStateLocked(int userId, boolean writePolicy) {
+ boolean removeUserStateUL(int userId, boolean writePolicy) {
- if (LOGV) Slog.v(TAG, "removeUserStateLocked()");
+ if (LOGV) Slog.v(TAG, "removeUserStateUL()");
boolean changed = false;
// Remove entries from restricted background UID whitelist
@@ -1777,7 +1828,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (wlUids.length > 0) {
for (int uid : wlUids) {
- removeRestrictBackgroundWhitelistedUidLocked(uid, false, false);
+ removeRestrictBackgroundWhitelistedUidUL(uid, false, false);
}
changed = true;
}
@@ -1806,11 +1857,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
changed = true;
}
-
- updateRulesForGlobalChangeLocked(true);
-
- if (writePolicy && changed) {
- writePolicyLocked();
+ synchronized (mNetworkPoliciesSecondLock) {
+ updateRulesForGlobalChangeAL(true);
+ if (writePolicy && changed) {
+ writePolicyAL();
+ }
}
return changed;
}
@@ -1845,19 +1896,21 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final long token = Binder.clearCallingIdentity();
try {
maybeRefreshTrustedTime();
- synchronized (mRulesLock) {
- normalizePoliciesLocked(policies);
- updateNetworkEnabledLocked();
- updateNetworkRulesLocked();
- updateNotificationsLocked();
- writePolicyLocked();
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ normalizePoliciesNL(policies);
+ updateNetworkEnabledNL();
+ updateNetworkRulesNL();
+ updateNotificationsNL();
+ writePolicyAL();
+ }
}
} finally {
Binder.restoreCallingIdentity(token);
}
}
- void addNetworkPolicyLocked(NetworkPolicy policy) {
+ void addNetworkPolicyNL(NetworkPolicy policy) {
NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
policies = ArrayUtils.appendElement(NetworkPolicy.class, policies, policy);
setNetworkPolicies(policies);
@@ -1879,7 +1932,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- synchronized (mRulesLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
final int size = mNetworkPolicy.size();
final NetworkPolicy[] policies = new NetworkPolicy[size];
for (int i = 0; i < size; i++) {
@@ -1889,11 +1942,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- private void normalizePoliciesLocked() {
- normalizePoliciesLocked(getNetworkPolicies(mContext.getOpPackageName()));
+ private void normalizePoliciesNL() {
+ normalizePoliciesNL(getNetworkPolicies(mContext.getOpPackageName()));
}
- private void normalizePoliciesLocked(NetworkPolicy[] policies) {
+ private void normalizePoliciesNL(NetworkPolicy[] policies) {
final TelephonyManager tele = TelephonyManager.from(mContext);
final String[] merged = tele.getMergedSubscriberIds();
@@ -1927,29 +1980,31 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
void performSnooze(NetworkTemplate template, int type) {
maybeRefreshTrustedTime();
final long currentTime = currentTimeMillis();
- synchronized (mRulesLock) {
- // find and snooze local policy that matches
- final NetworkPolicy policy = mNetworkPolicy.get(template);
- if (policy == null) {
- throw new IllegalArgumentException("unable to find policy for " + template);
- }
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ // find and snooze local policy that matches
+ final NetworkPolicy policy = mNetworkPolicy.get(template);
+ if (policy == null) {
+ throw new IllegalArgumentException("unable to find policy for " + template);
+ }
- switch (type) {
- case TYPE_WARNING:
- policy.lastWarningSnooze = currentTime;
- break;
- case TYPE_LIMIT:
- policy.lastLimitSnooze = currentTime;
- break;
- default:
- throw new IllegalArgumentException("unexpected type");
- }
+ switch (type) {
+ case TYPE_WARNING:
+ policy.lastWarningSnooze = currentTime;
+ break;
+ case TYPE_LIMIT:
+ policy.lastLimitSnooze = currentTime;
+ break;
+ default:
+ throw new IllegalArgumentException("unexpected type");
+ }
- normalizePoliciesLocked();
- updateNetworkEnabledLocked();
- updateNetworkRulesLocked();
- updateNotificationsLocked();
- writePolicyLocked();
+ normalizePoliciesNL();
+ updateNetworkEnabledNL();
+ updateNetworkRulesNL();
+ updateNotificationsNL();
+ writePolicyAL();
+ }
}
}
@@ -1957,7 +2012,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public void onTetheringChanged(String iface, boolean tethering) {
// No need to enforce permission because setRestrictBackground() will do it.
if (LOGD) Log.d(TAG, "onTetherStateChanged(" + iface + ", " + tethering + ")");
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
if (mRestrictBackground && tethering) {
Log.d(TAG, "Tethering on (" + iface +"); disable Data Saver");
setRestrictBackground(false);
@@ -1971,13 +2026,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final long token = Binder.clearCallingIdentity();
try {
maybeRefreshTrustedTime();
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
if (restrictBackground == mRestrictBackground) {
// Ideally, UI should never allow this scenario...
Slog.w(TAG, "setRestrictBackground: already " + restrictBackground);
return;
}
- setRestrictBackgroundLocked(restrictBackground);
+ setRestrictBackgroundUL(restrictBackground);
}
} finally {
@@ -1988,26 +2043,29 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
.sendToTarget();
}
- private void setRestrictBackgroundLocked(boolean restrictBackground) {
+ private void setRestrictBackgroundUL(boolean restrictBackground) {
+ Slog.d(TAG, "setRestrictBackgroundUL(): " + restrictBackground);
final boolean oldRestrictBackground = mRestrictBackground;
mRestrictBackground = restrictBackground;
// Must whitelist foreground apps before turning data saver mode on.
// TODO: there is no need to iterate through all apps here, just those in the foreground,
// so it could call AM to get the UIDs of such apps, and iterate through them instead.
- updateRulesForRestrictBackgroundLocked();
+ updateRulesForAllAppsUL(TYPE_RESTRICT_BACKGROUND);
try {
if (!mNetworkManager.setDataSaverModeEnabled(mRestrictBackground)) {
Slog.e(TAG, "Could not change Data Saver Mode on NMS to " + mRestrictBackground);
mRestrictBackground = oldRestrictBackground;
// TODO: if it knew the foreground apps (see TODO above), it could call
- // updateRulesForRestrictBackgroundLocked() again to restore state.
+ // updateRulesForRestrictBackgroundUL() again to restore state.
return;
}
} catch (RemoteException e) {
// ignored; service lives in system_server
}
- updateNotificationsLocked();
- writePolicyLocked();
+ synchronized (mNetworkPoliciesSecondLock) {
+ updateNotificationsNL();
+ writePolicyAL();
+ }
}
@Override
@@ -2015,7 +2073,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
final boolean oldStatus;
final boolean needFirewallRules;
- synchronized (mRulesLock) {
+ int changed;
+ synchronized (mUidRulesFirstLock) {
oldStatus = mRestrictBackgroundWhitelistUids.get(uid);
if (oldStatus) {
if (LOGD) Slog.d(TAG, "uid " + uid + " is already whitelisted");
@@ -2032,12 +2091,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
if (needFirewallRules) {
// Only update firewall rules if necessary...
- updateRulesForDataUsageRestrictionsLocked(uid);
+ updateRulesForDataUsageRestrictionsUL(uid);
}
// ...but always persists the whitelist request.
- writePolicyLocked();
+ synchronized (mNetworkPoliciesSecondLock) {
+ writePolicyAL();
+ }
+ changed = (mRestrictBackground && !oldStatus && needFirewallRules) ? 1 : 0;
}
- int changed = (mRestrictBackground && !oldStatus && needFirewallRules) ? 1 : 0;
mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, changed,
Boolean.TRUE).sendToTarget();
}
@@ -2046,8 +2107,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public void removeRestrictBackgroundWhitelistedUid(int uid) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
final boolean changed;
- synchronized (mRulesLock) {
- changed = removeRestrictBackgroundWhitelistedUidLocked(uid, false, true);
+ synchronized (mUidRulesFirstLock) {
+ changed = removeRestrictBackgroundWhitelistedUidUL(uid, false, true);
}
mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, changed ? 1 : 0,
Boolean.FALSE).sendToTarget();
@@ -2057,7 +2118,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* Removes a uid from the restricted background whitelist, returning whether its current
* {@link ConnectivityManager.RestrictBackgroundStatus} changed.
*/
- private boolean removeRestrictBackgroundWhitelistedUidLocked(int uid, boolean uidDeleted,
+ private boolean removeRestrictBackgroundWhitelistedUidUL(int uid, boolean uidDeleted,
boolean updateNow) {
final boolean oldStatus = mRestrictBackgroundWhitelistUids.get(uid);
if (!oldStatus && !uidDeleted) {
@@ -2077,11 +2138,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
if (needFirewallRules) {
// Only update firewall rules if necessary...
- updateRulesForDataUsageRestrictionsLocked(uid, uidDeleted);
+ updateRulesForDataUsageRestrictionsUL(uid, uidDeleted);
}
if (updateNow) {
// ...but always persists the whitelist request.
- writePolicyLocked();
+ synchronized (mNetworkPoliciesSecondLock) {
+ writePolicyAL();
+ }
}
// Status only changes if Data Saver is turned on (otherwise it is DISABLED, even if the
// app was whitelisted before).
@@ -2091,7 +2154,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@Override
public int[] getRestrictBackgroundWhitelistedUids() {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
final int size = mRestrictBackgroundWhitelistUids.size();
final int[] whitelist = new int[size];
for (int i = 0; i < size; i++) {
@@ -2110,7 +2173,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
final int uid = Binder.getCallingUid();
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
// Must clear identity because getUidPolicy() is restricted to system.
final long token = Binder.clearCallingIdentity();
final int policy;
@@ -2136,7 +2199,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public boolean getRestrictBackground() {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
return mRestrictBackground;
}
}
@@ -2145,13 +2208,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public void setDeviceIdleMode(boolean enabled) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
if (mDeviceIdleMode != enabled) {
mDeviceIdleMode = enabled;
if (mSystemReady) {
// Device idle change means we need to rebuild rules for all
// known apps, so do a global refresh.
- updateRulesForGlobalChangeLocked(false);
+ updateRulesForRestrictPowerUL();
}
if (enabled) {
EventLogTags.writeDeviceIdleOnPhase("net");
@@ -2162,7 +2225,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) {
+ private NetworkPolicy findPolicyForNetworkNL(NetworkIdentity ident) {
for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
NetworkPolicy policy = mNetworkPolicy.valueAt(i);
if (policy.template.matches(ident)) {
@@ -2190,8 +2253,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
final NetworkPolicy policy;
- synchronized (mRulesLock) {
- policy = findPolicyForNetworkLocked(ident);
+ synchronized (mNetworkPoliciesSecondLock) {
+ policy = findPolicyForNetworkNL(ident);
}
if (policy == null || !policy.hasCycle()) {
@@ -2229,8 +2292,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
final NetworkPolicy policy;
- synchronized (mRulesLock) {
- policy = findPolicyForNetworkLocked(ident);
+ synchronized (mNetworkPoliciesSecondLock) {
+ policy = findPolicyForNetworkNL(ident);
}
if (policy != null) {
@@ -2255,155 +2318,157 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
argSet.add(arg);
}
- synchronized (mRulesLock) {
- if (argSet.contains("--unsnooze")) {
- for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
- mNetworkPolicy.valueAt(i).clearSnooze();
- }
-
- normalizePoliciesLocked();
- updateNetworkEnabledLocked();
- updateNetworkRulesLocked();
- updateNotificationsLocked();
- writePolicyLocked();
-
- fout.println("Cleared snooze timestamps");
- return;
- }
-
- fout.print("System ready: "); fout.println(mSystemReady);
- fout.print("Restrict background: "); fout.println(mRestrictBackground);
- fout.print("Restrict power: "); fout.println(mRestrictPower);
- fout.print("Device idle: "); fout.println(mDeviceIdleMode);
- fout.println("Network policies:");
- fout.increaseIndent();
- for (int i = 0; i < mNetworkPolicy.size(); i++) {
- fout.println(mNetworkPolicy.valueAt(i).toString());
- }
- fout.decreaseIndent();
+ synchronized (mUidRulesFirstLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ if (argSet.contains("--unsnooze")) {
+ for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
+ mNetworkPolicy.valueAt(i).clearSnooze();
+ }
- fout.print("Metered ifaces: "); fout.println(String.valueOf(mMeteredIfaces));
+ normalizePoliciesNL();
+ updateNetworkEnabledNL();
+ updateNetworkRulesNL();
+ updateNotificationsNL();
+ writePolicyAL();
- fout.println("Policy for UIDs:");
- fout.increaseIndent();
- int size = mUidPolicy.size();
- for (int i = 0; i < size; i++) {
- final int uid = mUidPolicy.keyAt(i);
- final int policy = mUidPolicy.valueAt(i);
- fout.print("UID=");
- fout.print(uid);
- fout.print(" policy=");
- fout.print(DebugUtils.flagsToString(NetworkPolicyManager.class, "POLICY_", policy));
- fout.println();
- }
- fout.decreaseIndent();
+ fout.println("Cleared snooze timestamps");
+ return;
+ }
- size = mPowerSaveWhitelistExceptIdleAppIds.size();
- if (size > 0) {
- fout.println("Power save whitelist (except idle) app ids:");
+ fout.print("System ready: "); fout.println(mSystemReady);
+ fout.print("Restrict background: "); fout.println(mRestrictBackground);
+ fout.print("Restrict power: "); fout.println(mRestrictPower);
+ fout.print("Device idle: "); fout.println(mDeviceIdleMode);
+ fout.println("Network policies:");
fout.increaseIndent();
- for (int i = 0; i < size; i++) {
- fout.print("UID=");
- fout.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
- fout.print(": ");
- fout.print(mPowerSaveWhitelistExceptIdleAppIds.valueAt(i));
- fout.println();
+ for (int i = 0; i < mNetworkPolicy.size(); i++) {
+ fout.println(mNetworkPolicy.valueAt(i).toString());
}
fout.decreaseIndent();
- }
- size = mPowerSaveWhitelistAppIds.size();
- if (size > 0) {
- fout.println("Power save whitelist app ids:");
+ fout.print("Metered ifaces: "); fout.println(String.valueOf(mMeteredIfaces));
+
+ fout.println("Policy for UIDs:");
fout.increaseIndent();
+ int size = mUidPolicy.size();
for (int i = 0; i < size; i++) {
+ final int uid = mUidPolicy.keyAt(i);
+ final int policy = mUidPolicy.valueAt(i);
fout.print("UID=");
- fout.print(mPowerSaveWhitelistAppIds.keyAt(i));
- fout.print(": ");
- fout.print(mPowerSaveWhitelistAppIds.valueAt(i));
+ fout.print(uid);
+ fout.print(" policy=");
+ fout.print(DebugUtils.flagsToString(NetworkPolicyManager.class, "POLICY_", policy));
fout.println();
}
fout.decreaseIndent();
- }
- size = mRestrictBackgroundWhitelistUids.size();
- if (size > 0) {
- fout.println("Restrict background whitelist uids:");
- fout.increaseIndent();
- for (int i = 0; i < size; i++) {
- fout.print("UID=");
- fout.print(mRestrictBackgroundWhitelistUids.keyAt(i));
- fout.println();
+ size = mPowerSaveWhitelistExceptIdleAppIds.size();
+ if (size > 0) {
+ fout.println("Power save whitelist (except idle) app ids:");
+ fout.increaseIndent();
+ for (int i = 0; i < size; i++) {
+ fout.print("UID=");
+ fout.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
+ fout.print(": ");
+ fout.print(mPowerSaveWhitelistExceptIdleAppIds.valueAt(i));
+ fout.println();
+ }
+ fout.decreaseIndent();
+ }
+
+ size = mPowerSaveWhitelistAppIds.size();
+ if (size > 0) {
+ fout.println("Power save whitelist app ids:");
+ fout.increaseIndent();
+ for (int i = 0; i < size; i++) {
+ fout.print("UID=");
+ fout.print(mPowerSaveWhitelistAppIds.keyAt(i));
+ fout.print(": ");
+ fout.print(mPowerSaveWhitelistAppIds.valueAt(i));
+ fout.println();
+ }
+ fout.decreaseIndent();
}
- fout.decreaseIndent();
- }
- size = mDefaultRestrictBackgroundWhitelistUids.size();
- if (size > 0) {
- fout.println("Default restrict background whitelist uids:");
+ size = mRestrictBackgroundWhitelistUids.size();
+ if (size > 0) {
+ fout.println("Restrict background whitelist uids:");
+ fout.increaseIndent();
+ for (int i = 0; i < size; i++) {
+ fout.print("UID=");
+ fout.print(mRestrictBackgroundWhitelistUids.keyAt(i));
+ fout.println();
+ }
+ fout.decreaseIndent();
+ }
+
+ size = mDefaultRestrictBackgroundWhitelistUids.size();
+ if (size > 0) {
+ fout.println("Default restrict background whitelist uids:");
+ fout.increaseIndent();
+ for (int i = 0; i < size; i++) {
+ fout.print("UID=");
+ fout.print(mDefaultRestrictBackgroundWhitelistUids.keyAt(i));
+ fout.println();
+ }
+ fout.decreaseIndent();
+ }
+
+ size = mRestrictBackgroundWhitelistRevokedUids.size();
+ if (size > 0) {
+ fout.println("Default restrict background whitelist uids revoked by users:");
+ fout.increaseIndent();
+ for (int i = 0; i < size; i++) {
+ fout.print("UID=");
+ fout.print(mRestrictBackgroundWhitelistRevokedUids.keyAt(i));
+ fout.println();
+ }
+ fout.decreaseIndent();
+ }
+
+ final SparseBooleanArray knownUids = new SparseBooleanArray();
+ collectKeys(mUidState, knownUids);
+ collectKeys(mUidRules, knownUids);
+
+ fout.println("Status for all known UIDs:");
fout.increaseIndent();
+ size = knownUids.size();
for (int i = 0; i < size; i++) {
+ final int uid = knownUids.keyAt(i);
fout.print("UID=");
- fout.print(mDefaultRestrictBackgroundWhitelistUids.keyAt(i));
+ fout.print(uid);
+
+ final int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ fout.print(" state=");
+ fout.print(state);
+ if (state <= ActivityManager.PROCESS_STATE_TOP) {
+ fout.print(" (fg)");
+ } else {
+ fout.print(state <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
+ ? " (fg svc)" : " (bg)");
+ }
+
+ final int uidRules = mUidRules.get(uid, RULE_NONE);
+ fout.print(" rules=");
+ fout.print(uidRulesToString(uidRules));
fout.println();
}
fout.decreaseIndent();
- }
- size = mRestrictBackgroundWhitelistRevokedUids.size();
- if (size > 0) {
- fout.println("Default restrict background whitelist uids revoked by users:");
+ fout.println("Status for just UIDs with rules:");
fout.increaseIndent();
+ size = mUidRules.size();
for (int i = 0; i < size; i++) {
+ final int uid = mUidRules.keyAt(i);
fout.print("UID=");
- fout.print(mRestrictBackgroundWhitelistRevokedUids.keyAt(i));
+ fout.print(uid);
+ final int uidRules = mUidRules.get(uid, RULE_NONE);
+ fout.print(" rules=");
+ fout.print(uidRulesToString(uidRules));
fout.println();
}
fout.decreaseIndent();
}
-
- final SparseBooleanArray knownUids = new SparseBooleanArray();
- collectKeys(mUidState, knownUids);
- collectKeys(mUidRules, knownUids);
-
- fout.println("Status for all known UIDs:");
- fout.increaseIndent();
- size = knownUids.size();
- for (int i = 0; i < size; i++) {
- final int uid = knownUids.keyAt(i);
- fout.print("UID=");
- fout.print(uid);
-
- final int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
- fout.print(" state=");
- fout.print(state);
- if (state <= ActivityManager.PROCESS_STATE_TOP) {
- fout.print(" (fg)");
- } else {
- fout.print(state <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
- ? " (fg svc)" : " (bg)");
- }
-
- final int uidRules = mUidRules.get(uid, RULE_NONE);
- fout.print(" rules=");
- fout.print(uidRulesToString(uidRules));
- fout.println();
- }
- fout.decreaseIndent();
-
- fout.println("Status for just UIDs with rules:");
- fout.increaseIndent();
- size = mUidRules.size();
- for (int i = 0; i < size; i++) {
- final int uid = mUidRules.keyAt(i);
- fout.print("UID=");
- fout.print(uid);
- final int uidRules = mUidRules.get(uid, RULE_NONE);
- fout.print(" rules=");
- fout.print(uidRulesToString(uidRules));
- fout.println();
- }
- fout.decreaseIndent();
}
}
@@ -2418,74 +2483,74 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public boolean isUidForeground(int uid) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
- synchronized (mRulesLock) {
- return isUidForegroundLocked(uid);
+ synchronized (mUidRulesFirstLock) {
+ return isUidForegroundUL(uid);
}
}
- private boolean isUidForegroundLocked(int uid) {
- return isUidStateForegroundLocked(
+ private boolean isUidForegroundUL(int uid) {
+ return isUidStateForegroundUL(
mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY));
}
- private boolean isUidForegroundOnRestrictBackgroundLocked(int uid) {
+ private boolean isUidForegroundOnRestrictBackgroundUL(int uid) {
final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
- return isProcStateAllowedWhileOnRestrictBackgroundLocked(procState);
+ return isProcStateAllowedWhileOnRestrictBackground(procState);
}
- private boolean isUidForegroundOnRestrictPowerLocked(int uid) {
+ private boolean isUidForegroundOnRestrictPowerUL(int uid) {
final int procState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
return isProcStateAllowedWhileIdleOrPowerSaveMode(procState);
}
- private boolean isUidStateForegroundLocked(int state) {
+ private boolean isUidStateForegroundUL(int state) {
// only really in foreground when screen is also on
return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP;
}
/**
* Process state of UID changed; if needed, will trigger
- * {@link #updateRulesForDataUsageRestrictionsLocked(int)} and
- * {@link #updateRulesForPowerRestrictionsLocked(int)}
+ * {@link #updateRulesForDataUsageRestrictionsUL(int)} and
+ * {@link #updateRulesForPowerRestrictionsUL(int)}
*/
- private void updateUidStateLocked(int uid, int uidState) {
+ private void updateUidStateUL(int uid, int uidState) {
final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
if (oldUidState != uidState) {
// state changed, push updated rules
mUidState.put(uid, uidState);
- updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState, uidState);
+ updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState, uidState);
if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
!= isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
if (isUidIdle(uid)) {
- updateRuleForAppIdleLocked(uid);
+ updateRuleForAppIdleUL(uid);
}
if (mDeviceIdleMode) {
- updateRuleForDeviceIdleLocked(uid);
+ updateRuleForDeviceIdleUL(uid);
}
if (mRestrictPower) {
- updateRuleForRestrictPowerLocked(uid);
+ updateRuleForRestrictPowerUL(uid);
}
- updateRulesForPowerRestrictionsLocked(uid);
+ updateRulesForPowerRestrictionsUL(uid);
}
- updateNetworkStats(uid, isUidStateForegroundLocked(uidState));
+ updateNetworkStats(uid, isUidStateForegroundUL(uidState));
}
}
- private void removeUidStateLocked(int uid) {
+ private void removeUidStateUL(int uid) {
final int index = mUidState.indexOfKey(uid);
if (index >= 0) {
final int oldUidState = mUidState.valueAt(index);
mUidState.removeAt(index);
if (oldUidState != ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
- updateRestrictBackgroundRulesOnUidStatusChangedLocked(uid, oldUidState,
+ updateRestrictBackgroundRulesOnUidStatusChangedUL(uid, oldUidState,
ActivityManager.PROCESS_STATE_CACHED_EMPTY);
if (mDeviceIdleMode) {
- updateRuleForDeviceIdleLocked(uid);
+ updateRuleForDeviceIdleUL(uid);
}
if (mRestrictPower) {
- updateRuleForRestrictPowerLocked(uid);
+ updateRuleForRestrictPowerUL(uid);
}
- updateRulesForPowerRestrictionsLocked(uid);
+ updateRulesForPowerRestrictionsUL(uid);
updateNetworkStats(uid, false);
}
}
@@ -2500,38 +2565,38 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- private void updateRestrictBackgroundRulesOnUidStatusChangedLocked(int uid, int oldUidState,
+ private void updateRestrictBackgroundRulesOnUidStatusChangedUL(int uid, int oldUidState,
int newUidState) {
final boolean oldForeground =
- isProcStateAllowedWhileOnRestrictBackgroundLocked(oldUidState);
+ isProcStateAllowedWhileOnRestrictBackground(oldUidState);
final boolean newForeground =
- isProcStateAllowedWhileOnRestrictBackgroundLocked(newUidState);
+ isProcStateAllowedWhileOnRestrictBackground(newUidState);
if (oldForeground != newForeground) {
- updateRulesForDataUsageRestrictionsLocked(uid);
+ updateRulesForDataUsageRestrictionsUL(uid);
}
}
private void updateScreenOn() {
- synchronized (mRulesLock) {
+ synchronized (mUidRulesFirstLock) {
try {
mScreenOn = mPowerManager.isInteractive();
} catch (RemoteException e) {
// ignored; service lives in system_server
}
- updateRulesForScreenLocked();
+ updateRulesForScreenUL();
}
}
/**
* Update rules that might be changed by {@link #mScreenOn} value.
*/
- private void updateRulesForScreenLocked() {
+ private void updateRulesForScreenUL() {
// only update rules for anyone with foreground activities
final int size = mUidState.size();
for (int i = 0; i < size; i++) {
if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
final int uid = mUidState.keyAt(i);
- updateRestrictionRulesForUidLocked(uid);
+ updateRestrictionRulesForUidUL(uid);
}
}
}
@@ -2540,31 +2605,31 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
}
- static boolean isProcStateAllowedWhileOnRestrictBackgroundLocked(int procState) {
+ static boolean isProcStateAllowedWhileOnRestrictBackground(int procState) {
return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
}
- void updateRulesForRestrictPowerLocked() {
- updateRulesForWhitelistedPowerSaveLocked(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
+ void updateRulesForPowerSaveUL() {
+ updateRulesForWhitelistedPowerSaveUL(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
mUidFirewallPowerSaveRules);
}
- void updateRuleForRestrictPowerLocked(int uid) {
- updateRulesForWhitelistedPowerSaveLocked(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
+ void updateRuleForRestrictPowerUL(int uid) {
+ updateRulesForWhitelistedPowerSaveUL(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
}
- void updateRulesForDeviceIdleLocked() {
- updateRulesForWhitelistedPowerSaveLocked(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,
+ void updateRulesForDeviceIdleUL() {
+ updateRulesForWhitelistedPowerSaveUL(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,
mUidFirewallDozableRules);
}
- void updateRuleForDeviceIdleLocked(int uid) {
- updateRulesForWhitelistedPowerSaveLocked(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
+ void updateRuleForDeviceIdleUL(int uid) {
+ updateRulesForWhitelistedPowerSaveUL(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
}
// NOTE: since both fw_dozable and fw_powersave uses the same map
// (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
- private void updateRulesForWhitelistedPowerSaveLocked(boolean enabled, int chain,
+ private void updateRulesForWhitelistedPowerSaveUL(boolean enabled, int chain,
SparseIntArray rules) {
if (enabled) {
// Sync the whitelists before enabling the chain. We don't care about the rules if
@@ -2595,23 +2660,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
setUidFirewallRules(chain, uidRules);
}
- enableFirewallChainLocked(chain, enabled);
+ enableFirewallChainUL(chain, enabled);
}
- private void updateRulesForNonMeteredNetworksLocked() {
-
- }
-
- private boolean isWhitelistedBatterySaverLocked(int uid) {
+ private boolean isWhitelistedBatterySaverUL(int uid) {
final int appId = UserHandle.getAppId(uid);
return mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId);
}
// NOTE: since both fw_dozable and fw_powersave uses the same map
// (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
- private void updateRulesForWhitelistedPowerSaveLocked(int uid, boolean enabled, int chain) {
+ private void updateRulesForWhitelistedPowerSaveUL(int uid, boolean enabled, int chain) {
if (enabled) {
- if (isWhitelistedBatterySaverLocked(uid)
+ if (isWhitelistedBatterySaverUL(uid)
|| isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.get(uid))) {
setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
} else {
@@ -2620,7 +2681,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- void updateRulesForAppIdleLocked() {
+ void updateRulesForAppIdleUL() {
final SparseIntArray uidRules = mUidFirewallStandbyRules;
uidRules.clear();
@@ -2644,50 +2705,69 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
setUidFirewallRules(FIREWALL_CHAIN_STANDBY, uidRules);
}
- void updateRuleForAppIdleLocked(int uid) {
+ void updateRuleForAppIdleUL(int uid) {
if (!isUidValidForBlacklistRules(uid)) return;
int appId = UserHandle.getAppId(uid);
if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)
- && !isUidForegroundOnRestrictPowerLocked(uid)) {
+ && !isUidForegroundOnRestrictPowerUL(uid)) {
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
} else {
setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
}
}
- void updateRulesForAppIdleParoleLocked() {
+ void updateRulesForAppIdleParoleUL() {
boolean enableChain = !mUsageStats.isAppIdleParoleOn();
- enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain);
+ enableFirewallChainUL(FIREWALL_CHAIN_STANDBY, enableChain);
}
/**
* Update rules that might be changed by {@link #mRestrictBackground},
* {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
*/
- private void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) {
+ private void updateRulesForGlobalChangeAL(boolean restrictedNetworksChanged) {
long start;
if (LOGD) start = System.currentTimeMillis();
- updateRulesForDeviceIdleLocked();
- updateRulesForAppIdleLocked();
- updateRulesForRestrictPowerLocked();
- updateRulesForRestrictBackgroundLocked();
- setRestrictBackgroundLocked(mRestrictBackground);
+ updateRulesForRestrictPowerUL();
+ updateRulesForRestrictBackgroundUL();
// If the set of restricted networks may have changed, re-evaluate those.
if (restrictedNetworksChanged) {
- normalizePoliciesLocked();
- updateNetworkRulesLocked();
+ normalizePoliciesNL();
+ updateNetworkRulesNL();
}
if (LOGD) {
final long delta = System.currentTimeMillis() - start;
- Slog.d(TAG, "updateRulesForGlobalChangeLocked(" + restrictedNetworksChanged + ") took "
+ Slog.d(TAG, "updateRulesForGlobalChangeAL(" + restrictedNetworksChanged + ") took "
+ delta + "ms");
}
}
- private void updateRulesForRestrictBackgroundLocked() {
+ private void updateRulesForRestrictPowerUL() {
+ updateRulesForDeviceIdleUL();
+ updateRulesForAppIdleUL();
+ updateRulesForPowerSaveUL();
+ updateRulesForAllAppsUL(TYPE_RESTRICT_POWER);
+ }
+
+ private void updateRulesForRestrictBackgroundUL() {
+ updateRulesForAllAppsUL(TYPE_RESTRICT_BACKGROUND);
+ }
+
+ private static final int TYPE_RESTRICT_BACKGROUND = 1;
+ private static final int TYPE_RESTRICT_POWER = 2;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = false, value = {
+ TYPE_RESTRICT_BACKGROUND,
+ TYPE_RESTRICT_POWER,
+ })
+ public @interface RestrictType {
+ }
+
+ // TODO: refactor / consolidate all those updateXyz methods, there are way too many of them...
+ private void updateRulesForAllAppsUL(@RestrictType int type) {
final PackageManager pm = mContext.getPackageManager();
// update rules for all installed applications
@@ -2704,25 +2784,34 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
for (int j = 0; j < appsSize; j++) {
final ApplicationInfo app = apps.get(j);
final int uid = UserHandle.getUid(user.id, app.uid);
- updateRulesForDataUsageRestrictionsLocked(uid);
- updateRulesForPowerRestrictionsLocked(uid);
+ switch (type) {
+ case TYPE_RESTRICT_BACKGROUND:
+ updateRulesForDataUsageRestrictionsUL(uid);
+ break;
+ case TYPE_RESTRICT_POWER:
+ updateRulesForPowerRestrictionsUL(uid);
+ break;
+ default:
+ Slog.w(TAG, "Invalid type for updateRulesForAllApps: " + type);
+ }
}
}
}
- private void updateRulesForTempWhitelistChangeLocked() {
+ private void updateRulesForTempWhitelistChangeUL() {
final List<UserInfo> users = mUserManager.getUsers();
for (int i = 0; i < users.size(); i++) {
final UserInfo user = users.get(i);
for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; j--) {
int appId = mPowerSaveTempWhitelistAppIds.keyAt(j);
int uid = UserHandle.getUid(user.id, appId);
+ updateRulesForRestrictPowerUL();
// Update external firewall rules.
- updateRuleForAppIdleLocked(uid);
- updateRuleForDeviceIdleLocked(uid);
- updateRuleForRestrictPowerLocked(uid);
+ updateRuleForAppIdleUL(uid);
+ updateRuleForDeviceIdleUL(uid);
+ updateRuleForRestrictPowerUL(uid);
// Update internal rules.
- updateRulesForPowerRestrictionsLocked(uid);
+ updateRulesForPowerRestrictionsUL(uid);
}
}
}
@@ -2786,17 +2875,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
*
* <p>This method changes both the external firewall rules and the internal state.
*/
- private void updateRestrictionRulesForUidLocked(int uid) {
+ private void updateRestrictionRulesForUidUL(int uid) {
// Methods below only changes the firewall rules for the power-related modes.
- updateRuleForDeviceIdleLocked(uid);
- updateRuleForAppIdleLocked(uid);
- updateRuleForRestrictPowerLocked(uid);
+ updateRuleForDeviceIdleUL(uid);
+ updateRuleForAppIdleUL(uid);
+ updateRuleForRestrictPowerUL(uid);
// Update internal state for power-related modes.
- updateRulesForPowerRestrictionsLocked(uid);
+ updateRulesForPowerRestrictionsUL(uid);
// Update firewall and internal rules for Data Saver Mode.
- updateRulesForDataUsageRestrictionsLocked(uid);
+ updateRulesForDataUsageRestrictionsUL(uid);
}
/**
@@ -2818,7 +2907,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* {@link #setUidPolicy(int, int)} and {@link #addRestrictBackgroundWhitelistedUid(int)} /
* {@link #removeRestrictBackgroundWhitelistedUid(int)} methods (for blacklist and whitelist
* respectively): these methods set the proper internal state (blacklist / whitelist), then call
- * this ({@link #updateRulesForDataUsageRestrictionsLocked(int)}) to propagate the rules to
+ * this ({@link #updateRulesForDataUsageRestrictionsUL(int)}) to propagate the rules to
* {@link INetworkManagementService}, but this method should also be called in events (like
* Data Saver Mode flips or UID state changes) that might affect the foreground app, since the
* following rules should also be applied:
@@ -2838,15 +2927,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* <p>The {@link #mUidRules} map is used to define the transtion of states of an UID.
*
*/
- private void updateRulesForDataUsageRestrictionsLocked(int uid) {
- updateRulesForDataUsageRestrictionsLocked(uid, false);
+ private void updateRulesForDataUsageRestrictionsUL(int uid) {
+ updateRulesForDataUsageRestrictionsUL(uid, false);
}
/**
- * Overloaded version of {@link #updateRulesForDataUsageRestrictionsLocked(int)} called when an
+ * Overloaded version of {@link #updateRulesForDataUsageRestrictionsUL(int)} called when an
* app is removed - it ignores the UID validity check.
*/
- private void updateRulesForDataUsageRestrictionsLocked(int uid, boolean uidDeleted) {
+ private void updateRulesForDataUsageRestrictionsUL(int uid, boolean uidDeleted) {
if (!uidDeleted && !isUidValidForWhitelistRules(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid);
return;
@@ -2854,7 +2943,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final int oldUidRules = mUidRules.get(uid, RULE_NONE);
- final boolean isForeground = isUidForegroundOnRestrictBackgroundLocked(uid);
+ final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid);
final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
final boolean isWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
@@ -2878,7 +2967,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int newUidRules = newRule | (oldUidRules & MASK_ALL_NETWORKS);
if (LOGV) {
- Log.v(TAG, "updateRuleForRestrictBackgroundLocked(" + uid + ")"
+ Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")"
+ ": isForeground=" +isForeground
+ ", isBlacklisted=" + isBlacklisted
+ ", isWhitelisted=" + isWhitelisted
@@ -2971,7 +3060,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* <p>
* <strong>NOTE: </strong>This method does not update the firewall rules on {@code netd}.
*/
- private void updateRulesForPowerRestrictionsLocked(int uid) {
+ private void updateRulesForPowerRestrictionsUL(int uid) {
if (!isUidValidForBlacklistRules(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
return;
@@ -2981,9 +3070,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode;
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final int oldUidRules = mUidRules.get(uid, RULE_NONE);
- final boolean isForeground = isUidForegroundOnRestrictPowerLocked(uid);
+ final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
- final boolean isWhitelisted = isWhitelistedBatterySaverLocked(uid);
+ final boolean isWhitelisted = isWhitelistedBatterySaverUL(uid);
final int oldRule = oldUidRules & MASK_ALL_NETWORKS;
int newRule = RULE_NONE;
@@ -3002,7 +3091,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule;
if (LOGV) {
- Log.v(TAG, "updateRulesForNonMeteredNetworksLocked(" + uid + ")"
+ Log.v(TAG, "updateRulesForNonMeteredNetworksUL(" + uid + ")"
+ ", isIdle: " + isIdle
+ ", mRestrictPower: " + mRestrictPower
+ ", mDeviceIdleMode: " + mDeviceIdleMode
@@ -3047,9 +3136,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
if (LOGV) Log.v(TAG, "onAppIdleStateChanged(): uid=" + uid + ", idle=" + idle);
- synchronized (mRulesLock) {
- updateRuleForAppIdleLocked(uid);
- updateRulesForPowerRestrictionsLocked(uid);
+ synchronized (mUidRulesFirstLock) {
+ updateRuleForAppIdleUL(uid);
+ updateRulesForPowerRestrictionsUL(uid);
}
} catch (NameNotFoundException nnfe) {
}
@@ -3057,8 +3146,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@Override
public void onParoleStateChanged(boolean isParoleOn) {
- synchronized (mRulesLock) {
- updateRulesForAppIdleParoleLocked();
+ synchronized (mUidRulesFirstLock) {
+ updateRulesForAppIdleParoleUL();
}
}
}
@@ -3143,7 +3232,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final String iface = (String) msg.obj;
maybeRefreshTrustedTime();
- synchronized (mRulesLock) {
+ synchronized (mNetworkPoliciesSecondLock) {
if (mMeteredIfaces.contains(iface)) {
try {
// force stats update to make sure we have
@@ -3153,8 +3242,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// ignored; service lives in system_server
}
- updateNetworkEnabledLocked();
- updateNotificationsLocked();
+ updateNetworkEnabledNL();
+ updateNotificationsNL();
}
}
return true;
@@ -3354,7 +3443,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/**
* Add or remove a uid to the firewall blacklist for all network ifaces.
*/
- private void enableFirewallChainLocked(int chain, boolean enable) {
+ private void enableFirewallChainUL(int chain, boolean enable) {
if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
mFirewallChainStates.get(chain) == enable) {
// All is the same, nothing to do.
@@ -3483,9 +3572,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@Override
public void onPackageRemoved(String packageName, int uid) {
if (LOGV) Slog.v(TAG, "onPackageRemoved: " + packageName + " ->" + uid);
- synchronized (mRulesLock) {
- removeRestrictBackgroundWhitelistedUidLocked(uid, true, true);
- updateRestrictionRulesForUidLocked(uid);
+ synchronized (mUidRulesFirstLock) {
+ removeRestrictBackgroundWhitelistedUidUL(uid, true, true);
+ updateRestrictionRulesForUidUL(uid);
}
}
}
@@ -3494,11 +3583,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@Override
public void resetUserState(int userId) {
- synchronized (mRulesLock) {
- boolean changed = removeUserStateLocked(userId, false);
- changed = addDefaultRestrictBackgroundWhitelistUidsLocked(userId) || changed;
+ synchronized (mUidRulesFirstLock) {
+ boolean changed = removeUserStateUL(userId, false);
+ changed = addDefaultRestrictBackgroundWhitelistUidsUL(userId) || changed;
if (changed) {
- writePolicyLocked();
+ synchronized (mNetworkPoliciesSecondLock) {
+ writePolicyAL();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java
index ea361700faf4..336058453479 100644
--- a/services/core/java/com/android/server/net/NetworkStatsObservers.java
+++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java
@@ -355,9 +355,10 @@ class NetworkStatsObservers {
@Override
protected void recordSample(StatsContext statsContext) {
// Recorder does not need to be locked in this context since only the handler
- // thread will update it
+ // thread will update it. We pass a null VPN array because usage is aggregated by uid
+ // for this snapshot, so VPN traffic can't be reattributed to responsible apps.
mRecorder.recordSnapshotLocked(statsContext.mXtSnapshot, statsContext.mActiveIfaces,
- statsContext.mVpnArray, statsContext.mCurrentTime);
+ null /* vpnArray */, statsContext.mCurrentTime);
}
/**
@@ -396,7 +397,8 @@ class NetworkStatsObservers {
@Override
protected void recordSample(StatsContext statsContext) {
// Recorder does not need to be locked in this context since only the handler
- // thread will update it
+ // thread will update it. We pass the VPN info so VPN traffic is reattributed to
+ // responsible apps.
mRecorder.recordSnapshotLocked(statsContext.mUidSnapshot, statsContext.mActiveUidIfaces,
statsContext.mVpnArray, statsContext.mCurrentTime);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 04dc917ec3ab..090a0762a4b5 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -22,6 +22,7 @@ import static android.net.TrafficStats.MB_IN_BYTES;
import static android.text.format.DateUtils.YEAR_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
+import android.annotation.Nullable;
import android.net.NetworkStats;
import android.net.NetworkStats.NonMonotonicObserver;
import android.net.NetworkStatsHistory;
@@ -199,9 +200,14 @@ public class NetworkStatsRecorder {
* Record any delta that occurred since last {@link NetworkStats} snapshot,
* using the given {@link Map} to identify network interfaces. First
* snapshot is considered bootstrap, and is not counted as delta.
+ *
+ * @param vpnArray Optional info about the currently active VPN, if any. This is used to
+ * redistribute traffic from the VPN app to the underlying responsible apps.
+ * This should always be set to null if the provided snapshot is aggregated
+ * across all UIDs (e.g. contains UID_ALL buckets), regardless of VPN state.
*/
public void recordSnapshotLocked(NetworkStats snapshot,
- Map<String, NetworkIdentitySet> ifaceIdent, VpnInfo[] vpnArray,
+ Map<String, NetworkIdentitySet> ifaceIdent, @Nullable VpnInfo[] vpnArray,
long currentTimeMillis) {
final HashSet<String> unknownIfaces = Sets.newHashSet();
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 8610fa1b7b49..23c111e56cde 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -1009,9 +1009,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
+
+ // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
+ // can't be reattributed to responsible apps.
+ mDevRecorder.recordSnapshotLocked(
+ devSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
+ mXtRecorder.recordSnapshotLocked(
+ xtSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
+
+ // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps.
VpnInfo[] vpnArray = mConnManager.getAllVpnInfo();
- mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, null, currentTime);
- mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, null, currentTime);
mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d4ee02e75754..1206263fb281 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -67,7 +67,6 @@ import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
@@ -306,6 +305,7 @@ public class NotificationManagerService extends SystemService {
private RankingHandler mRankingHandler;
private long mLastOverRateLogTime;
private float mMaxPackageEnqueueRate = DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE;
+ private String mSystemNotificationSound;
private static class Archive {
final int mBufferSize;
@@ -818,6 +818,8 @@ public class NotificationManagerService extends SystemService {
private final class SettingsObserver extends ContentObserver {
private final Uri NOTIFICATION_LIGHT_PULSE_URI
= Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
+ private final Uri NOTIFICATION_SOUND_URI
+ = Settings.System.getUriFor(Settings.System.NOTIFICATION_SOUND);
private final Uri NOTIFICATION_RATE_LIMIT_URI
= Settings.Global.getUriFor(Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE);
@@ -829,6 +831,8 @@ public class NotificationManagerService extends SystemService {
ContentResolver resolver = getContext().getContentResolver();
resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI,
false, this, UserHandle.USER_ALL);
+ resolver.registerContentObserver(NOTIFICATION_SOUND_URI,
+ false, this, UserHandle.USER_ALL);
resolver.registerContentObserver(NOTIFICATION_RATE_LIMIT_URI,
false, this, UserHandle.USER_ALL);
update(null);
@@ -852,6 +856,10 @@ public class NotificationManagerService extends SystemService {
mMaxPackageEnqueueRate = Settings.Global.getFloat(resolver,
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE, mMaxPackageEnqueueRate);
}
+ if (uri == null || NOTIFICATION_SOUND_URI.equals(uri)) {
+ mSystemNotificationSound = Settings.System.getString(resolver,
+ Settings.System.NOTIFICATION_SOUND);
+ }
}
}
@@ -904,6 +912,11 @@ public class NotificationManagerService extends SystemService {
mHandler = handler;
}
+ @VisibleForTesting
+ void setSystemNotificationSound(String systemNotificationSound) {
+ mSystemNotificationSound = systemNotificationSound;
+ }
+
@Override
public void onStart() {
Resources resources = getContext().getResources();
@@ -1984,6 +1997,7 @@ public class NotificationManagerService extends SystemService {
android.Manifest.permission.MANAGE_NOTIFICATIONS)) {
return;
}
+ checkCallerIsSameApp(pkg);
if (!checkPolicyAccess(pkg)) {
Slog.w(TAG, "Notification policy access denied calling " + method);
throw new SecurityException("Notification policy access denied");
@@ -2521,6 +2535,8 @@ public class NotificationManagerService extends SystemService {
return;
}
+ mUsageStats.registerEnqueuedByApp(pkg);
+
// Limit the number of notifications that any given package except the android
// package or a registered listener can enqueue. Prevents DOS attacks and deals with leaks.
if (!isSystemNotification && !isNotificationFromListener) {
@@ -2562,7 +2578,22 @@ public class NotificationManagerService extends SystemService {
+ " id=" + id + " notification=" + notification);
}
- markAsSentFromNotification(notification);
+ // Whitelist pending intents.
+ if (notification.allPendingIntents != null) {
+ final int intentCount = notification.allPendingIntents.size();
+ if (intentCount > 0) {
+ final ActivityManagerInternal am = LocalServices
+ .getService(ActivityManagerInternal.class);
+ final long duration = LocalServices.getService(
+ DeviceIdleController.LocalService.class).getNotificationWhitelistDuration();
+ for (int i = 0; i < intentCount; i++) {
+ PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);
+ if (pendingIntent != null) {
+ am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(), duration);
+ }
+ }
+ }
+ }
// Sanitize inputs
notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN,
@@ -2578,67 +2609,6 @@ public class NotificationManagerService extends SystemService {
idOut[0] = id;
}
- private static void markAsSentFromNotification(Notification notification) {
- final ActivityManagerInternal am = LocalServices.getService(ActivityManagerInternal.class);
- final long duration = LocalServices.getService(DeviceIdleController.LocalService.class)
- .getNotificationWhitelistDuration();
-
- int size = 0;
- if (notification.contentIntent != null) {
- am.setPendingIntentWhitelistDuration(notification.contentIntent.getTarget(), duration);
- }
- if (notification.deleteIntent != null) {
- am.setPendingIntentWhitelistDuration(notification.deleteIntent.getTarget(), duration);
- }
- if (notification.fullScreenIntent != null) {
- am.setPendingIntentWhitelistDuration(notification.fullScreenIntent.getTarget(),
- duration);
- }
- if (notification.actions != null) {
- for (Notification.Action action: notification.actions) {
- if (action.actionIntent == null) {
- continue;
- }
- am.setPendingIntentWhitelistDuration(action.actionIntent.getTarget(), duration);
- setPendingIntentWhitelistDuration(am, duration, action.getExtras());
- final RemoteInput[] remoteInputs = action.getRemoteInputs();
- if (remoteInputs != null) {
- for (RemoteInput remoteInput : remoteInputs) {
- setPendingIntentWhitelistDuration(am, duration, remoteInput.getExtras());
- }
- }
- }
- }
- }
-
- private static void setPendingIntentWhitelistDuration(ActivityManagerInternal am, long duration,
- Bundle extras) {
- for (String key : extras.keySet()) {
- final Object value = extras.get(key);
- if (value instanceof Parcelable) {
- setPendingIntentWhitelistDuration(am, duration, (Parcelable) value);
- } else if (value instanceof Parcelable[]) {
- for (Parcelable parcelable : (Parcelable[]) value) {
- setPendingIntentWhitelistDuration(am, duration, parcelable);
- }
- } else if (value instanceof List) {
- for (Object element : (List <?>) value) {
- if (element instanceof Parcelable) {
- setPendingIntentWhitelistDuration(am, duration, (Parcelable) element);
- }
- }
- }
- }
- }
-
- private static void setPendingIntentWhitelistDuration(ActivityManagerInternal am, long duration,
- Parcelable parcelable) {
- if (parcelable instanceof PendingIntent) {
- am.setPendingIntentWhitelistDuration(((PendingIntent) parcelable).getTarget(),
- duration);
- }
- }
-
private class EnqueueNotificationRunnable implements Runnable {
private final NotificationRecord r;
private final int userId;
@@ -2803,7 +2773,7 @@ public class NotificationManagerService extends SystemService {
// notification was a summary and its group key changed.
if (oldIsSummary && (!isSummary || !oldGroup.equals(group))) {
cancelGroupChildrenLocked(old, callingUid, callingPid, null,
- REASON_GROUP_SUMMARY_CANCELED);
+ REASON_GROUP_SUMMARY_CANCELED, false /* sendDelete */);
}
}
@@ -2868,9 +2838,7 @@ public class NotificationManagerService extends SystemService {
soundUri = Settings.System.DEFAULT_NOTIFICATION_URI;
// check to see if the default notification sound is silent
- ContentResolver resolver = getContext().getContentResolver();
- hasValidSound = Settings.System.getString(resolver,
- Settings.System.NOTIFICATION_SOUND) != null;
+ hasValidSound = mSystemNotificationSound != null;
} else if (notification.sound != null) {
soundUri = notification.sound;
hasValidSound = (soundUri != null);
@@ -3436,7 +3404,7 @@ public class NotificationManagerService extends SystemService {
cancelNotificationLocked(r, sendDelete, reason);
cancelGroupChildrenLocked(r, callingUid, callingPid, listenerName,
- REASON_GROUP_SUMMARY_CANCELED);
+ REASON_GROUP_SUMMARY_CANCELED, sendDelete);
updateLightsLocked();
}
}
@@ -3515,7 +3483,7 @@ public class NotificationManagerService extends SystemService {
final int M = canceledNotifications.size();
for (int i = 0; i < M; i++) {
cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid,
- listenerName, REASON_GROUP_SUMMARY_CANCELED);
+ listenerName, REASON_GROUP_SUMMARY_CANCELED, false /* sendDelete */);
}
}
if (canceledNotifications != null) {
@@ -3559,14 +3527,14 @@ public class NotificationManagerService extends SystemService {
int M = canceledNotifications != null ? canceledNotifications.size() : 0;
for (int i = 0; i < M; i++) {
cancelGroupChildrenLocked(canceledNotifications.get(i), callingUid, callingPid,
- listenerName, REASON_GROUP_SUMMARY_CANCELED);
+ listenerName, REASON_GROUP_SUMMARY_CANCELED, false /* sendDelete */);
}
updateLightsLocked();
}
// Warning: The caller is responsible for invoking updateLightsLocked().
private void cancelGroupChildrenLocked(NotificationRecord r, int callingUid, int callingPid,
- String listenerName, int reason) {
+ String listenerName, int reason, boolean sendDelete) {
Notification n = r.getNotification();
if (!n.isGroupSummary()) {
return;
@@ -3589,7 +3557,7 @@ public class NotificationManagerService extends SystemService {
EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, childSbn.getId(),
childSbn.getTag(), userId, 0, 0, reason, listenerName);
mNotificationList.remove(i);
- cancelNotificationLocked(childR, false, reason);
+ cancelNotificationLocked(childR, sendDelete, reason);
}
}
}
@@ -3688,6 +3656,10 @@ public class NotificationManagerService extends SystemService {
if (isCallerSystem()) {
return;
}
+ checkCallerIsSameApp(pkg);
+ }
+
+ private static void checkCallerIsSameApp(String pkg) {
final int uid = Binder.getCallingUid();
try {
ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(
@@ -3897,7 +3869,9 @@ public class NotificationManagerService extends SystemService {
@Override
public void onUserSwitched(int user) {
synchronized (mNotificationList) {
- for (ManagedServiceInfo info : mServices) {
+ int i = mServices.size()-1;
+ while (i --> 0) {
+ final ManagedServiceInfo info = mServices.get(i);
unregisterService(info.service, info.userid);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 7b573da482e3..34c52833fbfd 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -114,6 +114,17 @@ public class NotificationUsageStats {
}
/**
+ * Called when a notification is tentatively enqueued by an app, before rate checking.
+ */
+ public synchronized void registerEnqueuedByApp(String packageName) {
+ AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(packageName);
+ for (AggregatedStats stats : aggregatedStatsArray) {
+ stats.numEnqueuedByApp++;
+ }
+ releaseAggregatedStatsLocked(aggregatedStatsArray);
+ }
+
+ /**
* Called when a notification has been posted.
*/
public synchronized void registerPostedByApp(NotificationRecord notification) {
@@ -135,7 +146,8 @@ public class NotificationUsageStats {
/**
* Called when a notification has been updated.
*/
- public void registerUpdatedByApp(NotificationRecord notification, NotificationRecord old) {
+ public synchronized void registerUpdatedByApp(NotificationRecord notification,
+ NotificationRecord old) {
notification.stats.updateFrom(old.stats);
AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
for (AggregatedStats stats : aggregatedStatsArray) {
@@ -344,6 +356,7 @@ public class NotificationUsageStats {
private AggregatedStats mPrevious;
// ---- Updated as the respective events occur.
+ public int numEnqueuedByApp;
public int numPostedByApp;
public int numUpdatedByApp;
public int numRemovedByApp;
@@ -470,6 +483,7 @@ public class NotificationUsageStats {
public void emit() {
AggregatedStats previous = getPrevious();
+ maybeCount("note_enqueued", (numEnqueuedByApp - previous.numEnqueuedByApp));
maybeCount("note_post", (numPostedByApp - previous.numPostedByApp));
maybeCount("note_update", (numUpdatedByApp - previous.numUpdatedByApp));
maybeCount("note_remove", (numRemovedByApp - previous.numRemovedByApp));
@@ -501,6 +515,7 @@ public class NotificationUsageStats {
quietImportance.maybeCount(previous.quietImportance);
finalImportance.maybeCount(previous.finalImportance);
+ previous.numEnqueuedByApp = numEnqueuedByApp;
previous.numPostedByApp = numPostedByApp;
previous.numUpdatedByApp = numUpdatedByApp;
previous.numRemovedByApp = numRemovedByApp;
@@ -568,6 +583,8 @@ public class NotificationUsageStats {
output.append(indentPlusTwo);
output.append("key='").append(key).append("',\n");
output.append(indentPlusTwo);
+ output.append("numEnqueuedByApp=").append(numEnqueuedByApp).append(",\n");
+ output.append(indentPlusTwo);
output.append("numPostedByApp=").append(numPostedByApp).append(",\n");
output.append(indentPlusTwo);
output.append("numUpdatedByApp=").append(numUpdatedByApp).append(",\n");
@@ -631,6 +648,7 @@ public class NotificationUsageStats {
JSONObject dump = new JSONObject();
dump.put("key", key);
dump.put("duration", SystemClock.elapsedRealtime() - mCreated);
+ maybePut(dump, "numEnqueuedByApp", numEnqueuedByApp);
maybePut(dump, "numPostedByApp", numPostedByApp);
maybePut(dump, "numUpdatedByApp", numUpdatedByApp);
maybePut(dump, "numRemovedByApp", numRemovedByApp);
diff --git a/services/core/java/com/android/server/notification/RateEstimator.java b/services/core/java/com/android/server/notification/RateEstimator.java
index c17db4acf3cd..a2f93dce2bca 100644
--- a/services/core/java/com/android/server/notification/RateEstimator.java
+++ b/services/core/java/com/android/server/notification/RateEstimator.java
@@ -26,9 +26,12 @@ public class RateEstimator {
private static final double RATE_ALPHA = 0.8;
private static final double MINIMUM_DT = 0.0005;
private Long mLastEventTime;
- private Float mInterarrivalTime;
+ private double mInterarrivalTime;
- public RateEstimator() {}
+ public RateEstimator() {
+ // assume something generous if we have no information
+ mInterarrivalTime = 1000.0;
+ }
/** Update the estimate to account for an event that just happened. */
public float update(long now) {
@@ -38,7 +41,7 @@ public class RateEstimator {
rate = 0f;
} else {
// Calculate the new inter-arrival time based on last event time.
- mInterarrivalTime = (float) getInterarrivalEstimate(now);
+ mInterarrivalTime = getInterarrivalEstimate(now);
rate = (float) (1.0 / mInterarrivalTime);
}
mLastEventTime = now;
@@ -57,10 +60,6 @@ public class RateEstimator {
private double getInterarrivalEstimate(long now) {
double dt = ((double) (now - mLastEventTime)) / 1000.0;
dt = Math.max(dt, MINIMUM_DT);
- if (mInterarrivalTime == null) {
- // No last inter-arrival time, return the new value directly.
- return dt;
- }
// a*iat_old + (1-a)*(t_now-t_last)
return (RATE_ALPHA * mInterarrivalTime + (1.0 - RATE_ALPHA) * dt);
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 7b85a4f25cee..72c549f7bec6 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -61,6 +61,13 @@ public final class Installer extends SystemService {
mInstaller = new InstallerConnection();
}
+ // Package-private installer that accepts a custom InstallerConnection. Used for
+ // OtaDexoptService.
+ Installer(Context context, InstallerConnection connection) {
+ super(context);
+ mInstaller = connection;
+ }
+
/**
* Yell loudly if someone tries making future calls while holding a lock on
* the given object.
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 43a0b9174f8e..46da60764e7e 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -380,7 +380,8 @@ public class LauncherAppsService extends SystemService {
"To query by shortcut ID, package name must also be set");
}
- return new ParceledListSlice<>(
+ // TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below.
+ return new ParceledListSlice<>((List<ShortcutInfo>)
mShortcutServiceInternal.getShortcuts(getCallingUserId(),
callingPackage, changedSince, packageName, shortcutIds,
componentName, flags, user.getIdentifier()));
@@ -775,8 +776,7 @@ public class LauncherAppsService extends SystemService {
/* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
/* component= */ null,
ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
- | ShortcutQuery.FLAG_GET_PINNED
- | ShortcutQuery.FLAG_GET_DYNAMIC
+ | ShortcutQuery.FLAG_GET_ALL_KINDS
, userId);
try {
listener.onShortcutChanged(user, packageName,
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index df91f4a1f62a..01b3dc28b50e 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -32,10 +32,12 @@ import android.os.storage.StorageManager;
import android.util.Log;
import android.util.Slog;
+import com.android.internal.os.InstallerConnection;
import com.android.internal.os.InstallerConnection.InstallerException;
import java.io.File;
import java.io.FileDescriptor;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -49,21 +51,28 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
private final static boolean DEBUG_DEXOPT = true;
private final Context mContext;
- private final PackageDexOptimizer mPackageDexOptimizer;
private final PackageManagerService mPackageManagerService;
// TODO: Evaluate the need for WeakReferences here.
+
+ /**
+ * The list of packages to dexopt.
+ */
private List<PackageParser.Package> mDexoptPackages;
+
+ /**
+ * The list of dexopt invocations for the current package (which will no longer be in
+ * mDexoptPackages). This can be more than one as a package may have multiple code paths,
+ * e.g., in the split-APK case.
+ */
+ private List<String> mCommandsForCurrentPackage;
+
private int completeSize;
public OtaDexoptService(Context context, PackageManagerService packageManagerService) {
this.mContext = context;
this.mPackageManagerService = packageManagerService;
- // Use the package manager install and install lock here for the OTA dex optimizer.
- mPackageDexOptimizer = new OTADexoptPackageDexOptimizer(packageManagerService.mInstaller,
- packageManagerService.mInstallLock, context);
-
// Now it's time to check whether we need to move any A/B artifacts.
moveAbArtifacts(packageManagerService.mInstaller);
}
@@ -93,6 +102,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
mPackageManagerService.mPackages.values(), mPackageManagerService);
}
completeSize = mDexoptPackages.size();
+ mCommandsForCurrentPackage = null;
}
@Override
@@ -101,6 +111,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
Log.i(TAG, "Cleaning up OTA Dexopt state.");
}
mDexoptPackages = null;
+ mCommandsForCurrentPackage = null;
}
@Override
@@ -109,15 +120,109 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
throw new IllegalStateException("done() called before prepare()");
}
- return mDexoptPackages.isEmpty();
+ return mDexoptPackages.isEmpty() && (mCommandsForCurrentPackage == null);
}
@Override
public synchronized float getProgress() throws RemoteException {
+ // We approximate by number of packages here. We could track all compiles, if we
+ // generated them ahead of time. Right now we're trying to conserve memory.
if (completeSize == 0) {
return 1f;
}
- return (completeSize - mDexoptPackages.size()) / ((float)completeSize);
+ int packagesLeft = mDexoptPackages.size() + (mCommandsForCurrentPackage != null ? 1 : 0);
+ return (completeSize - packagesLeft) / ((float)completeSize);
+ }
+
+ /**
+ * Return the next dexopt command for the current package. Enforces the invariant
+ */
+ private String getNextPackageDexopt() {
+ if (mCommandsForCurrentPackage != null) {
+ String next = mCommandsForCurrentPackage.remove(0);
+ if (mCommandsForCurrentPackage.isEmpty()) {
+ mCommandsForCurrentPackage = null;
+ }
+ return next;
+ }
+ return null;
+ }
+
+ @Override
+ public synchronized String nextDexoptCommand() throws RemoteException {
+ if (mDexoptPackages == null) {
+ throw new IllegalStateException("dexoptNextPackage() called before prepare()");
+ }
+
+ // Get the next command.
+ for (;;) {
+ // Check whether there's one for the current package.
+ String next = getNextPackageDexopt();
+ if (next != null) {
+ return next;
+ }
+
+ // Move to the next package, if possible.
+ if (mDexoptPackages.isEmpty()) {
+ return "Nothing to do";
+ }
+
+ PackageParser.Package nextPackage = mDexoptPackages.remove(0);
+
+ if (DEBUG_DEXOPT) {
+ Log.i(TAG, "Processing " + nextPackage.packageName + " for OTA dexopt.");
+ }
+
+ // Generate the next mPackageDexopts state. Ignore errors, this loop is strongly
+ // monotonically increasing, anyways.
+ generatePackageDexopts(nextPackage);
+
+ // Invariant check: mPackageDexopts is null or not empty.
+ if (mCommandsForCurrentPackage != null && mCommandsForCurrentPackage.isEmpty()) {
+ cleanup();
+ throw new IllegalStateException("mPackageDexopts empty for " + nextPackage);
+ }
+ }
+ }
+
+ /**
+ * Generate all dexopt commands for the given package and place them into mPackageDexopts.
+ * Returns true on success, false in an error situation like low disk space.
+ */
+ private synchronized boolean generatePackageDexopts(PackageParser.Package nextPackage) {
+ // Check for low space.
+ // TODO: If apps are not installed in the internal /data partition, we should compare
+ // against that storage's free capacity.
+ File dataDir = Environment.getDataDirectory();
+ @SuppressWarnings("deprecation")
+ long lowThreshold = StorageManager.from(mContext).getStorageLowBytes(dataDir);
+ if (lowThreshold == 0) {
+ throw new IllegalStateException("Invalid low memory threshold");
+ }
+ long usableSpace = dataDir.getUsableSpace();
+ if (usableSpace < lowThreshold) {
+ Log.w(TAG, "Not running dexopt on " + nextPackage.packageName + " due to low memory: " +
+ usableSpace);
+ return false;
+ }
+
+ // Use our custom connection that just collects the commands.
+ RecordingInstallerConnection collectingConnection = new RecordingInstallerConnection();
+ Installer collectingInstaller = new Installer(mContext, collectingConnection);
+
+ // Use the package manager install and install lock here for the OTA dex optimizer.
+ PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
+ collectingInstaller, mPackageManagerService.mInstallLock, mContext);
+ optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles,
+ null /* ISAs */, false /* checkProfiles */,
+ getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA));
+
+ mCommandsForCurrentPackage = collectingConnection.commands;
+ if (mCommandsForCurrentPackage.isEmpty()) {
+ mCommandsForCurrentPackage = null;
+ }
+
+ return true;
}
@Override
@@ -152,8 +257,10 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
return;
}
- mPackageDexOptimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles,
- null /* ISAs */, false /* checkProfiles */,
+ PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
+ mPackageManagerService.mInstaller, mPackageManagerService.mInstallLock, mContext);
+ optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles, null /* ISAs */,
+ false /* checkProfiles */,
getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA));
}
@@ -218,4 +325,40 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
}
}
+
+ private static class RecordingInstallerConnection extends InstallerConnection {
+ public List<String> commands = new ArrayList<String>(1);
+
+ @Override
+ public void setWarnIfHeld(Object warnIfHeld) {
+ throw new IllegalStateException("Should not reach here");
+ }
+
+ @Override
+ public synchronized String transact(String cmd) {
+ commands.add(cmd);
+ return "0";
+ }
+
+ @Override
+ public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
+ throw new IllegalStateException("Should not reach here");
+ }
+
+ @Override
+ public boolean dumpProfiles(String gid, String packageName, String codePaths)
+ throws InstallerException {
+ throw new IllegalStateException("Should not reach here");
+ }
+
+ @Override
+ public void disconnect() {
+ throw new IllegalStateException("Should not reach here");
+ }
+
+ @Override
+ public void waitForConnection() {
+ throw new IllegalStateException("Should not reach here");
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java b/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java
index e8fdfa50a12d..bbd404879a21 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptShellCommand.java
@@ -46,6 +46,8 @@ class OtaDexoptShellCommand extends ShellCommand {
return runOtaDone();
case "step":
return runOtaStep();
+ case "next":
+ return runOtaNext();
case "progress":
return runOtaProgress();
default:
@@ -83,6 +85,11 @@ class OtaDexoptShellCommand extends ShellCommand {
return 0;
}
+ private int runOtaNext() throws RemoteException {
+ getOutPrintWriter().println(mInterface.nextDexoptCommand());
+ return 0;
+ }
+
private int runOtaProgress() throws RemoteException {
final float progress = mInterface.getProgress();
final PrintWriter pw = getOutPrintWriter();
@@ -103,6 +110,8 @@ class OtaDexoptShellCommand extends ShellCommand {
pw.println(" Replies whether the OTA is complete or not.");
pw.println(" step");
pw.println(" OTA dexopt the next package.");
+ pw.println(" next");
+ pw.println(" Get parameters for OTA dexopt of the next package.");
pw.println(" cleanup");
pw.println(" Clean up internal states. Ends an OTA session.");
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 410ec38bce73..114ad968d6dc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -464,7 +464,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
- private static int DEFAULT_EPHEMERAL_HASH_PREFIX_MASK = 0xFFFFFFFF;
+ private static int DEFAULT_EPHEMERAL_HASH_PREFIX_MASK = 0xFFFFF000;
private static int DEFAULT_EPHEMERAL_HASH_PREFIX_COUNT = 5;
/** Permission grant: not grant the permission. */
@@ -627,7 +627,7 @@ public class PackageManagerService extends IPackageManager.Stub {
@GuardedBy("mPackages")
final ArraySet<String> mFrozenPackages = new ArraySet<>();
- final ProtectedPackages mProtectedPackages = new ProtectedPackages();
+ final ProtectedPackages mProtectedPackages;
boolean mFirstBoot;
@@ -1219,7 +1219,9 @@ public class PackageManagerService extends IPackageManager.Stub {
StringBuffer sb = new StringBuffer();
String firstLine = readLine(in, sb);
- if (firstLine.equals(USAGE_FILE_MAGIC_VERSION_1)) {
+ if (firstLine == null) {
+ // Empty file. Do nothing.
+ } else if (USAGE_FILE_MAGIC_VERSION_1.equals(firstLine)) {
readVersion1LP(in, sb);
} else {
readVersion0LP(in, sb, firstLine);
@@ -2307,6 +2309,8 @@ public class PackageManagerService extends IPackageManager.Stub {
mSystemPermissions = systemConfig.getSystemPermissions();
mAvailableFeatures = systemConfig.getAvailableFeatures();
+ mProtectedPackages = new ProtectedPackages(mContext);
+
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
@@ -5030,7 +5034,8 @@ public class PackageManagerService extends IPackageManager.Stub {
Global.EPHEMERAL_HASH_PREFIX_MASK, DEFAULT_EPHEMERAL_HASH_PREFIX_MASK);
final int ephemeralPrefixCount = Global.getInt(mContext.getContentResolver(),
Global.EPHEMERAL_HASH_PREFIX_COUNT, DEFAULT_EPHEMERAL_HASH_PREFIX_COUNT);
- final EphemeralDigest digest = new EphemeralDigest(intent.getData(), ephemeralPrefixCount);
+ final EphemeralDigest digest = new EphemeralDigest(intent.getData(), ephemeralPrefixMask,
+ ephemeralPrefixCount);
final int[] shaPrefix = digest.getDigestPrefix();
final byte[][] digestBytes = digest.getDigestBytes();
final List<EphemeralResolveInfo> ephemeralResolveInfoList =
@@ -5042,7 +5047,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
// Go in reverse order so we match the narrowest scope first.
- for (int i = shaPrefix.length; i >= 0 ; --i) {
+ for (int i = shaPrefix.length - 1; i >= 0 ; --i) {
for (EphemeralResolveInfo ephemeralApplication : ephemeralResolveInfoList) {
if (!Arrays.equals(digestBytes[i], ephemeralApplication.getDigestBytes())) {
continue;
@@ -6792,11 +6797,26 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ private long getLastModifiedTime(PackageParser.Package pkg, File srcFile) {
+ if (srcFile.isDirectory()) {
+ final File baseFile = new File(pkg.baseCodePath);
+ long maxModifiedTime = baseFile.lastModified();
+ if (pkg.splitCodePaths != null) {
+ for (int i = pkg.splitCodePaths.length - 1; i >=0; --i) {
+ final File splitFile = new File(pkg.splitCodePaths[i]);
+ maxModifiedTime = Math.max(maxModifiedTime, splitFile.lastModified());
+ }
+ }
+ return maxModifiedTime;
+ }
+ return srcFile.lastModified();
+ }
+
private void collectCertificatesLI(PackageSetting ps, PackageParser.Package pkg, File srcFile,
final int policyFlags) throws PackageManagerException {
if (ps != null
&& ps.codePath.equals(srcFile)
- && ps.timeStamp == srcFile.lastModified()
+ && ps.timeStamp == getLastModifiedTime(pkg, srcFile)
&& !isCompatSignatureUpdateNeeded(pkg)
&& !isRecoverSignatureUpdateNeeded(pkg)) {
long mSigningKeySetId = ps.keySetData.getProperSigningKeySet();
@@ -8432,7 +8452,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final String pkgName = pkg.packageName;
- final long scanFileTime = scanFile.lastModified();
+ final long scanFileTime = getLastModifiedTime(pkg, scanFile);
final boolean forceDex = (scanFlags & SCAN_FORCE_DEX) != 0;
pkg.applicationInfo.processName = fixProcessName(
pkg.applicationInfo.packageName,
@@ -9571,6 +9591,10 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private void killApplication(String pkgName, int appId, String reason) {
+ killApplication(pkgName, appId, UserHandle.USER_ALL, reason);
+ }
+
+ private void killApplication(String pkgName, int appId, int userId, String reason) {
// Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older
// version of the application while the new one gets installed.
@@ -9579,7 +9603,7 @@ public class PackageManagerService extends IPackageManager.Stub {
IActivityManager am = ActivityManagerNative.getDefault();
if (am != null) {
try {
- am.killApplicationWithAppId(pkgName, appId, reason);
+ am.killApplication(pkgName, appId, userId, reason);
} catch (RemoteException e) {
}
}
@@ -11671,6 +11695,12 @@ public class PackageManagerService extends IPackageManager.Stub {
if (pkgSetting == null) {
return false;
}
+ // Only allow protected packages to hide themselves.
+ if (hidden && !UserHandle.isSameApp(uid, pkgSetting.appId)
+ && mProtectedPackages.isPackageStateProtected(userId, packageName)) {
+ Slog.w(TAG, "Not hiding protected package: " + packageName);
+ return false;
+ }
if (pkgSetting.getHidden(userId) != hidden) {
pkgSetting.setHidden(hidden, userId);
mSettings.writePackageRestrictionsLPr(userId);
@@ -12563,13 +12593,12 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (mSuccess) {
- final boolean mounted;
- if (Environment.isExternalStorageEmulated()) {
- mounted = true;
- } else {
+ boolean mounted = false;
+ try {
final String status = Environment.getExternalStorageState();
mounted = (Environment.MEDIA_MOUNTED.equals(status)
|| Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
+ } catch (Exception e) {
}
if (mounted) {
@@ -15171,16 +15200,13 @@ public class PackageManagerService extends IPackageManager.Stub {
}
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
// Do not run PackageDexOptimizer through the local performDexOpt
- // method because `pkg` is not in `mPackages` yet.
- int result = mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
+ // method because `pkg` may not be in `mPackages` yet.
+ //
+ // Also, don't fail application installs if the dexopt step fails.
+ mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
null /* instructionSets */, false /* checkProfiles */,
getCompilerFilterForReason(REASON_INSTALL));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
- String msg = "Extracting package failed for " + pkgName;
- res.setError(INSTALL_FAILED_DEXOPT, msg);
- return;
- }
// Notify BackgroundDexOptService that the package has been changed.
// If this is an update of a package which used to fail to compile,
@@ -15596,10 +15622,10 @@ public class PackageManagerService extends IPackageManager.Stub {
final PackageRemovedInfo info = new PackageRemovedInfo();
final boolean res;
- final UserHandle removeForUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
- ? UserHandle.ALL : new UserHandle(userId);
+ final int removeUser = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0
+ ? UserHandle.USER_ALL : userId;
- if (isPackageDeviceAdmin(packageName, removeForUser.getIdentifier())) {
+ if (isPackageDeviceAdmin(packageName, removeUser)) {
Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
}
@@ -15619,11 +15645,21 @@ public class PackageManagerService extends IPackageManager.Stub {
info.origUsers = uninstalledPs.queryInstalledUsers(allUsers, true);
}
+ final int freezeUser;
+ if (isUpdatedSystemApp(uninstalledPs)
+ && ((deleteFlags & PackageManager.DELETE_SYSTEM_APP) == 0)) {
+ // We're downgrading a system app, which will apply to all users, so
+ // freeze them all during the downgrade
+ freezeUser = UserHandle.USER_ALL;
+ } else {
+ freezeUser = removeUser;
+ }
+
synchronized (mInstallLock) {
if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
- try (PackageFreezer freezer = freezePackageForDelete(packageName, deleteFlags,
- "deletePackageX")) {
- res = deletePackageLIF(packageName, removeForUser, true, allUsers,
+ try (PackageFreezer freezer = freezePackageForDelete(packageName, freezeUser,
+ deleteFlags, "deletePackageX")) {
+ res = deletePackageLIF(packageName, UserHandle.of(removeUser), true, allUsers,
deleteFlags | REMOVE_CHATTY, info, true, null);
}
synchronized (mPackages) {
@@ -16435,8 +16471,9 @@ public class PackageManagerService extends IPackageManager.Stub {
enforceCrossUserPermission(Binder.getCallingUid(), userId,
true /* requireFullPermission */, false /* checkShell */, "clear application data");
- if (mProtectedPackages.canPackageBeWiped(userId, packageName)) {
- throw new SecurityException("Cannot clear data for a device owner or a profile owner");
+ if (mProtectedPackages.isPackageDataProtected(userId, packageName)) {
+ throw new SecurityException("Cannot clear data for a protected package: "
+ + packageName);
}
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
@@ -17762,9 +17799,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
+ Binder.getCallingPid()
+ ", uid=" + uid + ", package uid=" + pkgSetting.appId);
}
- // Don't allow changing profile and device owners.
- if (mProtectedPackages.canPackageStateBeChanged(userId, packageName)) {
- throw new SecurityException("Cannot disable a device owner or a profile owner");
+ // Don't allow changing protected packages.
+ if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
+ throw new SecurityException("Cannot disable a protected package: " + packageName);
}
}
@@ -19878,24 +19915,38 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
public PackageFreezer freezePackage(String packageName, String killReason) {
- return new PackageFreezer(packageName, killReason);
+ return freezePackage(packageName, UserHandle.USER_ALL, killReason);
+ }
+
+ public PackageFreezer freezePackage(String packageName, int userId, String killReason) {
+ return new PackageFreezer(packageName, userId, killReason);
}
public PackageFreezer freezePackageForInstall(String packageName, int installFlags,
String killReason) {
+ return freezePackageForInstall(packageName, UserHandle.USER_ALL, installFlags, killReason);
+ }
+
+ public PackageFreezer freezePackageForInstall(String packageName, int userId, int installFlags,
+ String killReason) {
if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
return new PackageFreezer();
} else {
- return freezePackage(packageName, killReason);
+ return freezePackage(packageName, userId, killReason);
}
}
public PackageFreezer freezePackageForDelete(String packageName, int deleteFlags,
String killReason) {
+ return freezePackageForDelete(packageName, UserHandle.USER_ALL, deleteFlags, killReason);
+ }
+
+ public PackageFreezer freezePackageForDelete(String packageName, int userId, int deleteFlags,
+ String killReason) {
if ((deleteFlags & PackageManager.DELETE_DONT_KILL_APP) != 0) {
return new PackageFreezer();
} else {
- return freezePackage(packageName, killReason);
+ return freezePackage(packageName, userId, killReason);
}
}
@@ -19926,14 +19977,14 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
mCloseGuard.open("close");
}
- public PackageFreezer(String packageName, String killReason) {
+ public PackageFreezer(String packageName, int userId, String killReason) {
synchronized (mPackages) {
mPackageName = packageName;
mWeFroze = mFrozenPackages.add(mPackageName);
final PackageSetting ps = mSettings.mPackages.get(mPackageName);
if (ps != null) {
- killApplication(ps.name, ps.appId, killReason);
+ killApplication(ps.name, ps.appId, userId, killReason);
}
final PackageParser.Package p = mPackages.get(packageName);
@@ -19942,7 +19993,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
mChildren = new PackageFreezer[N];
for (int i = 0; i < N; i++) {
mChildren[i] = new PackageFreezer(p.childPackages.get(i).packageName,
- killReason);
+ userId, killReason);
}
} else {
mChildren = null;
@@ -20081,7 +20132,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
seinfo = pkg.applicationInfo.seinfo;
label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo));
targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
- freezer = new PackageFreezer(packageName, "movePackageInternal");
+ freezer = freezePackage(packageName, "movePackageInternal");
installedUserIds = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
}
@@ -20882,9 +20933,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
@Override
- public boolean canPackageBeWiped(int userId, String packageName) {
- return mProtectedPackages.canPackageBeWiped(userId,
- packageName);
+ public boolean isPackageDataProtected(int userId, String packageName) {
+ return mProtectedPackages.isPackageDataProtected(userId, packageName);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 07dc404e08db..5787bdb48498 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1099,8 +1099,9 @@ class PackageManagerShellCommand extends ShellCommand {
try {
mInterface.setHomeActivity(componentName, userId);
+ pw.println("Success");
return 0;
- } catch (RemoteException e) {
+ } catch (Exception e) {
pw.println(e.toString());
return 1;
}
diff --git a/services/core/java/com/android/server/pm/ProtectedPackages.java b/services/core/java/com/android/server/pm/ProtectedPackages.java
index 7bdea181473e..e67364a26e5c 100644
--- a/services/core/java/com/android/server/pm/ProtectedPackages.java
+++ b/services/core/java/com/android/server/pm/ProtectedPackages.java
@@ -16,10 +16,15 @@
package com.android.server.pm;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.content.Context;
import android.os.UserHandle;
import android.util.SparseArray;
+import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+
/**
* Manages package names that need special protection.
*
@@ -29,61 +34,87 @@ import android.util.SparseArray;
*/
public class ProtectedPackages {
@UserIdInt
+ @GuardedBy("this")
private int mDeviceOwnerUserId;
+ @Nullable
+ @GuardedBy("this")
private String mDeviceOwnerPackage;
+ @Nullable
+ @GuardedBy("this")
private SparseArray<String> mProfileOwnerPackages;
- private final Object mLock = new Object();
+ @Nullable
+ @GuardedBy("this")
+ private final String mDeviceProvisioningPackage;
+
+ private final Context mContext;
+
+ public ProtectedPackages(Context context) {
+ mContext = context;
+ mDeviceProvisioningPackage = mContext.getResources().getString(
+ R.string.config_deviceProvisioningPackage);
+ }
/**
* Sets the device/profile owner information.
*/
- public void setDeviceAndProfileOwnerPackages(
+ public synchronized void setDeviceAndProfileOwnerPackages(
int deviceOwnerUserId, String deviceOwnerPackage,
SparseArray<String> profileOwnerPackages) {
- synchronized (mLock) {
- mDeviceOwnerUserId = deviceOwnerUserId;
- mDeviceOwnerPackage =
- (deviceOwnerUserId == UserHandle.USER_NULL) ? null : deviceOwnerPackage;
- mProfileOwnerPackages = (profileOwnerPackages == null) ? null
- : profileOwnerPackages.clone();
- }
+ mDeviceOwnerUserId = deviceOwnerUserId;
+ mDeviceOwnerPackage =
+ (deviceOwnerUserId == UserHandle.USER_NULL) ? null : deviceOwnerPackage;
+ mProfileOwnerPackages = (profileOwnerPackages == null) ? null
+ : profileOwnerPackages.clone();
}
- private boolean hasDeviceOwnerOrProfileOwner(int userId, String packageName) {
+ private synchronized boolean hasDeviceOwnerOrProfileOwner(int userId, String packageName) {
if (packageName == null) {
return false;
}
- synchronized (mLock) {
- if (mDeviceOwnerPackage != null) {
- if ((mDeviceOwnerUserId == userId)
- && (packageName.equals(mDeviceOwnerPackage))) {
- return true;
- }
+ if (mDeviceOwnerPackage != null) {
+ if ((mDeviceOwnerUserId == userId)
+ && (packageName.equals(mDeviceOwnerPackage))) {
+ return true;
}
- if (mProfileOwnerPackages != null) {
- if (packageName.equals(mProfileOwnerPackages.get(userId))) {
- return true;
- }
+ }
+ if (mProfileOwnerPackages != null) {
+ if (packageName.equals(mProfileOwnerPackages.get(userId))) {
+ return true;
}
}
return false;
}
/**
- * Whether a package or the components in a package's enabled state can be changed
- * by other callers than itself.
+ * Returns {@code true} if a given package is protected. Otherwise, returns {@code false}.
+ *
+ * <p>A protected package means that, apart from the package owner, no system or privileged apps
+ * can modify its data or package state.
+ */
+ private synchronized boolean isProtectedPackage(String packageName) {
+ return packageName != null && packageName.equals(mDeviceProvisioningPackage);
+ }
+
+ /**
+ * Returns {@code true} if a given package's state is protected. Otherwise, returns
+ * {@code false}.
+ *
+ * <p>This is not applicable if the caller is the package owner.
*/
- public boolean canPackageStateBeChanged(@UserIdInt int userId, String packageName) {
- return hasDeviceOwnerOrProfileOwner(userId, packageName);
+ public boolean isPackageStateProtected(@UserIdInt int userId, String packageName) {
+ return hasDeviceOwnerOrProfileOwner(userId, packageName)
+ || isProtectedPackage(packageName);
}
/**
- * Whether a package's data be cleared.
+ * Returns {@code true} if a given package's data is protected. Otherwise, returns
+ * {@code false}.
*/
- public boolean canPackageBeWiped(@UserIdInt int userId, String packageName) {
- return hasDeviceOwnerOrProfileOwner(userId, packageName);
+ public boolean isPackageDataProtected(@UserIdInt int userId, String packageName) {
+ return hasDeviceOwnerOrProfileOwner(userId, packageName)
+ || isProtectedPackage(packageName);
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index d637586c8def..67e4e93fdbda 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -54,8 +54,6 @@ import java.util.function.Predicate;
* User information used by {@link ShortcutService}.
*
* All methods should be guarded by {@code #mShortcutUser.mService.mLock}.
- *
- * TODO Max dynamic shortcuts cap should be per activity.
*/
class ShortcutPackage extends ShortcutPackageItem {
private static final String TAG = ShortcutService.TAG;
@@ -321,9 +319,27 @@ class ShortcutPackage extends ShortcutPackageItem {
/**
* Remove a dynamic shortcut by ID. It'll be removed from the dynamic set, but if the shortcut
* is pinned, it'll remain as a pinned shortcut, and is still enabled.
+ *
+ * @return true if it's actually removed because it wasn't pinned, or false if it's still
+ * pinned.
+ */
+ public boolean deleteDynamicWithId(@NonNull String shortcutId) {
+ final ShortcutInfo removed = deleteOrDisableWithId(
+ shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false);
+ return removed == null;
+ }
+
+ /**
+ * Disable a dynamic shortcut by ID. It'll be removed from the dynamic set, but if the shortcut
+ * is pinned, it'll remain as a pinned shortcut, but will be disabled.
+ *
+ * @return true if it's actually removed because it wasn't pinned, or false if it's still
+ * pinned.
*/
- public void deleteDynamicWithId(@NonNull String shortcutId) {
- deleteOrDisableWithId(shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false);
+ private boolean disableDynamicWithId(@NonNull String shortcutId) {
+ final ShortcutInfo disabled = deleteOrDisableWithId(
+ shortcutId, /* disable =*/ true, /* overrideImmutable=*/ false);
+ return disabled == null;
}
/**
@@ -599,14 +615,14 @@ class ShortcutPackage extends ShortcutPackageItem {
*
* @return TRUE if any shortcuts have been changed.
*/
- public boolean handlePackageAddedOrUpdated(boolean isNewApp) {
+ public boolean handlePackageAddedOrUpdated(boolean isNewApp, boolean forceRescan) {
final PackageInfo pi = mShortcutUser.mService.getPackageInfo(
getPackageName(), getPackageUserId());
if (pi == null) {
return false; // Shouldn't happen.
}
- if (!isNewApp) {
+ if (!isNewApp && !forceRescan) {
// Make sure the version code or last update time has changed.
// Otherwise, nothing to do.
if (getPackageInfo().getVersionCode() >= pi.versionCode
@@ -649,12 +665,26 @@ class ShortcutPackage extends ShortcutPackageItem {
boolean changed = false;
// For existing shortcuts, update timestamps if they have any resources.
+ // Also check if shortcuts' activities are still main activities. Otherwise, disable them.
if (!isNewApp) {
Resources publisherRes = null;
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
+ if (si.isDynamic()) {
+ if (!s.injectIsMainActivity(si.getActivity(), getPackageUserId())) {
+ Slog.w(TAG, String.format(
+ "%s is no longer main activity. Disabling shorcut %s.",
+ getPackageName(), si.getId()));
+ if (disableDynamicWithId(si.getId())) {
+ continue; // Actually removed.
+ }
+ // Still pinned, so fall-through and possibly update the resources.
+ }
+ changed = true;
+ }
+
if (si.hasAnyResources()) {
if (!si.isOriginallyFromManifest()) {
if (publisherRes == null) {
@@ -912,9 +942,8 @@ class ShortcutPackage extends ShortcutPackageItem {
final ComponentName newActivity = newShortcut.getActivity();
if (newActivity == null) {
if (operation != ShortcutService.OPERATION_UPDATE) {
- // This method may be called before validating shortcuts, so this may happen,
- // and is a caller side error.
- throw new NullPointerException("Activity must be provided");
+ service.wtf("Activity must not be null at this point");
+ continue; // Just ignore this invalid case.
}
continue; // Activity can be null for update.
}
diff --git a/services/core/java/com/android/server/pm/ShortcutParser.java b/services/core/java/com/android/server/pm/ShortcutParser.java
index c349b758b0ce..858e1cd9284b 100644
--- a/services/core/java/com/android/server/pm/ShortcutParser.java
+++ b/services/core/java/com/android/server/pm/ShortcutParser.java
@@ -21,6 +21,7 @@ import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
@@ -58,18 +59,36 @@ public class ShortcutParser {
@Nullable
public static List<ShortcutInfo> parseShortcuts(ShortcutService service,
String packageName, @UserIdInt int userId) throws IOException, XmlPullParserException {
- final PackageInfo pi = service.injectGetActivitiesWithMetadata(packageName, userId);
+ if (ShortcutService.DEBUG) {
+ Slog.d(TAG, String.format("Scanning package %s for manifest shortcuts on user %d",
+ packageName, userId));
+ }
+ final List<ResolveInfo> activities = service.injectGetMainActivities(packageName, userId);
+ if (activities == null || activities.size() == 0) {
+ return null;
+ }
List<ShortcutInfo> result = null;
try {
- if (pi != null && pi.activities != null) {
- for (ActivityInfo activityInfo : pi.activities) {
- result = parseShortcutsOneFile(service, activityInfo, packageName, userId, result);
+ final int size = activities.size();
+ for (int i = 0; i < size; i++) {
+ final ActivityInfo activityInfoNoMetadata = activities.get(i).activityInfo;
+ if (activityInfoNoMetadata == null) {
+ continue;
+ }
+
+ final ActivityInfo activityInfoWithMetadata =
+ service.injectGetActivityInfoWithMetadata(
+ activityInfoNoMetadata.getComponentName(), userId);
+ if (activityInfoWithMetadata != null) {
+ result = parseShortcutsOneFile(
+ service, activityInfoWithMetadata, packageName, userId, result);
}
}
} catch (RuntimeException e) {
- // Resource ID mismatch may cause various runtime exceptions when parsing XMLs.
+ // Resource ID mismatch may cause various runtime exceptions when parsing XMLs,
+ // But we don't crash the device, so just swallow them.
service.wtf(
"Exception caught while parsing shortcut XML for package=" + packageName, e);
return null;
@@ -81,6 +100,11 @@ public class ShortcutParser {
ShortcutService service,
ActivityInfo activityInfo, String packageName, @UserIdInt int userId,
List<ShortcutInfo> result) throws IOException, XmlPullParserException {
+ if (ShortcutService.DEBUG) {
+ Slog.d(TAG, String.format(
+ "Checking main activity %s", activityInfo.getComponentName()));
+ }
+
XmlResourceParser parser = null;
try {
parser = service.injectXmlMetaData(activityInfo, METADATA_KEY);
@@ -223,7 +247,7 @@ public class ShortcutParser {
continue;
}
- Log.w(TAG, "Unknown tag " + tag + " at depth " + depth);
+ ShortcutService.warnForInvalidTag(depth, tag);
}
} finally {
if (parser != null) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index be8eeed72825..1db1ce7432f4 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -60,6 +60,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SELinux;
+import android.os.ServiceManager;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -76,6 +77,7 @@ import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.util.TypedValue;
import android.util.Xml;
+import android.view.IWindowManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -123,28 +125,15 @@ import java.util.function.Predicate;
* - Deal with the async nature of PACKAGE_ADD. Basically when a publisher does anything after
* it's upgraded, the manager should make sure the upgrade process has been executed.
*
- * - HandleUnlockUser needs to be async. Wait on it in onCleanupUser.
- *
- * - Implement reportShortcutUsed().
- *
- * - validateForXml() should be removed.
- *
- * - Ranks should be recalculated after each update.
- *
- * - When the system locale changes, update timestamps for shortcuts with string resources,
- * and notify the launcher. Right now, it resets the throttling, but timestamps are not changed
- * and there's no notification either.
- *
* - getIconMaxWidth()/getIconMaxHeight() should use xdpi and ydpi.
+ * -> But TypedValue.applyDimension() doesn't differentiate x and y..?
*
* - Default launcher check does take a few ms. Worth caching.
*
* - Detect when already registered instances are passed to APIs again, which might break
- * internal bitmap handling.
+ * internal bitmap handling.
*
* - Add more call stats.
- *
- * - Rename mMaxDynamicShortcuts, because it includes manifest shortcuts too.
*/
public class ShortcutService extends IShortcutService.Stub {
static final String TAG = "ShortcutService";
@@ -194,6 +183,8 @@ public class ShortcutService extends IShortcutService.Stub {
private static final String ATTR_VALUE = "value";
+ private static final String LAUNCHER_INTENT_CATEGORY = Intent.CATEGORY_LAUNCHER;
+
@VisibleForTesting
interface ConfigConstants {
/**
@@ -256,9 +247,9 @@ public class ShortcutService extends IShortcutService.Stub {
private final SparseArray<ShortcutUser> mUsers = new SparseArray<>();
/**
- * Max number of dynamic shortcuts that each application can have at a time.
+ * Max number of dynamic + manifest shortcuts that each application can have at a time.
*/
- private int mMaxDynamicShortcuts;
+ private int mMaxShortcuts;
/**
* Max number of updating API calls that each application can make during the interval.
@@ -295,7 +286,8 @@ public class ShortcutService extends IShortcutService.Stub {
private List<Integer> mDirtyUserIds = new ArrayList<>();
/**
- * A counter that increments every time the system locale changes. We keep track of it to reset
+ * A counter that increments every time the system locale changes. We keep track of it to
+ * reset
* throttling counters on the first call from each package after the last locale change.
*
* We need this mechanism because we can't do much in the locale change callback, which is
@@ -307,8 +299,8 @@ public class ShortcutService extends IShortcutService.Stub {
private static final int PACKAGE_MATCH_FLAGS =
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.MATCH_UNINSTALLED_PACKAGES;
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_UNINSTALLED_PACKAGES;
// Stats
@VisibleForTesting
@@ -319,13 +311,15 @@ public class ShortcutService extends IShortcutService.Stub {
int GET_APPLICATION_INFO = 3;
int LAUNCHER_PERMISSION_CHECK = 4;
int CLEANUP_DANGLING_BITMAPS = 5;
- int GET_ACTIVITIES_WITH_METADATA = 6;
+ int GET_ACTIVITY_WITH_METADATA = 6;
int GET_INSTALLED_PACKAGES = 7;
int CHECK_PACKAGE_CHANGES = 8;
int GET_APPLICATION_RESOURCES = 9;
int RESOURCE_NAME_LOOKUP = 10;
+ int GET_LAUNCHER_ACTIVITY = 11;
+ int CHECK_LAUNCHER_ACTIVITY = 12;
- int COUNT = RESOURCE_NAME_LOOKUP + 1;
+ int COUNT = CHECK_LAUNCHER_ACTIVITY + 1;
}
final Object mStatLock = new Object();
@@ -348,9 +342,10 @@ public class ShortcutService extends IShortcutService.Stub {
OPERATION_SET,
OPERATION_ADD,
OPERATION_UPDATE
- })
+ })
@Retention(RetentionPolicy.SOURCE)
- @interface ShortcutOperation {}
+ @interface ShortcutOperation {
+ }
public ShortcutService(Context context) {
this(context, BackgroundThread.get().getLooper());
@@ -386,18 +381,22 @@ public class ShortcutService extends IShortcutService.Stub {
}
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
- @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
+ @Override
+ public void onUidStateChanged(int uid, int procState) throws RemoteException {
handleOnUidStateChanged(uid, procState);
}
- @Override public void onUidGone(int uid) throws RemoteException {
+ @Override
+ public void onUidGone(int uid) throws RemoteException {
handleOnUidStateChanged(uid, ActivityManager.MAX_PROCESS_STATE);
}
- @Override public void onUidActive(int uid) throws RemoteException {
+ @Override
+ public void onUidActive(int uid) throws RemoteException {
}
- @Override public void onUidIdle(int uid) throws RemoteException {
+ @Override
+ public void onUidIdle(int uid) throws RemoteException {
}
};
@@ -563,16 +562,16 @@ public class ShortcutService extends IShortcutService.Stub {
mMaxUpdatesPerInterval = Math.max(0, (int) parser.getLong(
ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL, DEFAULT_MAX_UPDATES_PER_INTERVAL));
- mMaxDynamicShortcuts = Math.max(0, (int) parser.getLong(
+ mMaxShortcuts = Math.max(0, (int) parser.getLong(
ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP));
final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
? (int) parser.getLong(
- ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
- DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP)
+ ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
+ DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP)
: (int) parser.getLong(
- ConfigConstants.KEY_MAX_ICON_DIMENSION_DP,
- DEFAULT_MAX_ICON_DIMENSION_DP));
+ ConfigConstants.KEY_MAX_ICON_DIMENSION_DP,
+ DEFAULT_MAX_ICON_DIMENSION_DP));
mMaxIconDimension = injectDipToPixel(iconDimensionDp);
@@ -647,15 +646,19 @@ public class ShortcutService extends IShortcutService.Stub {
@Nullable
static Intent parseIntentAttribute(XmlPullParser parser, String attribute) {
final String value = parseStringAttribute(parser, attribute);
- if (TextUtils.isEmpty(value)) {
- return null;
+ Intent parsed = null;
+ if (!TextUtils.isEmpty(value)) {
+ try {
+ parsed = Intent.parseUri(value, /* flags =*/ 0);
+ } catch (URISyntaxException e) {
+ Slog.e(TAG, "Error parsing intent", e);
+ }
}
- try {
- return Intent.parseUri(value, /* flags =*/ 0);
- } catch (URISyntaxException e) {
- Slog.e(TAG, "Error parsing intent", e);
- return null;
+ if (parsed == null) {
+ // Default intent.
+ parsed = new Intent(Intent.ACTION_VIEW);
}
+ return parsed;
}
static void writeTagValue(XmlSerializer out, String tag, String value) throws IOException {
@@ -786,7 +789,7 @@ public class ShortcutService extends IShortcutService.Stub {
}
} catch (FileNotFoundException e) {
// Use the default
- } catch (IOException|XmlPullParserException e) {
+ } catch (IOException | XmlPullParserException e) {
Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
mRawLastResetTime = 0;
@@ -809,7 +812,7 @@ public class ShortcutService extends IShortcutService.Stub {
saveUserInternalLocked(userId, os, /* forBackup= */ false);
file.finishWrite(os);
- } catch (XmlPullParserException|IOException e) {
+ } catch (XmlPullParserException | IOException e) {
Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e);
file.failWrite(os);
}
@@ -859,10 +862,10 @@ public class ShortcutService extends IShortcutService.Stub {
return null;
}
try {
- final ShortcutUser ret = loadUserInternal(userId, in, /* forBackup= */ false);
+ final ShortcutUser ret = loadUserInternal(userId, in, /* forBackup= */ false);
cleanupDanglingBitmapDirectoriesLocked(userId, ret);
return ret;
- } catch (IOException|XmlPullParserException e) {
+ } catch (IOException | XmlPullParserException e) {
Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
return null;
} finally {
@@ -1142,7 +1145,7 @@ public class ShortcutService extends IShortcutService.Stub {
}
final String baseName = String.valueOf(injectCurrentTimeMillis());
- for (int suffix = 0;; suffix++) {
+ for (int suffix = 0; ; suffix++) {
final String filename = (suffix == 0 ? baseName : baseName + "_" + suffix) + ".png";
final File file = new File(packagePath, filename);
if (!file.exists()) {
@@ -1214,7 +1217,7 @@ public class ShortcutService extends IShortcutService.Stub {
} finally {
IoUtils.closeQuietly(out);
}
- } catch (IOException|RuntimeException e) {
+ } catch (IOException | RuntimeException e) {
// STOPSHIP Change wtf to e
Slog.wtf(ShortcutService.TAG, "Unable to write bitmap to file", e);
if (path != null && path.exists()) {
@@ -1293,7 +1296,7 @@ public class ShortcutService extends IShortcutService.Stub {
private boolean isCallerSystem() {
final int callingUid = injectBinderCallingUid();
- return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID);
+ return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID);
}
private boolean isCallerShell() {
@@ -1358,10 +1361,10 @@ public class ShortcutService extends IShortcutService.Stub {
/**
* @throws IllegalArgumentException if {@code numShortcuts} is bigger than
- * {@link #getMaxActivityShortcuts()}.
+ * {@link #getMaxActivityShortcuts()}.
*/
void enforceMaxActivityShortcuts(int numShortcuts) {
- if (numShortcuts > mMaxDynamicShortcuts) {
+ if (numShortcuts > mMaxShortcuts) {
throw new IllegalArgumentException("Max number of dynamic shortcuts exceeded");
}
}
@@ -1370,7 +1373,7 @@ public class ShortcutService extends IShortcutService.Stub {
* Return the max number of dynamic + manifest shortcuts for each launcher icon.
*/
int getMaxActivityShortcuts() {
- return mMaxDynamicShortcuts;
+ return mMaxShortcuts;
}
/**
@@ -1411,7 +1414,7 @@ public class ShortcutService extends IShortcutService.Stub {
* Clean up / validate an incoming shortcut.
* - Make sure all mandatory fields are set.
* - Make sure the intent's extras are persistable, and them to set
- * {@link ShortcutInfo#mIntentPersistableExtras}. Also clear its extras.
+ * {@link ShortcutInfo#mIntentPersistableExtras}. Also clear its extras.
* - Clear flags.
*
* TODO Detailed unit tests
@@ -1421,63 +1424,43 @@ public class ShortcutService extends IShortcutService.Stub {
if (shortcut.getActivity() != null) {
Preconditions.checkState(
shortcut.getPackage().equals(shortcut.getActivity().getPackageName()),
- "Activity package name mismatch");
+ "Cannot publish shortcut: activity " + shortcut.getActivity() + " does not"
+ + " belong to package " + shortcut.getPackage());
}
if (!forUpdate) {
shortcut.enforceMandatoryFields();
+ Preconditions.checkArgument(
+ injectIsMainActivity(shortcut.getActivity(), shortcut.getUserId()),
+ "Cannot publish shortcut: " + shortcut.getActivity() + " is not main activity");
}
if (shortcut.getIcon() != null) {
ShortcutInfo.validateIcon(shortcut.getIcon());
}
- validateForXml(shortcut.getId());
- validateForXml(shortcut.getTitle());
- validatePersistableBundleForXml(shortcut.getIntentPersistableExtras());
- validatePersistableBundleForXml(shortcut.getExtras());
-
shortcut.replaceFlags(0);
}
- // KXmlSerializer is strict and doesn't allow certain characters, so we disallow those
- // characters.
+ /**
+ * When a shortcut has no target activity, set the default one from the package.
+ */
+ private void fillInDefaultActivity(List<ShortcutInfo> shortcuts) {
- private static void validatePersistableBundleForXml(PersistableBundle b) {
- if (b == null || b.size() == 0) {
- return;
- }
- for (String key : b.keySet()) {
- validateForXml(key);
- final Object value = b.get(key);
- if (value == null) {
- continue;
- } else if (value instanceof String) {
- validateForXml((String) value);
- } else if (value instanceof String[]) {
- for (String v : (String[]) value) {
- validateForXml(v);
+ ComponentName defaultActivity = null;
+ for (int i = shortcuts.size() - 1; i >= 0; i--) {
+ final ShortcutInfo si = shortcuts.get(i);
+ if (si.getActivity() == null) {
+ if (defaultActivity == null) {
+ defaultActivity = injectGetDefaultMainActivity(
+ si.getPackage(), si.getUserId());
+ Preconditions.checkState(defaultActivity != null,
+ "Launcher activity not found for package " + si.getPackage());
}
- } else if (value instanceof PersistableBundle) {
- validatePersistableBundleForXml((PersistableBundle) value);
- }
- }
- }
-
- private static void validateForXml(CharSequence s) {
- if (TextUtils.isEmpty(s)) {
- return;
- }
- for (int i = s.length() - 1; i >= 0; i--) {
- if (!isAllowedInXml(s.charAt(i))) {
- throw new IllegalArgumentException("Unsupported character detected in: " + s);
+ si.setActivity(defaultActivity);
}
}
}
- private static boolean isAllowedInXml(char c) {
- return (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
- }
-
private void assignImplicitRanks(List<ShortcutInfo> shortcuts) {
for (int i = shortcuts.size() - 1; i >= 0; i--) {
shortcuts.get(i).setImplicitRank(i);
@@ -1499,6 +1482,8 @@ public class ShortcutService extends IShortcutService.Stub {
ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
+ fillInDefaultActivity(newShortcuts);
+
ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_SET);
// Throttling.
@@ -1546,6 +1531,9 @@ public class ShortcutService extends IShortcutService.Stub {
ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
+ // For update, don't fill in the default activity. Having null activity means
+ // "don't update the activity" here.
+
ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_UPDATE);
// Throttling.
@@ -1626,6 +1614,8 @@ public class ShortcutService extends IShortcutService.Stub {
ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
+ fillInDefaultActivity(newShortcuts);
+
ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_ADD);
// Initialize the implicit ranks for ShortcutPackage.adjustRanks().
@@ -1784,11 +1774,11 @@ public class ShortcutService extends IShortcutService.Stub {
}
@Override
- public int getMaxDynamicShortcutCount(String packageName, @UserIdInt int userId)
+ public int getMaxShortcutCountForActivity(String packageName, @UserIdInt int userId)
throws RemoteException {
verifyCaller(packageName, userId);
- return mMaxDynamicShortcuts;
+ return mMaxShortcuts;
}
@Override
@@ -1848,7 +1838,8 @@ public class ShortcutService extends IShortcutService.Stub {
}
/**
- * Reset all throttling, for developer options and command line. Only system/shell can call it.
+ * Reset all throttling, for developer options and command line. Only system/shell can call
+ * it.
*/
@Override
public void resetThrottling() {
@@ -1970,10 +1961,12 @@ public class ShortcutService extends IShortcutService.Stub {
// === House keeping ===
- private void cleanUpPackageForAllLoadedUsers(String packageName, @UserIdInt int packageUserId) {
+ private void cleanUpPackageForAllLoadedUsers(String packageName, @UserIdInt int packageUserId,
+ boolean appStillExists) {
synchronized (mLock) {
forEachLoadedUserLocked(user ->
- cleanUpPackageLocked(packageName, user.getUserId(), packageUserId));
+ cleanUpPackageLocked(packageName, user.getUserId(), packageUserId,
+ appStillExists));
}
}
@@ -1985,7 +1978,8 @@ public class ShortcutService extends IShortcutService.Stub {
* This is called when an app is uninstalled, or an app gets "clear data"ed.
*/
@VisibleForTesting
- void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) {
+ void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId,
+ boolean appStillExists) {
final boolean wasUserLoaded = isUserLoadedLocked(owningUserId);
final ShortcutUser user = getUserShortcutsLocked(owningUserId);
@@ -2014,6 +2008,13 @@ public class ShortcutService extends IShortcutService.Stub {
notifyListeners(packageName, owningUserId);
}
+ // If the app still exists (i.e. data cleared), we need to re-publish manifest shortcuts.
+ if (appStillExists && (packageUserId == owningUserId)) {
+ // This will do the notification and save when needed, so do it after the above
+ // notifyListeners.
+ user.handlePackageAddedOrUpdated(packageName, /* forceRescan=*/ true);
+ }
+
if (!wasUserLoaded) {
// Note this will execute the scheduled save.
unloadUserLocked(owningUserId);
@@ -2322,19 +2323,29 @@ public class ShortcutService extends IShortcutService.Stub {
public void onPackageDataCleared(String packageName, int uid) {
handlePackageDataCleared(packageName, getChangingUserId());
}
+
+ @Override
+ public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ handlePackageChanged(packageName, getChangingUserId());
+ return false; // We don't need to receive onSomePackagesChanged(), so just false.
+ }
};
/**
* Called when a user is unlocked.
* - Check all known packages still exist, and otherwise perform cleanup.
* - If a package still exists, check the version code. If it's been updated, may need to
- * update timestamps of its shortcuts.
+ * update timestamps of its shortcuts.
*/
@VisibleForTesting
void checkPackageChanges(@UserIdInt int ownerUserId) {
if (DEBUG) {
Slog.d(TAG, "checkPackageChanges() ownerUserId=" + ownerUserId);
}
+ if (injectIsSafeModeEnabled()) {
+ Slog.i(TAG, "Safe mode, skipping checkPackageChanges()");
+ return;
+ }
final long start = injectElapsedRealtime();
try {
@@ -2355,14 +2366,15 @@ public class ShortcutService extends IShortcutService.Stub {
if (gonePackages.size() > 0) {
for (int i = gonePackages.size() - 1; i >= 0; i--) {
final PackageWithUser pu = gonePackages.get(i);
- cleanUpPackageLocked(pu.packageName, ownerUserId, pu.userId);
+ cleanUpPackageLocked(pu.packageName, ownerUserId, pu.userId,
+ /* appStillExists = */ false);
}
}
final long now = injectCurrentTimeMillis();
// Then for each installed app, publish manifest shortcuts when needed.
forUpdatedPackages(ownerUserId, user.getLastAppScanTime(), ai -> {
- user.handlePackageAddedOrUpdated(ai.packageName);
+ user.handlePackageAddedOrUpdated(ai.packageName, /* forceRescan=*/ false);
});
// Write the time just before the scan, because there may be apps that have just
@@ -2383,7 +2395,7 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
final ShortcutUser user = getUserShortcutsLocked(userId);
user.attemptToRestoreIfNeededAndSave(this, packageName, userId);
- user.handlePackageAddedOrUpdated(packageName);
+ user.handlePackageAddedOrUpdated(packageName, /* forceRescan=*/ false);
}
verifyStates();
}
@@ -2398,7 +2410,7 @@ public class ShortcutService extends IShortcutService.Stub {
user.attemptToRestoreIfNeededAndSave(this, packageName, userId);
if (isPackageInstalled(packageName, userId)) {
- user.handlePackageAddedOrUpdated(packageName);
+ user.handlePackageAddedOrUpdated(packageName, /* forceRescan=*/ false);
}
}
verifyStates();
@@ -2409,7 +2421,7 @@ public class ShortcutService extends IShortcutService.Stub {
Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName,
packageUserId));
}
- cleanUpPackageForAllLoadedUsers(packageName, packageUserId);
+ cleanUpPackageForAllLoadedUsers(packageName, packageUserId, /* appStillExists = */ false);
verifyStates();
}
@@ -2419,7 +2431,23 @@ public class ShortcutService extends IShortcutService.Stub {
Slog.d(TAG, String.format("handlePackageDataCleared: %s user=%d", packageName,
packageUserId));
}
- cleanUpPackageForAllLoadedUsers(packageName, packageUserId);
+ cleanUpPackageForAllLoadedUsers(packageName, packageUserId, /* appStillExists = */ true);
+
+ verifyStates();
+ }
+
+ private void handlePackageChanged(String packageName, int packageUserId) {
+ if (DEBUG) {
+ Slog.d(TAG, String.format("handlePackageChanged: %s user=%d", packageName,
+ packageUserId));
+ }
+
+ // Activities may be disabled or enabled. Just rescan the package.
+ synchronized (mLock) {
+ final ShortcutUser user = getUserShortcutsLocked(packageUserId);
+
+ user.handlePackageAddedOrUpdated(packageName, /* forceRescan=*/ true);
+ }
verifyStates();
}
@@ -2458,7 +2486,7 @@ public class ShortcutService extends IShortcutService.Stub {
final long token = injectClearCallingIdentity();
try {
return mIPackageManager.getPackageInfo(packageName, PACKAGE_MATCH_FLAGS
- | (getSignatures ? PackageManager.GET_SIGNATURES : 0)
+ | (getSignatures ? PackageManager.GET_SIGNATURES : 0)
, userId);
} catch (RemoteException e) {
// Shouldn't happen.
@@ -2492,14 +2520,12 @@ public class ShortcutService extends IShortcutService.Stub {
}
@Nullable
- @VisibleForTesting
- PackageInfo injectGetActivitiesWithMetadata(String packageName, @UserIdInt int userId) {
+ ActivityInfo injectGetActivityInfoWithMetadata(ComponentName activity, @UserIdInt int userId) {
final long start = injectElapsedRealtime();
final long token = injectClearCallingIdentity();
try {
- return mIPackageManager.getPackageInfo(packageName,
- PACKAGE_MATCH_FLAGS | PackageManager.GET_ACTIVITIES
- | PackageManager.GET_META_DATA, userId);
+ return mIPackageManager.getActivityInfo(activity,
+ PACKAGE_MATCH_FLAGS | PackageManager.GET_META_DATA, userId);
} catch (RemoteException e) {
// Shouldn't happen.
Slog.wtf(TAG, "RemoteException", e);
@@ -2507,7 +2533,7 @@ public class ShortcutService extends IShortcutService.Stub {
} finally {
injectRestoreCallingIdentity(token);
- logDurationStat(Stats.GET_ACTIVITIES_WITH_METADATA, start);
+ logDurationStat(Stats.GET_ACTIVITY_WITH_METADATA, start);
}
}
@@ -2584,6 +2610,86 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
+ private Intent getMainActivityIntent() {
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(LAUNCHER_INTENT_CATEGORY);
+ return intent;
+ }
+
+ @Nullable
+ ComponentName injectGetDefaultMainActivity(@NonNull String packageName, int userId) {
+ final long start = injectElapsedRealtime();
+ final long token = injectClearCallingIdentity();
+ try {
+ final Intent intent = getMainActivityIntent();
+ intent.setPackage(packageName);
+
+ final List<ResolveInfo> resolved =
+ mContext.getPackageManager().queryIntentActivitiesAsUser(
+ intent, PACKAGE_MATCH_FLAGS, userId);
+
+ return (resolved == null || resolved.size() == 0)
+ ? null : resolved.get(0).activityInfo.getComponentName();
+ } finally {
+ injectRestoreCallingIdentity(token);
+
+ logDurationStat(Stats.GET_LAUNCHER_ACTIVITY, start);
+ }
+ }
+
+ boolean injectIsMainActivity(@NonNull ComponentName activity, int userId) {
+ final long start = injectElapsedRealtime();
+ final long token = injectClearCallingIdentity();
+ try {
+ final Intent intent = getMainActivityIntent();
+ intent.setPackage(activity.getPackageName());
+ intent.setComponent(activity);
+
+ final List<ResolveInfo> resolved =
+ mContext.getPackageManager().queryIntentActivitiesAsUser(
+ intent, PACKAGE_MATCH_FLAGS, userId);
+
+ return resolved != null && resolved.size() > 0;
+ } finally {
+ injectRestoreCallingIdentity(token);
+
+ logDurationStat(Stats.CHECK_LAUNCHER_ACTIVITY, start);
+ }
+ }
+
+ @NonNull
+ List<ResolveInfo> injectGetMainActivities(@NonNull String packageName, int userId) {
+ final long start = injectElapsedRealtime();
+ final long token = injectClearCallingIdentity();
+ try {
+ final Intent intent = getMainActivityIntent();
+ intent.setPackage(packageName);
+
+ final List<ResolveInfo> resolved =
+ mContext.getPackageManager().queryIntentActivitiesAsUser(
+ intent, PACKAGE_MATCH_FLAGS, userId);
+
+ return (resolved != null) ? resolved : new ArrayList<>(0);
+ } finally {
+ injectRestoreCallingIdentity(token);
+
+ logDurationStat(Stats.CHECK_LAUNCHER_ACTIVITY, start);
+ }
+ }
+
+ boolean injectIsSafeModeEnabled() {
+ final long token = injectClearCallingIdentity();
+ try {
+ return IWindowManager.Stub
+ .asInterface(ServiceManager.getService(Context.WINDOW_SERVICE))
+ .isSafeModeEnabled();
+ } catch (RemoteException e) {
+ return false; // Shouldn't happen though.
+ } finally {
+ injectRestoreCallingIdentity(token);
+ }
+ }
+
// === Backup & restore ===
boolean shouldBackupApp(String packageName, int userId) {
@@ -2613,7 +2719,7 @@ public class ShortcutService extends IShortcutService.Stub {
final ByteArrayOutputStream os = new ByteArrayOutputStream(32 * 1024);
try {
saveUserInternalLocked(userId, os, /* forBackup */ true);
- } catch (XmlPullParserException|IOException e) {
+ } catch (XmlPullParserException | IOException e) {
// Shouldn't happen.
Slog.w(TAG, "Backup failed.", e);
return null;
@@ -2632,7 +2738,7 @@ public class ShortcutService extends IShortcutService.Stub {
final ByteArrayInputStream is = new ByteArrayInputStream(payload);
try {
user = loadUserInternal(userId, is, /* fromBackup */ true);
- } catch (XmlPullParserException|IOException e) {
+ } catch (XmlPullParserException | IOException e) {
Slog.w(TAG, "Restoration failed.", e);
return;
}
@@ -2709,8 +2815,8 @@ public class ShortcutService extends IShortcutService.Stub {
pw.println(mResetInterval);
pw.print(" maxUpdatesPerInterval: ");
pw.println(mMaxUpdatesPerInterval);
- pw.print(" maxDynamicShortcuts: ");
- pw.println(mMaxDynamicShortcuts);
+ pw.print(" maxShortcutsPerActivity: ");
+ pw.println(mMaxShortcuts);
pw.println();
pw.println(" Stats:");
@@ -2723,11 +2829,13 @@ public class ShortcutService extends IShortcutService.Stub {
dumpStatLS(pw, p, Stats.GET_PACKAGE_INFO_WITH_SIG, "getPackageInfo(SIG)");
dumpStatLS(pw, p, Stats.GET_APPLICATION_INFO, "getApplicationInfo");
dumpStatLS(pw, p, Stats.CLEANUP_DANGLING_BITMAPS, "cleanupDanglingBitmaps");
- dumpStatLS(pw, p, Stats.GET_ACTIVITIES_WITH_METADATA, "getActivities+metadata");
+ dumpStatLS(pw, p, Stats.GET_ACTIVITY_WITH_METADATA, "getActivity+metadata");
dumpStatLS(pw, p, Stats.GET_INSTALLED_PACKAGES, "getInstalledPackages");
dumpStatLS(pw, p, Stats.CHECK_PACKAGE_CHANGES, "checkPackageChanges");
dumpStatLS(pw, p, Stats.GET_APPLICATION_RESOURCES, "getApplicationResources");
dumpStatLS(pw, p, Stats.RESOURCE_NAME_LOOKUP, "resourceNameLookup");
+ dumpStatLS(pw, p, Stats.GET_LAUNCHER_ACTIVITY, "getLauncherActivity");
+ dumpStatLS(pw, p, Stats.CHECK_LAUNCHER_ACTIVITY, "checkLauncherActivity");
}
for (int i = 0; i < mUsers.size(); i++) {
@@ -2778,7 +2886,9 @@ public class ShortcutService extends IShortcutService.Stub {
enforceShell();
- (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver);
+ final int status = (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver);
+
+ resultReceiver.send(status, null);
}
static class CommandException extends Exception {
@@ -2849,6 +2959,9 @@ public class ShortcutService extends IShortcutService.Stub {
case "clear-shortcuts":
handleClearShortcuts();
break;
+ case "verify-states": // hidden command to verify various internal states.
+ handleVerifyStates();
+ break;
default:
return handleDefaultCommands(cmd);
}
@@ -2991,7 +3104,16 @@ public class ShortcutService extends IShortcutService.Stub {
Slog.i(TAG, "cmd: handleClearShortcuts: " + mUserId + ", " + packageName);
- ShortcutService.this.cleanUpPackageForAllLoadedUsers(packageName, mUserId);
+ ShortcutService.this.cleanUpPackageForAllLoadedUsers(packageName, mUserId,
+ /* appStillExists = */ true);
+ }
+
+ private void handleVerifyStates() throws CommandException {
+ try {
+ verifyStatesForce(); // This will throw when there's an issue.
+ } catch (Throwable th) {
+ throw new CommandException(th.getMessage() + "\n" + Log.getStackTraceString(th));
+ }
}
}
@@ -3031,7 +3153,7 @@ public class ShortcutService extends IShortcutService.Stub {
}
final void wtf(String message) {
- wtf( message, /* exception= */ null);
+ wtf(message, /* exception= */ null);
}
// Injection point.
@@ -3077,8 +3199,8 @@ public class ShortcutService extends IShortcutService.Stub {
}
@VisibleForTesting
- int getMaxDynamicShortcutsForTest() {
- return mMaxDynamicShortcuts;
+ int getMaxShortcutsForTest() {
+ return mMaxShortcuts;
}
@VisibleForTesting
@@ -3145,6 +3267,10 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
+ private final void verifyStatesForce() {
+ verifyStatesInner();
+ }
+
private void verifyStatesInner() {
synchronized (this) {
forEachLoadedUserLocked(u -> u.forAllPackageItems(ShortcutPackageItem::verifyStates));
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index f8ee3251055b..7ea89c9e8fcd 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -88,7 +88,7 @@ class ShortcutUser {
@Override
public String toString() {
- return String.format("{Package: %d, %s}", userId, packageName);
+ return String.format("[Package: %d, %s]", userId, packageName);
}
}
@@ -99,8 +99,6 @@ class ShortcutUser {
private final ArrayMap<String, ShortcutPackage> mPackages = new ArrayMap<>();
- private final SparseArray<ShortcutPackage> mPackagesFromUid = new SparseArray<>();
-
private final ArrayMap<PackageWithUser, ShortcutLauncher> mLaunchers = new ArrayMap<>();
/** Default launcher that can access the launcher apps APIs. */
@@ -244,12 +242,12 @@ class ShortcutUser {
}
}
- public void handlePackageAddedOrUpdated(@NonNull String packageName) {
+ public void handlePackageAddedOrUpdated(@NonNull String packageName, boolean forceRescan) {
final boolean isNewApp = !mPackages.containsKey(packageName);
final ShortcutPackage shortcutPackage = getPackageShortcuts(packageName);
- if (!shortcutPackage.handlePackageAddedOrUpdated(isNewApp)) {
+ if (!shortcutPackage.handlePackageAddedOrUpdated(isNewApp, forceRescan)) {
if (isNewApp) {
mPackages.remove(packageName);
}
@@ -381,8 +379,10 @@ class ShortcutUser {
pw.print(mUserId);
pw.print(" Known locale seq#: ");
pw.print(mKnownLocaleChangeSequenceNumber);
- pw.print(" Last app scan: ");
+ pw.print(" Last app scan: [");
pw.print(mLastAppScanTime);
+ pw.print("] ");
+ pw.print(ShortcutService.formatTime(mLastAppScanTime));
pw.println();
prefix += prefix + " ";
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 02a2b2c69282..bbffd328eecd 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -456,7 +456,6 @@ public class UserManagerService extends IUserManager.Stub {
setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, currentGuestUser.id);
}
- maybeInitializeDemoMode(UserHandle.USER_SYSTEM);
mContext.registerReceiver(mDisableQuietModeCallback,
new IntentFilter(ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK),
null, mHandler);
@@ -471,6 +470,8 @@ public class UserManagerService extends IUserManager.Stub {
UserInfo ui = mUsers.valueAt(i).info;
if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) {
partials.add(ui);
+ mRemovingUserIds.append(ui.id, true);
+ ui.partial = true;
}
}
}
@@ -737,9 +738,9 @@ public class UserManagerService extends IUserManager.Stub {
long identity = Binder.clearCallingIdentity();
try {
if (enableQuietMode) {
+ ActivityManagerNative.getDefault().stopUser(userHandle, /* force */true, null);
LocalServices.getService(ActivityManagerInternal.class)
.killForegroundAppsForUser(userHandle);
- ActivityManagerNative.getDefault().stopUser(userHandle, /* force */true, null);
} else {
ActivityManagerNative.getDefault().startUserInBackground(userHandle);
}
@@ -867,12 +868,25 @@ public class UserManagerService extends IUserManager.Stub {
}
}
synchronized (mUsersLock) {
- UserInfo userInfo = getUserInfoLU(userId);
+ UserInfo userInfo = getUserInfoLU(userId);
return userInfo != null && userInfo.isManagedProfile();
}
}
@Override
+ public boolean isDemoUser(int userId) {
+ int callingUserId = UserHandle.getCallingUserId();
+ if (callingUserId != userId && !hasManageUsersPermission()) {
+ throw new SecurityException("You need MANAGE_USERS permission to query if u=" + userId
+ + " is a demo user");
+ }
+ synchronized (mUsersLock) {
+ UserInfo userInfo = getUserInfoLU(userId);
+ return userInfo != null && userInfo.isDemo();
+ }
+ }
+
+ @Override
public boolean isRestricted() {
synchronized (mUsersLock) {
return getUserInfoLU(UserHandle.getCallingUserId()).isRestricted();
@@ -1308,14 +1322,16 @@ public class UserManagerService extends IUserManager.Stub {
}
if (mAppOpsService != null) { // We skip it until system-ready.
- final long token = Binder.clearCallingIdentity();
- try {
- mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId);
- } catch (RemoteException e) {
- Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
+ }
+ }
+ });
}
propagateUserRestrictionsLR(userId, effective, prevAppliedRestrictions);
@@ -2897,7 +2913,7 @@ public class UserManagerService extends IUserManager.Stub {
}
private void maybeInitializeDemoMode(int userId) {
- if (UserManager.isDeviceInDemoMode(mContext)) {
+ if (UserManager.isDeviceInDemoMode(mContext) && userId != UserHandle.USER_SYSTEM) {
String demoLauncher =
mContext.getResources().getString(
com.android.internal.R.string.config_demoModeLauncherComponent);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f9f0fd948e4a..22521b916ba8 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5718,14 +5718,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
break;
}
- case KeyEvent.KEYCODE_FP_NAV_DOWN:
+ case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
// fall through
- case KeyEvent.KEYCODE_FP_NAV_UP:
+ case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
// fall through
- case KeyEvent.KEYCODE_FP_NAV_LEFT:
+ case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
// fall through
- case KeyEvent.KEYCODE_FP_NAV_RIGHT: {
- interceptStatusBarKey(event);
+ case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
+ result &= ~ACTION_PASS_TO_USER;
+ interceptSystemNavigationKey(event);
break;
}
@@ -5853,21 +5854,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* Handle statusbar expansion events.
* @param event
*/
- private void interceptStatusBarKey(KeyEvent event) {
- final int e = event.getKeyCode();
+ private void interceptSystemNavigationKey(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) {
- boolean doOpen = false;
- boolean doClose = false;
- doOpen = (e == KeyEvent.KEYCODE_FP_NAV_DOWN);
- doClose = (e == KeyEvent.KEYCODE_FP_NAV_UP);
IStatusBarService sbar = getStatusBarService();
if (sbar != null) {
try {
- if (doOpen) {
- sbar.expandNotificationsPanel();
- } else if (doClose) {
- sbar.collapsePanels();
- }
+ sbar.handleSystemNavigationKey(event.getKeyCode());
} catch (RemoteException e1) {
// oops, no statusbar. Ignore event.
}
@@ -7268,7 +7260,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private boolean areSystemNavigationKeysEnabled() {
return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.SYSTEM_NAVIGATION_KEYS_ENABLED, 0) == 1;
+ Settings.Global.SYSTEM_NAVIGATION_KEYS_ENABLED, 1) == 1;
}
@Override
@@ -7670,6 +7662,34 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
+ public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
+ // For the upside down rotation we don't rotate seamlessly as the navigation
+ // bar moves position.
+ // Note most apps (using orientation:sensor or user as opposed to fullSensor)
+ // will not enter the reverse portrait orientation, so actually the
+ // orientation won't change at all.
+ if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
+ return false;
+ }
+ int delta = newRotation - oldRotation;
+ if (delta < 0) delta += 4;
+ // Likewise we don't rotate seamlessly for 180 degree rotations
+ // in this case the surfaces never resize, and our logic to
+ // revert the transformations on size change will fail. We could
+ // fix this in the future with the "tagged" frames idea.
+ if (delta == Surface.ROTATION_180) {
+ return false;
+ }
+
+ if (mTopFullscreenOpaqueWindowState != null && mTopIsFullscreen &&
+ mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation ==
+ ROTATION_ANIMATION_JUMPCUT) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
public void dump(String prefix, PrintWriter pw, String[] args) {
pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
pw.print(" mSystemReady="); pw.print(mSystemReady);
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 3ed6ec90e845..9ccfd67980f5 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -18,12 +18,12 @@ package com.android.server.power;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
+import android.app.RetailDemoModeServiceInternal;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
-import com.android.server.am.RetailDemoModeServiceInternal;
import android.app.ActivityManagerNative;
import android.content.BroadcastReceiver;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index baa7f1e38e44..ca92b907686c 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -31,6 +31,8 @@ import android.os.ResultReceiver;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;
+import android.view.KeyEvent;
+
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
@@ -415,6 +417,18 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
}
@Override
+ public void handleSystemNavigationKey(int key) throws RemoteException {
+ enforceExpandStatusBar();
+
+ if (mBar != null) {
+ try {
+ mBar.handleSystemNavigationKey(key);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
+ @Override
public void disable(int what, IBinder token, String pkg) {
disableForUser(what, token, pkg, mCurrentUserId);
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index efd238201e7a..7c2ba1eaaac1 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -906,10 +906,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
public void onForegroundProfileSwitch(int newProfileId) {
// Ignore.
}
- });
+ }, TAG);
} catch (RemoteException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ e.rethrowAsRuntimeException();
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index b907da666fea..b9cb38b242c0 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -134,6 +134,9 @@ class AppWindowToken extends WindowToken {
boolean mAppStopped;
int mPendingRelaunchCount;
+ private ArrayList<WindowSurfaceController.SurfaceControlWithBackground> mSurfaceViewBackgrounds =
+ new ArrayList<WindowSurfaceController.SurfaceControlWithBackground>();
+
ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
@@ -625,6 +628,16 @@ class AppWindowToken extends WindowToken {
}
}
+ void clearRelaunching() {
+ if (mPendingRelaunchCount == 0) {
+ return;
+ }
+ if (canFreezeBounds()) {
+ unfreezeBounds();
+ }
+ mPendingRelaunchCount = 0;
+ }
+
void addWindow(WindowState w) {
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
WindowState candidate = allAppWindows.get(i);
@@ -704,8 +717,12 @@ class AppWindowToken extends WindowToken {
* Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
*/
private void unfreezeBounds() {
- mFrozenBounds.remove();
- mFrozenMergedConfig.remove();
+ if (!mFrozenBounds.isEmpty()) {
+ mFrozenBounds.remove();
+ }
+ if (!mFrozenMergedConfig.isEmpty()) {
+ mFrozenMergedConfig.remove();
+ }
for (int i = windows.size() - 1; i >= 0; i--) {
final WindowState win = windows.get(i);
if (!win.mHasSurface) {
@@ -720,6 +737,36 @@ class AppWindowToken extends WindowToken {
service.mWindowPlacerLocked.performSurfacePlacement();
}
+ void addSurfaceViewBackground(WindowSurfaceController.SurfaceControlWithBackground background) {
+ mSurfaceViewBackgrounds.add(background);
+ }
+
+ void removeSurfaceViewBackground(WindowSurfaceController.SurfaceControlWithBackground background) {
+ mSurfaceViewBackgrounds.remove(background);
+ updateSurfaceViewBackgroundVisibilities();
+ }
+
+ // We use DimLayers behind SurfaceViews to prevent holes while resizing and creating.
+ // However, we need to ensure one SurfaceView doesn't cover another when they are both placed
+ // below the main app window (as traditionally a SurfaceView which is never drawn
+ // to is totally translucent). So we look at all our SurfaceView backgrounds and only enable
+ // the background for the SurfaceView with lowest Z order
+ void updateSurfaceViewBackgroundVisibilities() {
+ WindowSurfaceController.SurfaceControlWithBackground bottom = null;
+ int bottomLayer = Integer.MAX_VALUE;
+ for (int i = 0; i < mSurfaceViewBackgrounds.size(); i++) {
+ WindowSurfaceController.SurfaceControlWithBackground sc = mSurfaceViewBackgrounds.get(i);
+ if (sc.mVisible && sc.mLayer < bottomLayer) {
+ bottomLayer = sc.mLayer;
+ bottom = sc;
+ }
+ }
+ for (int i = 0; i < mSurfaceViewBackgrounds.size(); i++) {
+ WindowSurfaceController.SurfaceControlWithBackground sc = mSurfaceViewBackgrounds.get(i);
+ sc.updateBackgroundVisibility(sc != bottom);
+ }
+ }
+
@Override
void dump(PrintWriter pw, String prefix) {
super.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 88028befdf1e..18f97a7f606f 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -479,6 +479,8 @@ class WallpaperController {
boolean resetTopWallpaper = false;
boolean inFreeformSpace = false;
boolean replacing = false;
+ boolean keyguardGoingAwayWithWallpaper = false;
+
for (int i = windows.size() - 1; i >= 0; i--) {
w = windows.get(i);
if ((w.mAttrs.type == TYPE_WALLPAPER)) {
@@ -506,13 +508,11 @@ class WallpaperController {
inFreeformSpace = stack != null && stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
}
- replacing = replacing || w.mWillReplaceWindow;
+ replacing |= w.mWillReplaceWindow;
+ keyguardGoingAwayWithWallpaper |= (w.mAppToken != null
+ && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper);
- // If the app is executing an animation because the keyguard is going away (and the
- // keyguard was showing the wallpaper) keep the wallpaper during the animation so it
- // doesn't flicker out.
- final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0
- || (w.mAppToken != null && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper);
+ final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w);
result.setWallpaperTarget(w, i);
@@ -529,18 +529,26 @@ class WallpaperController {
}
}
- if (result.wallpaperTarget == null && windowDetachedI >= 0) {
+ if (result.wallpaperTarget != null) {
+ return;
+ }
+
+ if (windowDetachedI >= 0) {
if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
"Found animating detached wallpaper activity: #" + windowDetachedI + "=" + w);
result.setWallpaperTarget(w, windowDetachedI);
- }
- if (result.wallpaperTarget == null
- && (inFreeformSpace || (replacing && mWallpaperTarget != null))) {
+ } else if (inFreeformSpace || (replacing && mWallpaperTarget != null)) {
// In freeform mode we set the wallpaper as its own target, so we don't need an
// additional window to make it visible. When we are replacing a window and there was
// wallpaper before replacement, we want to keep the window until the new windows fully
// appear and can determine the visibility, to avoid flickering.
result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
+
+ } else if (keyguardGoingAwayWithWallpaper) {
+ // If the app is executing an animation because the keyguard is going away (and the
+ // keyguard was showing the wallpaper) keep the wallpaper during the animation so it
+ // doesn't flicker out by having it be its own target.
+ result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 36875123d42c..84173d26ef8b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -41,8 +41,10 @@ import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
+import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
@@ -291,6 +293,9 @@ public class WindowManagerService extends IWindowManager.Stub
/** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
+ /** Amount of time (in milliseconds) to delay before declaring a seamless rotation timeout. */
+ static final int SEAMLESS_ROTATION_TIMEOUT_DURATION = 2000;
+
/** Amount of time (in milliseconds) to delay before declaring a window replacement timeout. */
static final int WINDOW_REPLACEMENT_TIMEOUT_DURATION = 2000;
@@ -516,6 +521,9 @@ public class WindowManagerService extends IWindowManager.Stub
final Rect mTmpRect = new Rect();
final Rect mTmpRect2 = new Rect();
final Rect mTmpRect3 = new Rect();
+ final RectF mTmpRectF = new RectF();
+
+ final Matrix mTmpTransform = new Matrix();
boolean mDisplayReady;
boolean mSafeMode;
@@ -2995,7 +3003,8 @@ public class WindowManagerService extends IWindowManager.Stub
if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
}
- if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
+ if (win.isWinVisibleLw() && (winAnimator.isAnimationSet() ||
+ winAnimator.applyAnimationLocked(transit, false))) {
focusMayChange = isDefaultDisplay;
win.mAnimatingExit = true;
win.mWinAnimator.mAnimating = true;
@@ -3161,6 +3170,7 @@ public class WindowManagerService extends IWindowManager.Stub
// frozen, there is no reason to animate and it can cause strange
// artifacts when we unfreeze the display if some different animation
// is running.
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
if (okToDisplay()) {
DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
final int width = displayInfo.appWidth;
@@ -3212,6 +3222,7 @@ public class WindowManagerService extends IWindowManager.Stub
} else {
atoken.mAppAnimator.clearAnimation();
}
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
return atoken.mAppAnimator.animation != null;
}
@@ -3510,6 +3521,13 @@ public class WindowManagerService extends IWindowManager.Stub
// can re-appear and inflict its own orientation on us. Keep the
// orientation stable until this all settles down.
return mLastWindowForcedOrientation;
+ } else if (mPolicy.isKeyguardLocked()
+ && mLastKeyguardForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
+ // Use the last orientation the keyguard forced while the display is frozen with the
+ // keyguard locked.
+ if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
+ + "return " + mLastKeyguardForcedOrientation);
+ return mLastKeyguardForcedOrientation;
}
} else {
// TODO(multidisplay): Change to the correct display.
@@ -6567,6 +6585,7 @@ public class WindowManagerService extends IWindowManager.Stub
Binder.restoreCallingIdentity(origId);
}
+
// TODO(multidisplay): Rotate any display?
/**
* Updates the current rotation.
@@ -6626,6 +6645,8 @@ public class WindowManagerService extends IWindowManager.Stub
+ ", forceApp=" + mForcedAppOrientation);
}
+ int oldRotation = mRotation;
+
mRotation = rotation;
mAltOrientation = altOrientation;
mPolicy.setRotationLw(mRotation);
@@ -6642,10 +6663,32 @@ public class WindowManagerService extends IWindowManager.Stub
} else {
mPolicy.selectRotationAnimationLw(anim);
}
- startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
- // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
- screenRotationAnimation =
+ boolean rotateSeamlessly = mPolicy.shouldRotateSeamlessly(oldRotation, mRotation);
+ final WindowList windows = displayContent.getWindowList();
+ // We can't rotate seamlessly while an existing seamless rotation is still
+ // waiting on windows to finish drawing.
+ if (rotateSeamlessly) {
+ for (int i = windows.size() - 1; i >= 0; i--) {
+ WindowState w = windows.get(i);
+ if (w.mSeamlesslyRotated) {
+ rotateSeamlessly = false;
+ break;
+ }
+ }
+ }
+
+ if (!rotateSeamlessly) {
+ startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
+ // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
+ screenRotationAnimation =
mAnimator.getScreenRotationAnimationLocked(Display.DEFAULT_DISPLAY);
+ } else {
+ // The screen rotation animation uses a screenshot to freeze the screen
+ // while windows resize underneath.
+ // When we are rotating seamlessly, we allow the elements to transition
+ // to their rotated state independently and without a freeze required.
+ screenRotationAnimation = null;
+ }
// We need to update our screen size information to match the new rotation. If the rotation
// has actually changed then this method will return true and, according to the comment at
@@ -6674,6 +6717,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ if (rotateSeamlessly) {
+ for (int i = windows.size() - 1; i >= 0; i--) {
+ WindowState w = windows.get(i);
+ w.mWinAnimator.seamlesslyRotateWindow(oldRotation, mRotation);
+ }
+ }
+
mDisplayManagerInternal.performTraversalInTransactionFromWindowManager();
} finally {
if (!inTransaction) {
@@ -6684,19 +6734,22 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- final WindowList windows = displayContent.getWindowList();
for (int i = windows.size() - 1; i >= 0; i--) {
WindowState w = windows.get(i);
// Discard surface after orientation change, these can't be reused.
if (w.mAppToken != null) {
w.mAppToken.destroySavedSurfaces();
}
- if (w.mHasSurface) {
+ if (w.mHasSurface && !rotateSeamlessly) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
w.mOrientationChanging = true;
mWindowPlacerLocked.mOrientationChangeComplete = false;
+ w.mLastFreezeDuration = 0;
}
- w.mLastFreezeDuration = 0;
+ }
+ if (rotateSeamlessly) {
+ mH.removeMessages(H.SEAMLESS_ROTATION_TIMEOUT);
+ mH.sendEmptyMessageDelayed(H.SEAMLESS_ROTATION_TIMEOUT, SEAMLESS_ROTATION_TIMEOUT_DURATION);
}
for (int i=mRotationWatchers.size()-1; i>=0; i--) {
@@ -6706,7 +6759,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- //TODO (multidisplay): Magnification is supported only for the default display.
+ // TODO (multidisplay): Magnification is supported only for the default display.
// Announce rotation only if we will not animate as we already have the
// windows in final state. Otherwise, we make this call at the rotation end.
if (screenRotationAnimation == null && mAccessibilityController != null
@@ -7994,8 +8047,8 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int NOTIFY_STARTING_WINDOW_DRAWN = 50;
public static final int UPDATE_ANIMATION_SCALE = 51;
public static final int WINDOW_REMOVE_TIMEOUT = 52;
-
public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53;
+ public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
/**
* Used to denote that an integer field in a message will not be used.
@@ -8635,6 +8688,25 @@ public class WindowManagerService extends IWindowManager.Stub
mAmInternal.notifyDockedStackMinimizedChanged(msg.arg1 == 1);
}
break;
+ case SEAMLESS_ROTATION_TIMEOUT: {
+ // Rotation only supported on primary display.
+ // TODO(multi-display)
+ final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ final WindowList windows = displayContent.getWindowList();
+ boolean layoutNeeded = false;
+ for (int i = windows.size() - 1; i >= 0; i--) {
+ WindowState w = windows.get(i);
+ if (w.mSeamlesslyRotated) {
+ layoutNeeded = true;
+ w.setDisplayLayoutNeeded();
+ }
+ w.mSeamlesslyRotated = false;
+ }
+ if (layoutNeeded) {
+ mWindowPlacerLocked.performSurfacePlacement();
+ }
+ }
+ break;
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG_WM, "handleMessage: exit");
@@ -10143,6 +10215,15 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ public void notifyAppRelaunchesCleared(IBinder token) {
+ synchronized (mWindowMap) {
+ final AppWindowToken appWindow = findAppWindowToken(token);
+ if (appWindow != null) {
+ appWindow.clearRelaunching();
+ }
+ }
+ }
+
@Override
public int getDockedDividerInsetsLw() {
return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 08bfa2de0b83..99fec7bdb791 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -494,6 +494,15 @@ final class WindowState implements WindowManagerPolicy.WindowState {
/** @see #isResizedWhileNotDragResizingReported(). */
private boolean mResizedWhileNotDragResizingReported;
+ /**
+ * During seamless rotation we have two phases, first the old window contents
+ * are rotated to look as if they didn't move in the new coordinate system. Then we
+ * have to freeze updates to this layer (to preserve the transformation) until
+ * the resize actually occurs. This is true from when the transformation is set
+ * and false until the transaction to resize is sent.
+ */
+ boolean mSeamlesslyRotated = false;
+
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
int viewVisibility, final DisplayContent displayContent) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 36d96979d36e..e374ee91389f 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -51,12 +51,15 @@ import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.Region;
import android.os.Debug;
import android.os.RemoteException;
+import android.os.Trace;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.MagnificationSpec;
+import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -1400,6 +1403,9 @@ class WindowStateAnimator {
mExtraHScale = (float) 1.0;
mExtraVScale = (float) 1.0;
+ boolean wasForceScaled = mForceScaleUntilResize;
+ boolean wasSeamlesslyRotated = w.mSeamlesslyRotated;
+
// Once relayout has been called at least once, we need to make sure
// we only resize the client surface during calls to relayout. For
// clients which use indeterminate measure specs (MATCH_PARENT),
@@ -1407,21 +1413,17 @@ class WindowStateAnimator {
// However, this would be unsafe, as the client may be in the middle
// of producing a frame at the old size, having just completed layout
// to find the surface size changed underneath it.
- //
- // TODO: For N we only apply this fix to the pinned workspace. As we
- // aren't observing known issues here outside of PiP resizing. (Typically
- // the other windows that use -1 are PopupWindows which aren't likely
- // to be rendering while we resize).
-
- boolean wasForceScaled = mForceScaleUntilResize;
-
- if (!w.inPinnedWorkspace() || (!w.mRelayoutCalled || w.mInRelayout)) {
+ if (!w.mRelayoutCalled || w.mInRelayout) {
mSurfaceResized = mSurfaceController.setSizeInTransaction(
mTmpSize.width(), mTmpSize.height(), recoveringMemory);
} else {
mSurfaceResized = false;
}
mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized;
+ // If we are undergoing seamless rotation, the surface has already
+ // been set up to persist at it's old location. We need to freeze
+ // updates until a resize occurs.
+ w.mSeamlesslyRotated = w.mSeamlesslyRotated && !mSurfaceResized;
calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect);
@@ -1471,17 +1473,20 @@ class WindowStateAnimator {
// will be seamless.
mForceScaleUntilResize = true;
} else {
- mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top,
- recoveringMemory);
+ if (!w.mSeamlesslyRotated) {
+ mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top,
+ recoveringMemory);
+ }
}
// If we are ending the scaling mode. We switch to SCALING_MODE_FREEZE
- // to prevent further updates until buffer latch. Normally position
- // would continue to apply immediately. But we need a different position
- // before and after resize (since we have scaled the shadows, as discussed
- // above).
- if (wasForceScaled && !mForceScaleUntilResize) {
- mSurfaceController.setPositionAppliesWithResizeInTransaction(true);
+ // to prevent further updates until buffer latch.
+ // When ending both force scaling, and seamless rotation, we need to freeze
+ // the Surface geometry until a buffer comes in at the new size (normally position and crop
+ // are unfrozen). setGeometryAppliesWithResizeInTransaction accomplishes this for us.
+ if ((wasForceScaled && !mForceScaleUntilResize) ||
+ (wasSeamlesslyRotated && !w.mSeamlesslyRotated)) {
+ mSurfaceController.setGeometryAppliesWithResizeInTransaction(true);
mSurfaceController.forceScaleableInTransaction(false);
}
@@ -1493,12 +1498,13 @@ class WindowStateAnimator {
-w.mAttrs.surfaceInsets.right, -w.mAttrs.surfaceInsets.bottom);
}
- updateSurfaceWindowCrop(clipRect, mTmpFinalClipRect, recoveringMemory);
-
- mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
- mDtDx * w.mVScale * mExtraVScale,
- mDsDy * w.mHScale * mExtraHScale,
- mDtDy * w.mVScale * mExtraVScale, recoveringMemory);
+ if (!w.mSeamlesslyRotated) {
+ updateSurfaceWindowCrop(clipRect, mTmpFinalClipRect, recoveringMemory);
+ mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
+ mDtDx * w.mVScale * mExtraVScale,
+ mDsDy * w.mHScale * mExtraHScale,
+ mDtDy * w.mVScale * mExtraVScale, recoveringMemory);
+ }
if (mSurfaceResized) {
mReportSurfaceResized = true;
@@ -1858,6 +1864,7 @@ class WindowStateAnimator {
// frozen, there is no reason to animate and it can cause strange
// artifacts when we unfreeze the display if some different animation
// is running.
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#applyAnimationLocked");
if (mService.okToDisplay()) {
int anim = mPolicy.selectAnimationLw(mWin, transit);
int attr = -1;
@@ -1897,6 +1904,8 @@ class WindowStateAnimator {
} else {
clearAnimation();
}
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+
if (mWin.mAttrs.type == TYPE_INPUT_METHOD) {
mService.adjustForImeIfNeeded(mWin.mDisplayContent);
if (isEntrance) {
@@ -2084,4 +2093,98 @@ class WindowStateAnimator {
void endDelayingAnimationStart() {
mAnimationStartDelayed = false;
}
+
+ void seamlesslyRotateWindow(int oldRotation, int newRotation) {
+ final WindowState w = mWin;
+ if (!w.isVisibleNow() || w.mIsWallpaper) {
+ return;
+ }
+
+ final Rect cropRect = mService.mTmpRect;
+ final Rect displayRect = mService.mTmpRect2;
+ final RectF frameRect = mService.mTmpRectF;
+ final Matrix transform = mService.mTmpTransform;
+
+ final float x = w.mFrame.left;
+ final float y = w.mFrame.top;
+ final float width = w.mFrame.width();
+ final float height = w.mFrame.height();
+
+ mService.getDefaultDisplayContentLocked().getLogicalDisplayRect(displayRect);
+ final float displayWidth = displayRect.width();
+ final float displayHeight = displayRect.height();
+
+ // Compute a transform matrix to undo the coordinate space transformation,
+ // and present the window at the same physical position it previously occupied.
+ final int deltaRotation = DisplayContent.deltaRotation(newRotation, oldRotation);
+ switch (deltaRotation) {
+ case Surface.ROTATION_0:
+ transform.reset();
+ break;
+ case Surface.ROTATION_270:
+ transform.setRotate(270, 0, 0);
+ transform.postTranslate(0, displayHeight);
+ transform.postTranslate(y, 0);
+ break;
+ case Surface.ROTATION_180:
+ transform.reset();
+ break;
+ case Surface.ROTATION_90:
+ transform.setRotate(90, 0, 0);
+ transform.postTranslate(displayWidth, 0);
+ transform.postTranslate(-y, x);
+ break;
+ }
+
+ // We have two cases:
+ // 1. Windows with NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY:
+ // These windows never change buffer size when rotating. Rather the window manager
+ // just updates the scaling factors to fit in the new coordinate system,
+ // and SurfaceFlinger takes care of updating the buffer contents. So in this case
+ // we just need we just need to update the scaling factors and things are seamless
+ // already.
+ // 2. Other windows:
+ // In this case, we need to apply a rotation matrix to the window. For example
+ // if we have a portrait window and rotate to landscape, the window is still portrait
+ // and now extends off the bottom of the screen (and only halfway across). Essentially we
+ // apply a transform to display the current buffer at it's old position
+ // (in the new coordinate space). We then freeze layer updates until the resize
+ // occurs, at which point we undo, them.
+ if (w.isChildWindow() && mSurfaceController.getTransformToDisplayInverse()) {
+ frameRect.set(x, y, x+width, y+height);
+ transform.mapRect(frameRect);
+
+ w.mAttrs.x = (int) frameRect.left - w.mAttachedWindow.mFrame.left;
+ w.mAttrs.y = (int) frameRect.top - w.mAttachedWindow.mFrame.top;
+ w.mAttrs.width = (int) Math.ceil(frameRect.width());
+ w.mAttrs.height = (int) Math.ceil(frameRect.height());
+
+ w.setWindowScale(w.mRequestedWidth, w.mRequestedHeight);
+
+ w.applyGravityAndUpdateFrame(w.mContainingFrame, w.mDisplayFrame);
+ computeShownFrameLocked();
+ setSurfaceBoundariesLocked(false);
+
+ // The stack bounds will not yet be rotated at this point so setSurfaceBoundaries locked
+ // will crop us incorrectly. Overwrite the crop, exposing the full surface. By the next
+ // transaction this will be corrected.
+ cropRect.set(0, 0, w.mRequestedWidth, w.mRequestedWidth + w.mRequestedHeight);
+ mSurfaceController.setCropInTransaction(cropRect, false);
+ } else {
+ w.mSeamlesslyRotated = true;
+ transform.getValues(mService.mTmpFloats);
+
+ float DsDx = mService.mTmpFloats[Matrix.MSCALE_X];
+ float DtDx = mService.mTmpFloats[Matrix.MSKEW_Y];
+ float DsDy = mService.mTmpFloats[Matrix.MSKEW_X];
+ float DtDy = mService.mTmpFloats[Matrix.MSCALE_Y];
+ float nx = mService.mTmpFloats[Matrix.MTRANS_X];
+ float ny = mService.mTmpFloats[Matrix.MTRANS_Y];
+ mSurfaceController.setPositionInTransaction(nx, ny, false);
+ mSurfaceController.setMatrixInTransaction(DsDx * w.mHScale,
+ DtDx * w.mVScale,
+ DsDy * w.mHScale,
+ DtDy * w.mVScale, false);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index fd0bb9905ce0..c77e5725a707 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -84,9 +84,10 @@ class WindowSurfaceController {
// to a black-out layer placed one Z-layer below the surface.
// This prevents holes to whatever app/wallpaper is underneath.
if (animator.mWin.isChildWindow() &&
- animator.mWin.mSubLayer < 0) {
+ animator.mWin.mSubLayer < 0 &&
+ animator.mWin.mAppToken != null) {
mSurfaceControl = new SurfaceControlWithBackground(s,
- name, w, h, format, flags);
+ name, w, h, format, flags, animator.mWin.mAppToken);
} else if (DEBUG_SURFACE_TRACE) {
mSurfaceControl = new SurfaceTrace(
s, name, w, h, format, flags);
@@ -259,8 +260,8 @@ class WindowSurfaceController {
}
}
- void setPositionAppliesWithResizeInTransaction(boolean recoveringMemory) {
- mSurfaceControl.setPositionAppliesWithResize();
+ void setGeometryAppliesWithResizeInTransaction(boolean recoveringMemory) {
+ mSurfaceControl.setGeometryAppliesWithResize();
}
void setMatrixInTransaction(float dsdx, float dtdx, float dsdy, float dtdy,
@@ -457,6 +458,10 @@ class WindowSurfaceController {
return mSurfaceControl.getHandle();
}
+ boolean getTransformToDisplayInverse() {
+ return mSurfaceControl.getTransformToDisplayInverse();
+ }
+
void getSurface(Surface outSurface) {
outSurface.copyFrom(mSurfaceControl);
}
@@ -581,10 +586,10 @@ class WindowSurfaceController {
}
@Override
- public void setPositionAppliesWithResize() {
- if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setPositionAppliesWithResize(): OLD: "
- + this + ". Called by" + Debug.getCallers(9));
- super.setPositionAppliesWithResize();
+ public void setGeometryAppliesWithResize() {
+ if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setGeometryAppliesWithResize(): OLD: "
+ + this + ". Called by" + Debug.getCallers(3));
+ super.setGeometryAppliesWithResize();
}
@Override
@@ -754,18 +759,25 @@ class WindowSurfaceController {
}
}
- private static class SurfaceControlWithBackground extends SurfaceControl {
+ class SurfaceControlWithBackground extends SurfaceControl {
private SurfaceControl mBackgroundControl;
private boolean mOpaque = true;
- private boolean mVisible = false;
+ private boolean mAppForcedInvisible = false;
+ private AppWindowToken mAppToken;
+ public boolean mVisible = false;
+ public int mLayer = -1;
public SurfaceControlWithBackground(SurfaceSession s,
- String name, int w, int h, int format, int flags)
+ String name, int w, int h, int format, int flags,
+ AppWindowToken token)
throws OutOfResourcesException {
super(s, name, w, h, format, flags);
mBackgroundControl = new SurfaceControl(s, name, w, h,
PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
+ mAppToken = token;
+
+ mAppToken.addSurfaceViewBackground(this);
}
@Override
@@ -778,6 +790,10 @@ class WindowSurfaceController {
public void setLayer(int zorder) {
super.setLayer(zorder);
mBackgroundControl.setLayer(zorder - 1);
+ if (mLayer != zorder) {
+ mLayer = zorder;
+ mAppToken.updateSurfaceViewBackgroundVisibilities();
+ }
}
@Override
@@ -814,7 +830,7 @@ class WindowSurfaceController {
public void setOpaque(boolean isOpaque) {
super.setOpaque(isOpaque);
mOpaque = isOpaque;
- updateBackgroundVisibility();
+ updateBackgroundVisibility(mAppForcedInvisible);
}
@Override
@@ -830,23 +846,28 @@ class WindowSurfaceController {
@Override
public void hide() {
- mVisible = false;
super.hide();
- updateBackgroundVisibility();
+ if (mVisible) {
+ mVisible = false;
+ mAppToken.updateSurfaceViewBackgroundVisibilities();
+ }
}
@Override
public void show() {
- mVisible = true;
super.show();
- updateBackgroundVisibility();
+ if (!mVisible) {
+ mVisible = true;
+ mAppToken.updateSurfaceViewBackgroundVisibilities();
+ }
}
@Override
public void destroy() {
super.destroy();
mBackgroundControl.destroy();
- }
+ mAppToken.removeSurfaceViewBackground(this);
+ }
@Override
public void release() {
@@ -866,8 +887,9 @@ class WindowSurfaceController {
mBackgroundControl.deferTransactionUntil(handle, frame);
}
- private void updateBackgroundVisibility() {
- if (mOpaque && mVisible) {
+ void updateBackgroundVisibility(boolean forcedInvisible) {
+ mAppForcedInvisible = forcedInvisible;
+ if (mOpaque && mVisible && !mAppForcedInvisible) {
mBackgroundControl.show();
} else {
mBackgroundControl.hide();
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 4148cd07681f..e5f972886ccf 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -731,9 +731,7 @@ class WindowSurfacePlacer {
}
try {
- if (task == null || task.mStack.getBoundsAnimating()) {
- w.mClient.moved(left, top);
- }
+ w.mClient.moved(left, top);
} catch (RemoteException e) {
}
w.mMovedByResize = false;
@@ -1076,6 +1074,8 @@ class WindowSurfacePlacer {
if (!transitionGoodToGo(appsCount)) {
return 0;
}
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady");
+
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
int transit = mService.mAppTransition.getAppTransition();
if (mService.mSkipAppTransitionAnimation) {
@@ -1209,6 +1209,9 @@ class WindowSurfacePlacer {
true /*updateInputWindows*/);
mService.mFocusMayChange = false;
mService.notifyActivityDrawnForKeyguard();
+
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+
return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b5280165bb39..c42d4617b179 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8193,6 +8193,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public SystemUpdatePolicy getSystemUpdatePolicy() {
+ if (UserManager.isDeviceInDemoMode(mContext)) {
+ // Pretending to have an automatic update policy when the device is in retail demo
+ // mode. This will allow the device to download and install an ota without
+ // any user interaction.
+ return SystemUpdatePolicy.createAutomaticInstallPolicy();
+ }
synchronized (this) {
SystemUpdatePolicy policy = mOwners.getSystemUpdatePolicy();
if (policy != null && !policy.isValid()) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 8f8ba1d19273..76424d82a2b0 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -57,7 +57,6 @@ import com.android.internal.os.ZygoteInit;
import com.android.internal.widget.ILockSettings;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.am.ActivityManagerService;
-import com.android.server.am.RetailDemoModeService;
import com.android.server.audio.AudioService;
import com.android.server.camera.CameraService;
import com.android.server.clipboard.ClipboardService;
@@ -88,6 +87,7 @@ import com.android.server.pm.UserManagerService;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.restrictions.RestrictionsManagerService;
+import com.android.server.retaildemo.RetailDemoModeService;
import com.android.server.soundtrigger.SoundTriggerService;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.storage.DeviceStorageMonitorService;
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 485f2f5318f4..ce374266b6a2 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -367,8 +367,9 @@ public class ApfFilter {
}
// Note that this parses RA and may throw IllegalArgumentException (from
- // Buffer.position(int) ) or IndexOutOfBoundsException (from ByteBuffer.get(int) ) if
- // parsing encounters something non-compliant with specifications.
+ // Buffer.position(int) or due to an invalid-length option) or IndexOutOfBoundsException
+ // (from ByteBuffer.get(int) ) if parsing encounters something non-compliant with
+ // specifications.
Ra(byte[] packet, int length) {
mPacket = ByteBuffer.allocate(length).put(ByteBuffer.wrap(packet, 0, length));
mPacket.clear();
@@ -418,6 +419,10 @@ public class ApfFilter {
// compatibility.
break;
}
+ if (optionLength <= 0) {
+ throw new IllegalArgumentException(String.format(
+ "Invalid option length opt=%d len=%d", optionType, optionLength));
+ }
mPacket.position(mPacket.position() + optionLength);
}
// Mark non-lifetime bytes since last lifetime.
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 96c852bf55f5..5852626db83b 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -30,6 +30,7 @@ import android.net.DhcpResults;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.NetworkUtils;
+import android.net.metrics.IpConnectivityLog;
import android.net.metrics.DhcpClientEvent;
import android.net.metrics.DhcpErrorEvent;
import android.os.Message;
@@ -163,6 +164,7 @@ public class DhcpClient extends StateMachine {
// System services / libraries we use.
private final Context mContext;
private final Random mRandom;
+ private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
// Sockets.
// - We use a packet socket to receive, because servers send us packets bound for IP addresses
@@ -356,14 +358,14 @@ public class DhcpClient extends StateMachine {
} catch (IOException|ErrnoException e) {
if (!mStopped) {
Log.e(TAG, "Read error", e);
- DhcpErrorEvent.logReceiveError(mIfaceName);
+ logError(DhcpErrorEvent.RECEIVE_ERROR);
}
} catch (DhcpPacket.ParseException e) {
Log.e(TAG, "Can't parse packet: " + e.getMessage());
if (PACKET_DBG) {
Log.d(TAG, HexDump.dumpHexString(mPacket, 0, length));
}
- DhcpErrorEvent.logParseError(mIfaceName, e.errorCode);
+ logError(e.errorCode);
}
}
if (DBG) Log.d(TAG, "Receive thread stopped");
@@ -493,7 +495,7 @@ public class DhcpClient extends StateMachine {
@Override
public void enter() {
if (STATE_DBG) Log.d(TAG, "Entering state " + getName());
- DhcpClientEvent.logStateEvent(mIfaceName, getName());
+ mMetricsLog.log(new DhcpClientEvent(mIfaceName, getName()));
}
private String messageName(int what) {
@@ -977,4 +979,8 @@ public class DhcpClient extends StateMachine {
class DhcpRebootingState extends LoggingState {
}
+
+ private void logError(int errorCode) {
+ mMetricsLog.log(new DhcpErrorEvent(mIfaceName, errorCode));
+ }
}
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index cece6c8c0cac..86e15182165d 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -31,6 +31,7 @@ import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.StaticIpConfiguration;
import android.net.dhcp.DhcpClient;
+import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpManagerEvent;
import android.os.INetworkManagementService;
import android.os.Message;
@@ -393,6 +394,7 @@ public class IpManager extends StateMachine {
private final WakeupMessage mProvisioningTimeoutAlarm;
private final WakeupMessage mDhcpActionTimeoutAlarm;
private final LocalLog mLocalLog;
+ private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
private NetworkInterface mNetworkInterface;
@@ -634,8 +636,8 @@ public class IpManager extends StateMachine {
private void recordMetric(final int type) {
if (mStartTimeMillis <= 0) { Log.wtf(mTag, "Start time undefined!"); }
- IpManagerEvent.logEvent(type, mInterfaceName,
- SystemClock.elapsedRealtime() - mStartTimeMillis);
+ final long duration = SystemClock.elapsedRealtime() - mStartTimeMillis;
+ mMetricsLog.log(new IpManagerEvent(mInterfaceName, type, duration));
}
// For now: use WifiStateMachine's historical notion of provisioned.
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index 27600a768896..afb644f3546b 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -24,6 +24,7 @@ import android.net.LinkProperties;
import android.net.LinkProperties.ProvisioningChange;
import android.net.ProxyInfo;
import android.net.RouteInfo;
+import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpReachabilityEvent;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkErrorMessage;
@@ -151,6 +152,7 @@ public class IpReachabilityMonitor {
private final Callback mCallback;
private final NetlinkSocketObserver mNetlinkSocketObserver;
private final Thread mObserverThread;
+ private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
@GuardedBy("mLock")
private LinkProperties mLinkProperties = new LinkProperties();
// TODO: consider a map to a private NeighborState class holding more
@@ -359,7 +361,6 @@ public class IpReachabilityMonitor {
}
if (delta == ProvisioningChange.LOST_PROVISIONING) {
- IpReachabilityEvent.logProvisioningLost(mInterfaceName);
final String logMsg = "FAILURE: LOST_PROVISIONING, " + msg;
Log.w(TAG, logMsg);
if (mCallback != null) {
@@ -367,8 +368,9 @@ public class IpReachabilityMonitor {
// an InetAddress argument.
mCallback.notifyLost(ip, logMsg);
}
+ logEvent(IpReachabilityEvent.PROVISIONING_LOST, 0);
} else {
- IpReachabilityEvent.logNudFailed(mInterfaceName);
+ logEvent(IpReachabilityEvent.NUD_FAILED, 0);
}
}
@@ -393,7 +395,7 @@ public class IpReachabilityMonitor {
break;
}
final int returnValue = probeNeighbor(mInterfaceIndex, target);
- IpReachabilityEvent.logProbeEvent(mInterfaceName, returnValue);
+ logEvent(IpReachabilityEvent.PROBE, returnValue);
}
}
@@ -413,6 +415,11 @@ public class IpReachabilityMonitor {
return (numUnicastProbes * retransTimeMs) + gracePeriodMs;
}
+ private void logEvent(int probeType, int errorCode) {
+ int eventType = probeType | (errorCode & 0xff );
+ mMetricsLog.log(new IpReachabilityEvent(mInterfaceName, eventType));
+ }
+
// TODO: simplify the number of objects by making this extend Thread.
private final class NetlinkSocketObserver implements Runnable {
private NetlinkSocket mSocket;
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index 7a3ebf422a8a..05301c1cb5f2 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -764,9 +764,8 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
public void updateIfNeededLocked() {
throwIfDestroyedLocked();
- if (readConfigurationLocked()) {
- onConfigurationChangedLocked();
- }
+ readConfigurationLocked();
+ onConfigurationChangedLocked();
}
public void destroyLocked() {
@@ -841,14 +840,12 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
pw.println();
}
- private boolean readConfigurationLocked() {
- boolean somethingChanged = false;
- somethingChanged |= readInstalledPrintServicesLocked();
- somethingChanged |= readDisabledPrintServicesLocked();
- return somethingChanged;
+ private void readConfigurationLocked() {
+ readInstalledPrintServicesLocked();
+ readDisabledPrintServicesLocked();
}
- private boolean readInstalledPrintServicesLocked() {
+ private void readInstalledPrintServicesLocked() {
Set<PrintServiceInfo> tempPrintServices = new HashSet<PrintServiceInfo>();
List<ResolveInfo> installedServices = mContext.getPackageManager()
@@ -872,39 +869,8 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
tempPrintServices.add(PrintServiceInfo.create(installedService, mContext));
}
- boolean someServiceChanged = false;
-
- if (tempPrintServices.size() != mInstalledServices.size()) {
- someServiceChanged = true;
- } else {
- for (PrintServiceInfo newService: tempPrintServices) {
- final int oldServiceIndex = mInstalledServices.indexOf(newService);
- if (oldServiceIndex < 0) {
- someServiceChanged = true;
- break;
- }
- // PrintServiceInfo#equals compares only the id not all members,
- // so we are also comparing the members coming from meta-data.
- PrintServiceInfo oldService = mInstalledServices.get(oldServiceIndex);
- if (!TextUtils.equals(oldService.getAddPrintersActivityName(),
- newService.getAddPrintersActivityName())
- || !TextUtils.equals(oldService.getAdvancedOptionsActivityName(),
- newService.getAdvancedOptionsActivityName())
- || !TextUtils.equals(oldService.getSettingsActivityName(),
- newService.getSettingsActivityName())) {
- someServiceChanged = true;
- break;
- }
- }
- }
-
- if (someServiceChanged) {
- mInstalledServices.clear();
- mInstalledServices.addAll(tempPrintServices);
- return true;
- }
-
- return false;
+ mInstalledServices.clear();
+ mInstalledServices.addAll(tempPrintServices);
}
/**
@@ -944,16 +910,14 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
*
* @return true if the state changed.
*/
- private boolean readDisabledPrintServicesLocked() {
+ private void readDisabledPrintServicesLocked() {
Set<ComponentName> tempDisabledServiceNameSet = new HashSet<ComponentName>();
readPrintServicesFromSettingLocked(Settings.Secure.DISABLED_PRINT_SERVICES,
tempDisabledServiceNameSet);
if (!tempDisabledServiceNameSet.equals(mDisabledServices)) {
mDisabledServices.clear();
mDisabledServices.addAll(tempDisabledServiceNameSet);
- return true;
}
- return false;
}
private void readPrintServicesFromSettingLocked(String setting,
diff --git a/services/retaildemo/Android.mk b/services/retaildemo/Android.mk
new file mode 100644
index 000000000000..670c6bfa1e6a
--- /dev/null
+++ b/services/retaildemo/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.retaildemo
+
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under,java)
+
+LOCAL_JAVA_LIBRARIES := services.core
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/am/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index 6a5ec9697a41..d858e822cdbe 100644
--- a/services/core/java/com/android/server/am/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -14,23 +14,32 @@
* limitations under the License
*/
-package com.android.server.am;
+package com.android.server.retaildemo;
+import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.RetailDemoModeServiceInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.content.res.Configuration;
import android.database.ContentObserver;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.media.AudioManager;
+import android.media.AudioSystem;
import android.net.Uri;
import android.os.Environment;
import android.os.FileUtils;
@@ -44,13 +53,19 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;
-
import com.android.internal.os.BackgroundThread;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.logging.MetricsLogger;
import com.android.internal.widget.LockPatternUtils;
+import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.retaildemo.UserInactivityCountdownDialog.OnCountDownExpiredListener;
+
import java.io.File;
+import java.util.ArrayList;
public class RetailDemoModeService extends SystemService {
private static final boolean DEBUG = false;
@@ -65,9 +80,23 @@ public class RetailDemoModeService extends SystemService {
private static final long SCREEN_WAKEUP_DELAY = 2500;
private static final long USER_INACTIVITY_TIMEOUT = 30000;
+ private static final long WARNING_DIALOG_TIMEOUT = 6000;
+ private static final long MILLIS_PER_SECOND = 1000;
+
+ private static final int[] VOLUME_STREAMS_TO_MUTE = {
+ AudioSystem.STREAM_RING,
+ AudioSystem.STREAM_MUSIC
+ };
+
+ // Tron Vars
+ private static final String DEMO_SESSION_COUNT = "retail_demo_session_count";
+ private static final String DEMO_SESSION_DURATION = "retail_demo_session_duration";
boolean mDeviceInDemoMode = false;
+ int mCurrentUserId = UserHandle.USER_SYSTEM;
private ActivityManagerService mAms;
+ private ActivityManagerInternal mAmi;
+ private AudioManager mAudioManager;
private NotificationManager mNm;
private UserManager mUm;
private PowerManager mPm;
@@ -75,6 +104,18 @@ public class RetailDemoModeService extends SystemService {
Handler mHandler;
private ServiceThread mHandlerThread;
private PendingIntent mResetDemoPendingIntent;
+ private CameraManager mCameraManager;
+ private String[] mCameraIdsWithFlash;
+ private Configuration mSystemUserConfiguration;
+
+ final Object mActivityLock = new Object();
+ // Whether the newly created demo user has interacted with the screen yet
+ @GuardedBy("mActivityLock")
+ boolean mUserUntouched;
+ @GuardedBy("mActivityLock")
+ long mFirstUserActivityTime;
+ @GuardedBy("mActivityLock")
+ long mLastUserActivityTime;
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -110,20 +151,9 @@ public class RetailDemoModeService extends SystemService {
mWakeLock.acquire();
break;
case MSG_INACTIVITY_TIME_OUT:
- IPackageManager pm = AppGlobals.getPackageManager();
- int enabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
- String demoLauncherComponent = getContext().getResources()
- .getString(R.string.config_demoModeLauncherComponent);
- try {
- enabledState = pm.getComponentEnabledSetting(
- ComponentName.unflattenFromString(demoLauncherComponent),
- getActivityManager().getCurrentUser().id);
- } catch (RemoteException exc) {
- // XXX: shouldn't happen
- }
- if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
- Slog.i(TAG, "Restarting session due to user inactivity timeout");
- sendEmptyMessage(MSG_START_NEW_SESSION);
+ if (isDemoLauncherDisabled()) {
+ Slog.i(TAG, "User inactivity timeout reached");
+ showInactivityCountdownDialog();
}
break;
case MSG_START_NEW_SESSION:
@@ -131,7 +161,11 @@ public class RetailDemoModeService extends SystemService {
Slog.d(TAG, "Switching to a new demo user");
}
removeMessages(MSG_START_NEW_SESSION);
- UserInfo demoUser = getUserManager().createUser(DEMO_USER_NAME,
+ removeMessages(MSG_INACTIVITY_TIME_OUT);
+ if (mCurrentUserId != UserHandle.USER_SYSTEM) {
+ logSessionDuration();
+ }
+ final UserInfo demoUser = getUserManager().createUser(DEMO_USER_NAME,
UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL);
if (demoUser != null) {
setupDemoUser(demoUser);
@@ -142,8 +176,30 @@ public class RetailDemoModeService extends SystemService {
}
}
+ private void showInactivityCountdownDialog() {
+ UserInactivityCountdownDialog dialog = new UserInactivityCountdownDialog(getContext(),
+ WARNING_DIALOG_TIMEOUT, MILLIS_PER_SECOND);
+ dialog.setNegativeButtonClickListener(null);
+ dialog.setPositiveButtonClickListener(new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
+ }
+ });
+ dialog.setOnCountDownExpiredListener(new OnCountDownExpiredListener() {
+ @Override
+ public void onCountDownExpired() {
+ mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
+ }
+ });
+ dialog.show();
+ }
+
public RetailDemoModeService(Context context) {
super(context);
+ synchronized (mActivityLock) {
+ mFirstUserActivityTime = mLastUserActivityTime = SystemClock.uptimeMillis();
+ }
}
private Notification createResetNotification() {
@@ -167,7 +223,22 @@ public class RetailDemoModeService extends SystemService {
return mResetDemoPendingIntent;
}
- void setupDemoUser(UserInfo userInfo) {
+ boolean isDemoLauncherDisabled() {
+ IPackageManager pm = AppGlobals.getPackageManager();
+ int enabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ String demoLauncherComponent = getContext().getResources()
+ .getString(R.string.config_demoModeLauncherComponent);
+ try {
+ enabledState = pm.getComponentEnabledSetting(
+ ComponentName.unflattenFromString(demoLauncherComponent),
+ mCurrentUserId);
+ } catch (RemoteException exc) {
+ Slog.e(TAG, "Unable to talk to Package Manager", exc);
+ }
+ return enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+ }
+
+ private void setupDemoUser(UserInfo userInfo) {
UserManager um = getUserManager();
UserHandle user = UserHandle.of(userInfo.id);
LockPatternUtils lockPatternUtils = new LockPatternUtils(getContext());
@@ -180,6 +251,14 @@ public class RetailDemoModeService extends SystemService {
Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
}
+ void logSessionDuration() {
+ final int sessionDuration;
+ synchronized (mActivityLock) {
+ sessionDuration = (int) ((mLastUserActivityTime - mFirstUserActivityTime) / 1000);
+ }
+ MetricsLogger.count(getContext(), DEMO_SESSION_DURATION, sessionDuration);
+ }
+
private ActivityManagerService getActivityManager() {
if (mAms == null) {
mAms = (ActivityManagerService) ActivityManagerNative.getDefault();
@@ -194,6 +273,13 @@ public class RetailDemoModeService extends SystemService {
return mUm;
}
+ private AudioManager getAudioManager() {
+ if (mAudioManager == null) {
+ mAudioManager = getContext().getSystemService(AudioManager.class);
+ }
+ return mAudioManager;
+ }
+
private void registerSettingsChangeObserver() {
final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
final Uri deviceProvisionedUri = Settings.Global.getUriFor(
@@ -230,13 +316,13 @@ public class RetailDemoModeService extends SystemService {
UserHandle.USER_SYSTEM);
}
- boolean isDeviceProvisioned() {
+ private boolean isDeviceProvisioned() {
return Settings.Global.getInt(
getContext().getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
}
private boolean deleteDemoFolderContents() {
- File dir = Environment.getDataPreloadsDemoDirectory();
+ final File dir = Environment.getDataPreloadsDemoDirectory();
Slog.i(TAG, "Deleting contents of " + dir);
return FileUtils.deleteContents(dir);
}
@@ -248,6 +334,46 @@ public class RetailDemoModeService extends SystemService {
getContext().registerReceiver(mBroadcastReceiver, filter);
}
+ private String[] getCameraIdsWithFlash() {
+ ArrayList<String> cameraIdsList = new ArrayList<String>();
+ try {
+ for (String cameraId : mCameraManager.getCameraIdList()) {
+ CameraCharacteristics c = mCameraManager.getCameraCharacteristics(cameraId);
+ if (Boolean.TRUE.equals(c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE))) {
+ cameraIdsList.add(cameraId);
+ }
+ }
+ } catch (CameraAccessException e) {
+ Slog.e(TAG, "Unable to access camera while getting camera id list", e);
+ }
+ return cameraIdsList.toArray(new String[cameraIdsList.size()]);
+ }
+
+ private void turnOffAllFlashLights() {
+ for (String cameraId : mCameraIdsWithFlash) {
+ try {
+ mCameraManager.setTorchMode(cameraId, false);
+ } catch (CameraAccessException e) {
+ Slog.e(TAG, "Unable to access camera " + cameraId + " while turning off flash", e);
+ }
+ }
+ }
+
+ private void muteVolumeStreams() {
+ for (int stream : VOLUME_STREAMS_TO_MUTE) {
+ getAudioManager().setStreamVolume(stream, getAudioManager().getStreamMinVolume(stream),
+ 0);
+ }
+ }
+
+ private Configuration getSystemUsersConfiguration() {
+ if (mSystemUserConfiguration == null) {
+ Settings.System.getConfiguration(getContext().getContentResolver(),
+ mSystemUserConfiguration = new Configuration());
+ }
+ return mSystemUserConfiguration;
+ }
+
@Override
public void onStart() {
if (DEBUG) {
@@ -266,9 +392,12 @@ public class RetailDemoModeService extends SystemService {
return;
}
mPm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
+ mAmi = LocalServices.getService(ActivityManagerInternal.class);
mWakeLock = mPm
.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
mNm = NotificationManager.from(getContext());
+ mCameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
+ mCameraIdsWithFlash = getCameraIdsWithFlash();
if (UserManager.isDeviceInDemoMode(getContext())) {
mDeviceInDemoMode = true;
@@ -286,7 +415,7 @@ public class RetailDemoModeService extends SystemService {
if (DEBUG) {
Slog.d(TAG, "onSwitchUser: " + userId);
}
- UserInfo ui = getUserManager().getUserInfo(userId);
+ final UserInfo ui = getUserManager().getUserInfo(userId);
if (!ui.isDemo()) {
Slog.wtf(TAG, "Should not allow switch to non-demo user in demo mode");
return;
@@ -294,12 +423,21 @@ public class RetailDemoModeService extends SystemService {
if (!mWakeLock.isHeld()) {
mWakeLock.acquire();
}
+ mCurrentUserId = userId;
+ mAmi.updatePersistentConfigurationForUser(getSystemUsersConfiguration(), userId);
+ turnOffAllFlashLights();
+ muteVolumeStreams();
mNm.notifyAsUser(TAG, 1, createResetNotification(), UserHandle.of(userId));
+
+ synchronized (mActivityLock) {
+ mUserUntouched = true;
+ }
+ MetricsLogger.count(getContext(), DEMO_SESSION_COUNT, 1);
+ mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
}
- public RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() {
+ private RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() {
private static final long USER_ACTIVITY_DEBOUNCE_TIME = 2000;
- private long mLastUserActivityTime = 0;
@Override
public void onUserActivity() {
@@ -307,10 +445,17 @@ public class RetailDemoModeService extends SystemService {
return;
}
long timeOfActivity = SystemClock.uptimeMillis();
- if (timeOfActivity < mLastUserActivityTime + USER_ACTIVITY_DEBOUNCE_TIME) {
- return;
+ synchronized (mActivityLock) {
+ if (timeOfActivity < mLastUserActivityTime + USER_ACTIVITY_DEBOUNCE_TIME) {
+ return;
+ }
+ mLastUserActivityTime = timeOfActivity;
+ if (mUserUntouched && isDemoLauncherDisabled()) {
+ Slog.d(TAG, "retail_demo first touch");
+ mUserUntouched = false;
+ mFirstUserActivityTime = timeOfActivity;
+ }
}
- mLastUserActivityTime = timeOfActivity;
mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
mHandler.sendEmptyMessageDelayed(MSG_INACTIVITY_TIME_OUT, USER_INACTIVITY_TIMEOUT);
}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
new file mode 100644
index 000000000000..d14f4eb33dc5
--- /dev/null
+++ b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.retaildemo;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.os.CountDownTimer;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
+public class UserInactivityCountdownDialog extends AlertDialog {
+
+ private OnCountDownExpiredListener mOnCountDownExpiredListener;
+ private CountDownTimer mCountDownTimer;
+ private long mCountDownDuration;
+ private long mRefreshInterval;
+
+ UserInactivityCountdownDialog(Context context, long duration, long refreshInterval) {
+ super(context);
+ mCountDownDuration = duration;
+ mRefreshInterval = refreshInterval;
+
+ getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+ WindowManager.LayoutParams attrs = getWindow().getAttributes();
+ attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ getWindow().setAttributes(attrs);
+
+ setTitle(R.string.demo_user_inactivity_timeout_title);
+ setMessage(getContext().getString(R.string.demo_user_inactivity_timeout_countdown,
+ duration));
+ }
+
+ public void setOnCountDownExpiredListener(
+ OnCountDownExpiredListener onCountDownExpiredListener) {
+ mOnCountDownExpiredListener = onCountDownExpiredListener;
+ }
+
+ public void setPositiveButtonClickListener(OnClickListener onClickListener) {
+ setButton(Dialog.BUTTON_POSITIVE,
+ getContext().getString(R.string.demo_user_inactivity_timeout_right_button),
+ onClickListener);
+ }
+
+ public void setNegativeButtonClickListener(OnClickListener onClickListener) {
+ setButton(Dialog.BUTTON_NEGATIVE,
+ getContext().getString(R.string.demo_user_inactivity_timeout_left_button),
+ onClickListener);
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ final TextView messageView = (TextView) findViewById(R.id.message);
+ messageView.post(new Runnable() {
+ @Override
+ public void run() {
+ mCountDownTimer = new CountDownTimer(mCountDownDuration, mRefreshInterval) {
+
+ @Override
+ public void onTick(long millisUntilFinished) {
+ String msg = getContext().getString(
+ R.string.demo_user_inactivity_timeout_countdown,
+ millisUntilFinished / 1000);
+ messageView.setText(msg);
+ }
+
+ @Override
+ public void onFinish() {
+ dismiss();
+ if (mOnCountDownExpiredListener != null)
+ mOnCountDownExpiredListener.onCountDownExpired();
+ }
+ }.start();
+ }
+ });
+ }
+
+ @Override
+ public void onStop() {
+ if (mCountDownTimer != null) {
+ mCountDownTimer.cancel();
+ }
+ }
+
+ interface OnCountDownExpiredListener {
+ void onCountDownExpired();
+ }
+}
diff --git a/services/tests/servicestests/res/xml/shortcut_3.xml b/services/tests/servicestests/res/xml/shortcut_3.xml
new file mode 100644
index 000000000000..432ca4935ec3
--- /dev/null
+++ b/services/tests/servicestests/res/xml/shortcut_3.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android" >
+ <shortcut
+ android:shortcutId="ms1"
+ android:enabled="true"
+ android:icon="@drawable/icon1"
+ android:shortcutShortLabel="@string/shortcut_title1"
+ android:shortcutLongLabel="@string/shortcut_text1"
+ android:shortcutDisabledMessage="@string/shortcut_disabled_message1"
+ >
+ <intent
+ android:action="action1"
+ android:data="http://a.b.c/"
+ >
+ </intent>
+ <categories android:name="android.shortcut.conversation" />
+ <categories android:name="android.shortcut.media" />
+ </shortcut>
+ <shortcut
+ android:shortcutId="ms2"
+ android:enabled="true"
+ android:icon="@drawable/icon2"
+ android:shortcutShortLabel="@string/shortcut_title2"
+ android:shortcutLongLabel="@string/shortcut_text2"
+ android:shortcutDisabledMessage="@string/shortcut_disabled_message2"
+ >
+ <intent
+ android:action="action2"
+ android:data="http://a.b.c/2"
+ >
+ </intent>
+ <categories android:name="android.shortcut.conversation" />
+ </shortcut>
+ <shortcut
+ android:shortcutId="ms3"
+ android:enabled="true"
+ android:icon="@drawable/icon3"
+ android:shortcutShortLabel="@string/shortcut_title2"
+ >
+ <intent android:action="action3" />
+ </shortcut>
+</shortcuts>
diff --git a/services/tests/servicestests/src/android/net/apf/ApfTest.java b/services/tests/servicestests/src/android/net/apf/ApfTest.java
index fae82ca4e7a3..8ac238a9c415 100644
--- a/services/tests/servicestests/src/android/net/apf/ApfTest.java
+++ b/services/tests/servicestests/src/android/net/apf/ApfTest.java
@@ -552,6 +552,10 @@ public class ApfTest extends AndroidTestCase {
assertTrue(mGotApfProgram.block(TIMEOUT_MS));
return mLastApfProgram;
}
+
+ public void assertNoProgramUpdate() {
+ assertFalse(mGotApfProgram.block(TIMEOUT_MS));
+ }
}
private static class TestApfFilter extends ApfFilter {
@@ -863,6 +867,13 @@ public class ApfTest extends AndroidTestCase {
verifyRaLifetime(ipManagerCallback, packet, lifetime);
}
+ private void assertInvalidRa(TestApfFilter apfFilter, MockIpManagerCallback ipManagerCallback,
+ ByteBuffer packet) throws IOException, ErrnoException {
+ ipManagerCallback.resetApfProgramWait();
+ apfFilter.pretendPacketReceived(packet.array());
+ ipManagerCallback.assertNoProgramUpdate();
+ }
+
@LargeTest
public void testApfFilterRa() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
@@ -881,6 +892,16 @@ public class ApfTest extends AndroidTestCase {
testRaLifetime(apfFilter, ipManagerCallback, basePacket, 1000);
+ // Ensure zero-length options cause the packet to be silently skipped.
+ // Do this before we test other packets. http://b/29586253
+ ByteBuffer zeroLengthOptionPacket = ByteBuffer.wrap(
+ new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
+ basePacket.clear();
+ zeroLengthOptionPacket.put(basePacket);
+ zeroLengthOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
+ zeroLengthOptionPacket.put((byte)0);
+ assertInvalidRa(apfFilter, ipManagerCallback, zeroLengthOptionPacket);
+
// Generate several RAs with different options and lifetimes, and verify when
// ApfFilter is shown these packets, it generates programs to filter them for the
// appropriate lifetime.
diff --git a/services/tests/servicestests/src/android/net/metrics/IpConnectivityLogTest.java b/services/tests/servicestests/src/android/net/metrics/IpConnectivityLogTest.java
new file mode 100644
index 000000000000..1433f959898c
--- /dev/null
+++ b/services/tests/servicestests/src/android/net/metrics/IpConnectivityLogTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.net.ConnectivityMetricsEvent;
+import android.net.IConnectivityMetricsLogger;
+
+import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+public class IpConnectivityLogTest extends TestCase {
+
+ // use same Parcel object everywhere for pointer equality
+ static final Bundle FAKE_EV = new Bundle();
+
+ @Mock IConnectivityMetricsLogger mService;
+ ArgumentCaptor<ConnectivityMetricsEvent> evCaptor;
+
+ IpConnectivityLog mLog;
+
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ evCaptor = ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);
+ mLog = new IpConnectivityLog(mService);
+ }
+
+ public void testLogEvents() throws Exception {
+ assertTrue(mLog.log(1, FAKE_EV));
+ assertTrue(mLog.log(2, FAKE_EV));
+ assertTrue(mLog.log(3, FAKE_EV));
+
+ List<ConnectivityMetricsEvent> gotEvents = verifyEvents(3);
+ assertEventsEqual(expectedEvent(1), gotEvents.get(0));
+ assertEventsEqual(expectedEvent(2), gotEvents.get(1));
+ assertEventsEqual(expectedEvent(3), gotEvents.get(2));
+ }
+
+ public void testLogEventTriggerThrottling() throws Exception {
+ when(mService.logEvent(any())).thenReturn(1234L);
+
+ assertFalse(mLog.log(1, FAKE_EV));
+ }
+
+ public void testLogEventFails() throws Exception {
+ when(mService.logEvent(any())).thenReturn(-1L); // Error.
+
+ assertFalse(mLog.log(1, FAKE_EV));
+ }
+
+ public void testLogEventWhenThrottling() throws Exception {
+ when(mService.logEvent(any())).thenReturn(Long.MAX_VALUE); // Throttled
+
+ // No events are logged. The service is only called once
+ // After that, throttling state is maintained locally.
+ assertFalse(mLog.log(1, FAKE_EV));
+ assertFalse(mLog.log(2, FAKE_EV));
+
+ List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1);
+ assertEventsEqual(expectedEvent(1), gotEvents.get(0));
+ }
+
+ public void testLogEventRecoverFromThrottling() throws Exception {
+ final long throttleTimeout = System.currentTimeMillis() + 50;
+ when(mService.logEvent(any())).thenReturn(throttleTimeout, 0L);
+
+ assertFalse(mLog.log(1, FAKE_EV));
+ new Thread() {
+ public void run() {
+ busySpinLog();
+ }
+ }.start();
+
+ List<ConnectivityMetricsEvent> gotEvents = verifyEvents(2, 200);
+ assertEventsEqual(expectedEvent(1), gotEvents.get(0));
+ assertEventsEqual(expectedEvent(2), gotEvents.get(1));
+ }
+
+ public void testLogEventRecoverFromThrottlingWithMultipleCallers() throws Exception {
+ final long throttleTimeout = System.currentTimeMillis() + 50;
+ when(mService.logEvent(any())).thenReturn(throttleTimeout, 0L);
+
+ assertFalse(mLog.log(1, FAKE_EV));
+ final int nCallers = 10;
+ for (int i = 0; i < nCallers; i++) {
+ new Thread() {
+ public void run() {
+ busySpinLog();
+ }
+ }.start();
+ }
+
+ List<ConnectivityMetricsEvent> gotEvents = verifyEvents(1 + nCallers, 200);
+ assertEventsEqual(expectedEvent(1), gotEvents.get(0));
+ for (int i = 0; i < nCallers; i++) {
+ assertEventsEqual(expectedEvent(2), gotEvents.get(1 + i));
+ }
+ }
+
+ void busySpinLog() {
+ final long timeout = 200;
+ final long stop = System.currentTimeMillis() + timeout;
+ try {
+ while (System.currentTimeMillis() < stop) {
+ if (mLog.log(2, FAKE_EV)) {
+ return;
+ }
+ Thread.sleep(10);
+ }
+ } catch (InterruptedException e) { }
+ }
+
+ List<ConnectivityMetricsEvent> verifyEvents(int n) throws Exception {
+ verify(mService, times(n)).logEvent(evCaptor.capture());
+ return evCaptor.getAllValues();
+ }
+
+ List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
+ verify(mService, timeout(timeoutMs).times(n)).logEvent(evCaptor.capture());
+ return evCaptor.getAllValues();
+ }
+
+ static ConnectivityMetricsEvent expectedEvent(int timestamp) {
+ return new ConnectivityMetricsEvent((long)timestamp, 0, 0, FAKE_EV);
+ }
+
+ /** Outer equality for ConnectivityMetricsEvent to avoid overriding equals() and hashCode(). */
+ static void assertEventsEqual(ConnectivityMetricsEvent expected, ConnectivityMetricsEvent got) {
+ assertEquals(expected.timestamp, got.timestamp);
+ assertEquals(expected.componentTag, got.componentTag);
+ assertEquals(expected.eventTag, got.eventTag);
+ assertEquals(expected.data, got.data);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/internal/util/FakeSettingsProviderTest.java b/services/tests/servicestests/src/com/android/internal/util/FakeSettingsProviderTest.java
index a18737c42e52..05de0a53e055 100644
--- a/services/tests/servicestests/src/com/android/internal/util/FakeSettingsProviderTest.java
+++ b/services/tests/servicestests/src/com/android/internal/util/FakeSettingsProviderTest.java
@@ -24,6 +24,7 @@ import android.test.AndroidTestCase;
import android.test.mock.MockContentResolver;
import android.test.mock.MockContext;
import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
import android.util.Log;
import java.util.concurrent.CountDownLatch;
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/DnsEventListenerServiceTest.java b/services/tests/servicestests/src/com/android/server/connectivity/DnsEventListenerServiceTest.java
new file mode 100644
index 000000000000..033b2c96c8f5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/connectivity/DnsEventListenerServiceTest.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.metrics.DnsEvent;
+import android.net.metrics.IDnsEventListener;
+import android.net.metrics.IpConnectivityLog;
+
+import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.List;
+import java.util.OptionalInt;
+import java.util.stream.IntStream;
+
+public class DnsEventListenerServiceTest extends TestCase {
+
+ // TODO: read from DnsEventListenerService after this constant is read from system property
+ static final int BATCH_SIZE = 100;
+ static final int EVENT_TYPE = IDnsEventListener.EVENT_GETADDRINFO;
+ // TODO: read from IDnsEventListener
+ static final int RETURN_CODE = 1;
+
+ static final byte[] EVENT_TYPES = new byte[BATCH_SIZE];
+ static final byte[] RETURN_CODES = new byte[BATCH_SIZE];
+ static final int[] LATENCIES = new int[BATCH_SIZE];
+ static {
+ for (int i = 0; i < BATCH_SIZE; i++) {
+ EVENT_TYPES[i] = EVENT_TYPE;
+ RETURN_CODES[i] = RETURN_CODE;
+ LATENCIES[i] = i;
+ }
+ }
+
+ DnsEventListenerService mDnsService;
+
+ @Mock ConnectivityManager mCm;
+ @Mock IpConnectivityLog mLog;
+ ArgumentCaptor<NetworkCallback> mCallbackCaptor;
+ ArgumentCaptor<DnsEvent> mEvCaptor;
+
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class);
+ mEvCaptor = ArgumentCaptor.forClass(DnsEvent.class);
+ mDnsService = new DnsEventListenerService(mCm, mLog);
+
+ verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture());
+ }
+
+ public void testOneBatch() throws Exception {
+ log(105, LATENCIES);
+ log(106, Arrays.copyOf(LATENCIES, BATCH_SIZE - 1)); // one lookup short of a batch event
+
+ verifyLoggedEvents(new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES));
+
+ log(106, Arrays.copyOfRange(LATENCIES, BATCH_SIZE - 1, BATCH_SIZE));
+
+ mEvCaptor = ArgumentCaptor.forClass(DnsEvent.class); // reset argument captor
+ verifyLoggedEvents(
+ new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
+ new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES));
+ }
+
+ public void testSeveralBatches() throws Exception {
+ log(105, LATENCIES);
+ log(106, LATENCIES);
+ log(105, LATENCIES);
+ log(107, LATENCIES);
+
+ verifyLoggedEvents(
+ new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
+ new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES),
+ new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
+ new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES));
+ }
+
+ public void testBatchAndNetworkLost() throws Exception {
+ byte[] eventTypes = Arrays.copyOf(EVENT_TYPES, 20);
+ byte[] returnCodes = Arrays.copyOf(RETURN_CODES, 20);
+ int[] latencies = Arrays.copyOf(LATENCIES, 20);
+
+ log(105, LATENCIES);
+ log(105, latencies);
+ mCallbackCaptor.getValue().onLost(new Network(105));
+ log(105, LATENCIES);
+
+ verifyLoggedEvents(
+ new DnsEvent(105, eventTypes, returnCodes, latencies),
+ new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
+ new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES));
+ }
+
+ public void testConcurrentBatchesAndDumps() throws Exception {
+ final long stop = System.currentTimeMillis() + 100;
+ final PrintWriter pw = new PrintWriter(new FileOutputStream("/dev/null"));
+ new Thread() {
+ public void run() {
+ while (System.currentTimeMillis() < stop) {
+ mDnsService.dump(pw);
+ }
+ }
+ }.start();
+
+ logAsync(105, LATENCIES);
+ logAsync(106, LATENCIES);
+ logAsync(107, LATENCIES);
+
+ verifyLoggedEvents(500,
+ new DnsEvent(105, EVENT_TYPES, RETURN_CODES, LATENCIES),
+ new DnsEvent(106, EVENT_TYPES, RETURN_CODES, LATENCIES),
+ new DnsEvent(107, EVENT_TYPES, RETURN_CODES, LATENCIES));
+ }
+
+ public void testConcurrentBatchesAndNetworkLoss() throws Exception {
+ logAsync(105, LATENCIES);
+ Thread.sleep(10L);
+ // call onLost() asynchronously to logAsync's onDnsEvent() calls.
+ mCallbackCaptor.getValue().onLost(new Network(105));
+
+ // do not verify unpredictable batch
+ verify(mLog, timeout(500).times(1)).log(any());
+ }
+
+ void log(int netId, int[] latencies) {
+ for (int l : latencies) {
+ mDnsService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l);
+ }
+ }
+
+ void logAsync(int netId, int[] latencies) {
+ new Thread() {
+ public void run() {
+ log(netId, latencies);
+ }
+ }.start();
+ }
+
+ void verifyLoggedEvents(DnsEvent... expected) {
+ verifyLoggedEvents(0, expected);
+ }
+
+ void verifyLoggedEvents(int wait, DnsEvent... expectedEvents) {
+ verify(mLog, timeout(wait).times(expectedEvents.length)).log(mEvCaptor.capture());
+ for (DnsEvent got : mEvCaptor.getAllValues()) {
+ OptionalInt index = IntStream.range(0, expectedEvents.length)
+ .filter(i -> eventsEqual(expectedEvents[i], got))
+ .findFirst();
+ // Don't match same expected event more than once.
+ index.ifPresent(i -> expectedEvents[i] = null);
+ assertTrue(index.isPresent());
+ }
+ }
+
+ /** equality function for DnsEvent to avoid overriding equals() and hashCode(). */
+ static boolean eventsEqual(DnsEvent expected, DnsEvent got) {
+ return (expected == got) || ((expected != null) && (got != null)
+ && (expected.netId == got.netId)
+ && Arrays.equals(expected.eventTypes, got.eventTypes)
+ && Arrays.equals(expected.returnCodes, got.returnCodes)
+ && Arrays.equals(expected.latenciesMs, got.latenciesMs));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/MetricsLoggerServiceTest.java b/services/tests/servicestests/src/com/android/server/connectivity/MetricsLoggerServiceTest.java
new file mode 100644
index 000000000000..5f84ea1bfd96
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/connectivity/MetricsLoggerServiceTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.content.Context;
+import android.net.ConnectivityMetricsEvent;
+import android.os.Bundle;
+import android.os.RemoteException;
+import static android.net.ConnectivityMetricsEvent.Reference;
+
+import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertArrayEquals;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/*
+ * TODO:
+ * - allow overriding MetricsLoggerService constants in tests.
+ * - test intents are correctly sent after the notification threshold.
+ * - test oldest events are correctly pushed out when internal deque is full.
+ * - test throttling triggers correctly.
+ */
+public class MetricsLoggerServiceTest extends TestCase {
+
+ static final int COMPONENT_TAG = 1;
+ static final long N_EVENTS = 10L;
+ static final ConnectivityMetricsEvent EVENTS[] = new ConnectivityMetricsEvent[(int)N_EVENTS];
+ static {
+ for (int i = 0; i < N_EVENTS; i++) {
+ EVENTS[i] = new ConnectivityMetricsEvent(i, COMPONENT_TAG, i, new Bundle());
+ }
+ }
+
+ static final ConnectivityMetricsEvent NO_EVENTS[] = new ConnectivityMetricsEvent[0];
+
+ @Mock Context mContext;
+ MetricsLoggerService mService;
+
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mService = new MetricsLoggerService(mContext);
+ mService.onStart();
+ }
+
+ public void testGetNoEvents() throws Exception {
+ Reference r = new Reference(0);
+ assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r));
+ assertEquals(0, r.getValue());
+ }
+
+ public void testLogAndGetEvents() throws Exception {
+ mService.mBinder.logEvents(EVENTS);
+
+ Reference r = new Reference(0);
+
+ assertArrayEquals(EVENTS, mService.mBinder.getEvents(r));
+ assertEquals(N_EVENTS, r.getValue());
+
+ assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r));
+ assertEquals(N_EVENTS, r.getValue());
+ }
+
+ public void testLogOneByOne() throws Exception {
+ for (ConnectivityMetricsEvent ev : EVENTS) {
+ mService.mBinder.logEvent(ev);
+ }
+
+ Reference r = new Reference(0);
+
+ assertArrayEquals(EVENTS, mService.mBinder.getEvents(r));
+ assertEquals(N_EVENTS, r.getValue());
+
+ assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r));
+ assertEquals(N_EVENTS, r.getValue());
+ }
+
+ public void testInterleavedLogAndGet() throws Exception {
+ mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 0, 3));
+
+ Reference r = new Reference(0);
+
+ assertArrayEquals(Arrays.copyOfRange(EVENTS, 0, 3), mService.mBinder.getEvents(r));
+ assertEquals(3, r.getValue());
+
+ mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 3, 8));
+ mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 8, 10));
+
+ assertArrayEquals(Arrays.copyOfRange(EVENTS, 3, 10), mService.mBinder.getEvents(r));
+ assertEquals(N_EVENTS, r.getValue());
+
+ assertArrayEquals(NO_EVENTS, mService.mBinder.getEvents(r));
+ assertEquals(N_EVENTS, r.getValue());
+ }
+
+ public void testMultipleGetAll() throws Exception {
+ mService.mBinder.logEvents(Arrays.copyOf(EVENTS, 3));
+
+ Reference r1 = new Reference(0);
+ assertArrayEquals(Arrays.copyOf(EVENTS, 3), mService.mBinder.getEvents(r1));
+ assertEquals(3, r1.getValue());
+
+ mService.mBinder.logEvents(Arrays.copyOfRange(EVENTS, 3, 10));
+
+ Reference r2 = new Reference(0);
+ assertArrayEquals(EVENTS, mService.mBinder.getEvents(r2));
+ assertEquals(N_EVENTS, r2.getValue());
+ }
+
+ public void testLogAndDumpConcurrently() throws Exception {
+ for (int i = 0; i < 50; i++) {
+ mContext = null;
+ mService = null;
+ setUp();
+ logAndDumpConcurrently();
+ }
+ }
+
+ public void logAndDumpConcurrently() throws Exception {
+ final CountDownLatch latch = new CountDownLatch((int)N_EVENTS);
+ final FileDescriptor fd = new FileOutputStream("/dev/null").getFD();
+
+ for (ConnectivityMetricsEvent ev : EVENTS) {
+ new Thread() {
+ public void run() {
+ mService.mBinder.logEvent(ev);
+ latch.countDown();
+ }
+ }.start();
+ }
+
+ new Thread() {
+ public void run() {
+ while (latch.getCount() > 0) {
+ mService.mBinder.dump(fd, new String[]{"--all"});
+ }
+ }
+ }.start();
+
+ latch.await(100, TimeUnit.MILLISECONDS);
+
+ Reference r = new Reference(0);
+ ConnectivityMetricsEvent[] got = mService.mBinder.getEvents(r);
+ Arrays.sort(got, new EventComparator());
+ assertArrayEquals(EVENTS, got);
+ assertEquals(N_EVENTS, r.getValue());
+ }
+
+ static class EventComparator implements Comparator<ConnectivityMetricsEvent> {
+ public int compare(ConnectivityMetricsEvent ev1, ConnectivityMetricsEvent ev2) {
+ return Long.compare(ev1.timestamp, ev2.timestamp);
+ }
+ public boolean equal(Object o) {
+ return o instanceof EventComparator;
+ }
+ };
+}
diff --git a/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 83a59fd85d29..d51f2d8152ac 100644
--- a/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -76,6 +76,7 @@ public class BuzzBeepBlinkTest extends AndroidTestCase {
mService.setVibrator(mVibrator);
mService.setSystemReady(true);
mService.setHandler(mHandler);
+ mService.setSystemNotificationSound("beep!");
}
//
diff --git a/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java b/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java
index b5698d5bd40b..3278cf1c0b71 100644
--- a/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/RateEstimatorTest.java
@@ -59,6 +59,15 @@ public class RateEstimatorTest extends AndroidTestCase {
}
@SmallTest
+ public void testInstantaneousBurstIsEstimatedUnderTwoPercent() throws Exception {
+ assertUpdateTime(mTestStartTime);
+ long eventStart = mTestStartTime + 1000; // start event a long time after initialization
+ long nextEventTime = postEvents(eventStart, 0, 5); // five events at \inf
+ final float rate = mEstimator.getRate(nextEventTime);
+ assertLessThan("Rate", rate, 20f);
+ }
+
+ @SmallTest
public void testCompactBurstIsEstimatedUnderTwoPercent() throws Exception {
assertUpdateTime(mTestStartTime);
long eventStart = mTestStartTime + 1000; // start event a long time after initialization
@@ -110,12 +119,19 @@ public class RateEstimatorTest extends AndroidTestCase {
assertLessThan("Rate", rate, 0.1f);
}
+ @SmallTest
+ public void testGetRateWithOneUpdate() throws Exception {
+ assertUpdateTime(mTestStartTime);
+ final float rate = mEstimator.getRate(mTestStartTime+1);
+ assertLessThan("Rate", rate, 1f);
+ }
+
private void assertLessThan(String label, float a, float b) {
- assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a < b);
+ assertTrue(String.format("%s was %f, but should be less than %f", label, a, b), a <= b);
}
private void assertGreaterThan(String label, float a, float b) {
- assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a > b);
+ assertTrue(String.format("%s was %f, but should be more than %f", label, a, b), a >= b);
}
/** @returns the next event time. */
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 69152d405ac0..71d1a3a64d19 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -52,6 +52,7 @@ import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.content.pm.ShortcutServiceInternal;
@@ -65,6 +66,7 @@ import android.os.Bundle;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
+import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
@@ -97,8 +99,11 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected static final String TAG = "ShortcutManagerTest";
@@ -113,6 +118,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected static final String[] EMPTY_STRINGS = new String[0]; // Just for readability.
+ protected static final String MAIN_ACTIVITY_CLASS = "MainActivity";
+
// public for mockito
public class BaseContext extends MockContext {
@Override
@@ -310,8 +317,55 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
@Override
- PackageInfo injectGetActivitiesWithMetadata(String packageName, @UserIdInt int userId) {
- return mContext.injectGetActivitiesWithMetadata(packageName, userId);
+ ActivityInfo injectGetActivityInfoWithMetadata(ComponentName activity,
+ @UserIdInt int userId) {
+ final PackageInfo pi = mContext.injectGetActivitiesWithMetadata(
+ activity.getPackageName(), userId);
+ if (pi == null || pi.activities == null) {
+ return null;
+ }
+ for (ActivityInfo ai : pi.activities) {
+ if (!mEnabledActivityChecker.test(ai.getComponentName(), userId)) {
+ continue;
+ }
+ if (activity.equals(ai.getComponentName())) {
+ return ai;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ boolean injectIsMainActivity(@NonNull ComponentName activity, int userId) {
+ if (!mEnabledActivityChecker.test(activity, userId)) {
+ return false;
+ }
+ return mMainActivityChecker.test(activity, userId);
+ }
+
+ @Override
+ List<ResolveInfo> injectGetMainActivities(@NonNull String packageName, int userId) {
+ final PackageInfo pi = mContext.injectGetActivitiesWithMetadata(
+ packageName, userId);
+ if (pi == null || pi.activities == null) {
+ return null;
+ }
+ final ArrayList<ResolveInfo> ret = new ArrayList<>(pi.activities.length);
+ for (int i = 0; i < pi.activities.length; i++) {
+ if (!mEnabledActivityChecker.test(pi.activities[i].getComponentName(), userId)) {
+ continue;
+ }
+ final ResolveInfo ri = new ResolveInfo();
+ ri.activityInfo = pi.activities[i];
+ ret.add(ri);
+ }
+
+ return ret;
+ }
+
+ @Override
+ ComponentName injectGetDefaultMainActivity(@NonNull String packageName, int userId) {
+ return mMainActivityFetcher.apply(packageName, userId);
}
@Override
@@ -334,6 +388,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
@Override
+ boolean injectIsSafeModeEnabled() {
+ return mSafeMode;
+ }
+
+ @Override
void wtf(String message, Exception e) {
// During tests, WTF is fatal.
fail(message + " exception: " + e);
@@ -440,6 +499,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected File mInjectedFilePathRoot;
+ protected boolean mSafeMode;
+
protected long mInjectedCurrentTimeMillis;
protected boolean mInjectedIsLowRamDevice;
@@ -511,6 +572,15 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage)
|| LAUNCHER_3.equals(callingPackage) || LAUNCHER_4.equals(callingPackage);
+ protected BiPredicate<ComponentName, Integer> mMainActivityChecker =
+ (activity, userId) -> true;
+
+ protected BiFunction<String, Integer, ComponentName> mMainActivityFetcher =
+ (packageName, userId) -> new ComponentName(packageName, MAIN_ACTIVITY_CLASS);
+
+ protected BiPredicate<ComponentName, Integer> mEnabledActivityChecker
+ = (activity, userId) -> true; // all activities are enabled.
+
protected static final long START_TIME = 1440000000101L;
protected static final long INTERVAL = 10000;
@@ -532,7 +602,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
static {
QUERY_ALL.setQueryFlags(
- ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+ ShortcutQuery.FLAG_GET_ALL_KINDS);
}
@Override
@@ -1050,10 +1120,6 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
+ "/" + ShortcutService.FILENAME_USER_PACKAGES, message);
}
- protected void waitOnMainThread() throws Throwable {
- runTestOnUiThread(() -> {});
- }
-
/**
* Make a shortcut with an ID.
*/
@@ -1134,6 +1200,12 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
}
+ protected ShortcutInfo makeShortcutWithIntent(String id, Intent intent) {
+ return makeShortcut(
+ id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
+ intent, /* rank =*/ 0);
+ }
+
protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity,
String title) {
return makeShortcut(
@@ -1153,10 +1225,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
*/
protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
Icon icon, Intent intent, int rank) {
- final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext)
- .setId(id)
+ final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
.setActivity(new ComponentName(mClientContext.getPackageName(), "dummy"))
- .setTitle(title)
+ .setShortLabel(title)
.setRank(rank)
.setIntent(intent);
if (icon != null) {
@@ -1173,6 +1244,23 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
/**
+ * Make a shortcut with details.
+ */
+ protected ShortcutInfo makeShortcutWithExtras(String id, Intent intent,
+ PersistableBundle extras) {
+ final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
+ .setActivity(new ComponentName(mClientContext.getPackageName(), "dummy"))
+ .setShortLabel("title-" + id)
+ .setExtras(extras)
+ .setIntent(intent);
+ final ShortcutInfo s = b.build();
+
+ s.setTimestamp(mInjectedCurrentTimeMillis); // HACK
+
+ return s;
+ }
+
+ /**
* Make an intent.
*/
protected Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) {
@@ -1387,6 +1475,13 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
return i;
}
+ protected Intent genPackageChangedIntent(String pakcageName, int userId) {
+ Intent i = new Intent(Intent.ACTION_PACKAGE_CHANGED);
+ i.setData(Uri.parse("package:" + pakcageName));
+ i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ return i;
+ }
+
protected Intent genPackageDataClear(String packageName, int userId) {
Intent i = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED);
i.setData(Uri.parse("package:" + packageName));
@@ -1434,7 +1529,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected static ShortcutQuery buildAllQuery(String packageName) {
final ShortcutQuery q = new ShortcutQuery();
q.setPackage(packageName);
- q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
+ q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
return q;
}
@@ -1445,6 +1540,12 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
return q;
}
+ protected static ShortcutQuery buildQueryWithFlags(int queryFlags) {
+ final ShortcutQuery q = new ShortcutQuery();
+ q.setQueryFlags(queryFlags);
+ return q;
+ }
+
protected void backupAndRestore() {
int prevUid = mInjectedCallingUid;
@@ -1584,4 +1685,38 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"))));
});
}
+
+ public static List<ShortcutInfo> assertAllHaveIconResId(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource());
+ assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllHaveIconFile(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource());
+ assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllHaveIcon(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId() + " has no icon ", s.hasIconFile() || s.hasIconResource());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllStringsResolved(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId(), s.hasStringResourcesResolved());
+ }
+ return actualShortcuts;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 56232c03ea4d..7d33a3004e3b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -19,9 +19,6 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamic;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamicOrPinned;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllEnabled;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIcon;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIconFile;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIconResId;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIntents;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveTitle;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllImmutable;
@@ -32,7 +29,6 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotKeyFieldsOnly;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotManifest;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllPinned;
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllStringsResolved;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllUnique;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBitmapSize;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBundleEmpty;
@@ -44,6 +40,7 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertDynamicShortcutCountExceeded;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertEmpty;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertForLauncherCallback;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertShortcutIds;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.filterByActivity;
@@ -54,6 +51,7 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.pfdToBitmap;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.resetAll;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.waitOnMainThread;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
@@ -88,6 +86,7 @@ import com.android.frameworks.servicestests.R;
import com.android.server.pm.ShortcutService.ConfigConstants;
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
import com.android.server.pm.ShortcutUser.PackageWithUser;
+import com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.ShortcutListAsserter;
import org.mockito.ArgumentCaptor;
@@ -95,6 +94,9 @@ import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
/**
* Tests for ShortcutService and ShortcutManager.
@@ -191,7 +193,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
+ ConfigConstants.KEY_ICON_FORMAT + "=WEBP,"
+ ConfigConstants.KEY_ICON_QUALITY + "=75");
assertEquals(123000, mService.getResetIntervalForTest());
- assertEquals(4, mService.getMaxDynamicShortcutsForTest());
+ assertEquals(4, mService.getMaxShortcutsForTest());
assertEquals(5, mService.getMaxUpdatesPerIntervalForTest());
assertEquals(100, mService.getMaxIconDimensionForTest());
assertEquals(CompressFormat.WEBP, mService.getIconPersistFormatForTest());
@@ -206,7 +208,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mService.getResetIntervalForTest());
assertEquals(ShortcutService.DEFAULT_MAX_SHORTCUTS_PER_APP,
- mService.getMaxDynamicShortcutsForTest());
+ mService.getMaxShortcutsForTest());
assertEquals(ShortcutService.DEFAULT_MAX_UPDATES_PER_INTERVAL,
mService.getMaxUpdatesPerIntervalForTest());
@@ -351,6 +353,127 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
+ public void testPublishWithNoActivity() {
+ // If activity is not explicitly set, use the default one.
+
+ runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+ // s1 and s3 has no activities.
+ final ShortcutInfo si1 = new ShortcutInfo.Builder(mClientContext, "si1")
+ .setShortLabel("label1")
+ .setIntent(new Intent("action1"))
+ .build();
+ final ShortcutInfo si2 = new ShortcutInfo.Builder(mClientContext, "si2")
+ .setShortLabel("label2")
+ .setActivity(new ComponentName(getCallingPackage(), "abc"))
+ .setIntent(new Intent("action2"))
+ .build();
+ final ShortcutInfo si3 = new ShortcutInfo.Builder(mClientContext, "si3")
+ .setShortLabel("label3")
+ .setIntent(new Intent("action3"))
+ .build();
+
+ // Set test 1
+ assertTrue(mManager.setDynamicShortcuts(list(si1)));
+
+ assertWith(getCallerShortcuts())
+ .haveIds("si1")
+ .forShortcutWithId("si1", si -> {
+ assertEquals(new ComponentName(getCallingPackage(),
+ MAIN_ACTIVITY_CLASS), si.getActivity());
+ });
+
+ // Set test 2
+ assertTrue(mManager.setDynamicShortcuts(list(si2, si1)));
+
+ assertWith(getCallerShortcuts())
+ .haveIds("si1", "si2")
+ .forShortcutWithId("si1", si -> {
+ assertEquals(new ComponentName(getCallingPackage(),
+ MAIN_ACTIVITY_CLASS), si.getActivity());
+ })
+ .forShortcutWithId("si2", si -> {
+ assertEquals(new ComponentName(getCallingPackage(),
+ "abc"), si.getActivity());
+ });
+
+
+ // Set test 3
+ assertTrue(mManager.setDynamicShortcuts(list(si3, si1)));
+
+ assertWith(getCallerShortcuts())
+ .haveIds("si1", "si3")
+ .forShortcutWithId("si1", si -> {
+ assertEquals(new ComponentName(getCallingPackage(),
+ MAIN_ACTIVITY_CLASS), si.getActivity());
+ })
+ .forShortcutWithId("si3", si -> {
+ assertEquals(new ComponentName(getCallingPackage(),
+ MAIN_ACTIVITY_CLASS), si.getActivity());
+ });
+
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling
+
+ // Add test 1
+ mManager.removeAllDynamicShortcuts();
+ assertTrue(mManager.addDynamicShortcuts(list(si1)));
+
+ assertWith(getCallerShortcuts())
+ .haveIds("si1")
+ .forShortcutWithId("si1", si -> {
+ assertEquals(new ComponentName(getCallingPackage(),
+ MAIN_ACTIVITY_CLASS), si.getActivity());
+ });
+
+ // Add test 2
+ mManager.removeAllDynamicShortcuts();
+ assertTrue(mManager.addDynamicShortcuts(list(si2, si1)));
+
+ assertWith(getCallerShortcuts())
+ .haveIds("si1", "si2")
+ .forShortcutWithId("si1", si -> {
+ assertEquals(new ComponentName(getCallingPackage(),
+ MAIN_ACTIVITY_CLASS), si.getActivity());
+ })
+ .forShortcutWithId("si2", si -> {
+ assertEquals(new ComponentName(getCallingPackage(),
+ "abc"), si.getActivity());
+ });
+
+
+ // Add test 3
+ mManager.removeAllDynamicShortcuts();
+ assertTrue(mManager.addDynamicShortcuts(list(si3, si1)));
+
+ assertWith(getCallerShortcuts())
+ .haveIds("si1", "si3")
+ .forShortcutWithId("si1", si -> {
+ assertEquals(new ComponentName(getCallingPackage(),
+ MAIN_ACTIVITY_CLASS), si.getActivity());
+ })
+ .forShortcutWithId("si3", si -> {
+ assertEquals(new ComponentName(getCallingPackage(),
+ MAIN_ACTIVITY_CLASS), si.getActivity());
+ });
+ });
+ }
+
+ public void testPublishWithNoActivity_noMainActivityInPackage() {
+ runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+ final ShortcutInfo si1 = new ShortcutInfo.Builder(mClientContext, "si1")
+ .setShortLabel("label1")
+ .setIntent(new Intent("action1"))
+ .build();
+
+ // Returning null means there's no main activity in this package.
+ mMainActivityFetcher = (packageName, userId) -> null;
+
+ assertExpectException(
+ RuntimeException.class, "Launcher activity not found for", () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(si1)));
+ });
+ });
+ }
+
public void testDeleteDynamicShortcuts() {
final ShortcutInfo si1 = makeShortcut("shortcut1");
final ShortcutInfo si2 = makeShortcut("shortcut2");
@@ -1102,6 +1225,117 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// TODO More tests: pinned but dynamic.
}
+ public void testGetShortcuts_shortcutKinds() throws Exception {
+ // Create 3 manifest and 3 dynamic shortcuts
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_3);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+
+ // Pin 2 and 3
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "ms3", "s2", "s3"),
+ HANDLE_USER_0);
+ });
+
+ // Remove ms3 and s3
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_2);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"))));
+ });
+
+ // Check their status.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1", "ms2", "ms3", "s1", "s2", "s3")
+
+ .selectByIds("ms1", "ms2")
+ .areAllManifest()
+ .areAllImmutable()
+ .areAllNotDynamic()
+
+ .revertToOriginalList()
+ .selectByIds("ms3")
+ .areAllNotManifest()
+ .areAllImmutable()
+ .areAllDisabled()
+ .areAllNotDynamic()
+
+ .revertToOriginalList()
+ .selectByIds("s1", "s2")
+ .areAllNotManifest()
+ .areAllMutable()
+ .areAllDynamic()
+
+ .revertToOriginalList()
+ .selectByIds("s3")
+ .areAllNotManifest()
+ .areAllMutable()
+ .areAllEnabled()
+ .areAllNotDynamic()
+
+ .revertToOriginalList()
+ .selectByIds("s1", "ms1")
+ .areAllNotPinned()
+
+ .revertToOriginalList()
+ .selectByIds("s2", "s3", "ms2", "ms3")
+ .areAllPinned()
+ ;
+ });
+
+ // Finally, actual tests.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertWith(mLauncherApps.getShortcuts(
+ buildQueryWithFlags(ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0))
+ .haveIds("s1", "s2");
+ assertWith(mLauncherApps.getShortcuts(
+ buildQueryWithFlags(ShortcutQuery.FLAG_GET_MANIFEST), HANDLE_USER_0))
+ .haveIds("ms1", "ms2");
+ assertWith(mLauncherApps.getShortcuts(
+ buildQueryWithFlags(ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0))
+ .haveIds("s2", "s3", "ms2", "ms3");
+
+ assertWith(mLauncherApps.getShortcuts(
+ buildQueryWithFlags(
+ ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED
+ ), HANDLE_USER_0))
+ .haveIds("s1", "s2", "s3", "ms2", "ms3");
+
+ assertWith(mLauncherApps.getShortcuts(
+ buildQueryWithFlags(
+ ShortcutQuery.FLAG_GET_MANIFEST | ShortcutQuery.FLAG_GET_PINNED
+ ), HANDLE_USER_0))
+ .haveIds("ms1", "s2", "s3", "ms2", "ms3");
+
+ assertWith(mLauncherApps.getShortcuts(
+ buildQueryWithFlags(
+ ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_MANIFEST
+ ), HANDLE_USER_0))
+ .haveIds("ms1", "ms2", "s1", "s2");
+
+ assertWith(mLauncherApps.getShortcuts(
+ buildQueryWithFlags(
+ ShortcutQuery.FLAG_GET_ALL_KINDS
+ ), HANDLE_USER_0))
+ .haveIds("ms1", "ms2", "ms3", "s1", "s2", "s3");
+ });
+ }
+
public void testGetShortcuts_resolveStrings() throws Exception {
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
ShortcutInfo si = new ShortcutInfo.Builder(mClientContext)
@@ -2223,137 +2457,167 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
}
public void testLauncherCallback() throws Throwable {
- LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
-
- // Set listeners
-
- runWithCaller(LAUNCHER_1, USER_0, () -> {
- mLauncherApps.registerCallback(c0, new Handler(Looper.getMainLooper()));
- });
+ // Disable throttling for this test.
+ mService.updateConfigurationLocked(
+ ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=99999999,"
+ + ConfigConstants.KEY_MAX_SHORTCUTS + "=99999999"
+ );
- runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- assertTrue(mManager.setDynamicShortcuts(list(
- makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
- });
+ setCaller(LAUNCHER_1, USER_0);
- waitOnMainThread();
- ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
- verify(c0).onShortcutsChanged(
- eq(CALLING_PACKAGE_1),
- shortcuts.capture(),
- eq(HANDLE_USER_0)
- );
- assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
- "s1", "s2", "s3");
+ assertForLauncherCallback(mLauncherApps, () -> {
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+ }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+ .haveIds("s1", "s2", "s3")
+ .areAllWithKeyFieldsOnly()
+ .areAllDynamic();
// From different package.
- reset(c0);
- runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
- assertTrue(mManager.setDynamicShortcuts(list(
- makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
- });
- waitOnMainThread();
- shortcuts = ArgumentCaptor.forClass(List.class);
- verify(c0).onShortcutsChanged(
- eq(CALLING_PACKAGE_2),
- shortcuts.capture(),
- eq(HANDLE_USER_0)
- );
- assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
- "s1", "s2", "s3");
+ assertForLauncherCallback(mLauncherApps, () -> {
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+ }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_2, HANDLE_USER_0)
+ .haveIds("s1", "s2", "s3")
+ .areAllWithKeyFieldsOnly()
+ .areAllDynamic();
// Different user, callback shouldn't be called.
- reset(c0);
- runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
- assertTrue(mManager.setDynamicShortcuts(list(
- makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
- });
- waitOnMainThread();
- verify(c0, times(0)).onShortcutsChanged(
- anyString(),
- any(List.class),
- any(UserHandle.class)
- );
+ assertForLauncherCallback(mLauncherApps, () -> {
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+ }).assertNoCallbackCalled();
- // Test for addDynamicShortcuts.
- reset(c0);
- runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- dumpsysOnLogcat("before addDynamicShortcuts");
- assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s4"))));
- });
- waitOnMainThread();
- shortcuts = ArgumentCaptor.forClass(List.class);
- verify(c0).onShortcutsChanged(
- eq(CALLING_PACKAGE_1),
- shortcuts.capture(),
- eq(HANDLE_USER_0)
- );
- assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
- "s1", "s2", "s3", "s4");
+ // Test for addDynamicShortcuts.
+ assertForLauncherCallback(mLauncherApps, () -> {
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s4"))));
+ });
+ }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+ .haveIds("s1", "s2", "s3", "s4")
+ .areAllWithKeyFieldsOnly()
+ .areAllDynamic();
// Test for remove
- reset(c0);
- runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- mManager.removeDynamicShortcuts(list("s1"));
- });
-
- waitOnMainThread();
- shortcuts = ArgumentCaptor.forClass(List.class);
- verify(c0).onShortcutsChanged(
- eq(CALLING_PACKAGE_1),
- shortcuts.capture(),
- eq(HANDLE_USER_0)
- );
- assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
- "s2", "s3", "s4");
+ assertForLauncherCallback(mLauncherApps, () -> {
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ mManager.removeDynamicShortcuts(list("s1"));
+ });
+ }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+ .haveIds("s2", "s3", "s4")
+ .areAllWithKeyFieldsOnly()
+ .areAllDynamic();
// Test for update
- reset(c0);
+ assertForLauncherCallback(mLauncherApps, () -> {
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.updateShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"))));
+ });
+ }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+ // All remaining shortcuts will be passed regardless of what's been updated.
+ .haveIds("s2", "s3", "s4")
+ .areAllWithKeyFieldsOnly()
+ .areAllDynamic();
+
+ // Test for deleteAll
+ assertForLauncherCallback(mLauncherApps, () -> {
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ mManager.removeAllDynamicShortcuts();
+ });
+ }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+ .isEmpty();
+
+ // Update package1 with manifest shortcuts
+ assertForLauncherCallback(mLauncherApps, () -> {
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_2);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+ }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+ .areAllManifest()
+ .areAllWithKeyFieldsOnly()
+ .haveIds("ms1", "ms2");
+
+ // Make sure pinned shortcuts are passed too.
+ // 1. Add dynamic shortcuts.
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- assertTrue(mManager.updateShortcuts(list(
+ assertTrue(mManager.setDynamicShortcuts(list(
makeShortcut("s1"), makeShortcut("s2"))));
});
- waitOnMainThread();
- shortcuts = ArgumentCaptor.forClass(List.class);
- verify(c0).onShortcutsChanged(
- eq(CALLING_PACKAGE_1),
- shortcuts.capture(),
- eq(HANDLE_USER_0)
- );
- assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
- "s2", "s3", "s4");
-
- // Test for deleteAll
- reset(c0);
+ // 2. Pin some.
+ runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_0);
+ });
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
- mManager.removeAllDynamicShortcuts();
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1", "ms2", "s1", "s2")
+ .areAllEnabled()
+
+ .selectByIds("ms1", "ms2")
+ .areAllManifest()
+
+ .revertToOriginalList()
+ .selectByIds("s1", "s2")
+ .areAllDynamic()
+ ;
});
- waitOnMainThread();
- shortcuts = ArgumentCaptor.forClass(List.class);
- verify(c0).onShortcutsChanged(
- eq(CALLING_PACKAGE_1),
- shortcuts.capture(),
- eq(HANDLE_USER_0)
- );
- assertEquals(0, shortcuts.getValue().size());
+ // 3 Update the app with no manifest shortcuts. (Pinned one will survive.)
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_0);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
- // Remove CALLING_PACKAGE_2
- reset(c0);
- uninstallPackage(USER_0, CALLING_PACKAGE_2);
- mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_0, USER_0);
+ assertForLauncherCallback(mLauncherApps, () -> {
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ mManager.removeDynamicShortcuts(list("s2"));
+
+ assertWith(getCallerShortcuts())
+ .haveIds("ms2", "s1", "s2")
+
+ .selectByIds("ms2")
+ .areAllNotManifest()
+ .areAllPinned()
+ .areAllImmutable()
+ .areAllDisabled()
+
+ .revertToOriginalList()
+ .selectByIds("s1")
+ .areAllDynamic()
+ .areAllNotPinned()
+ .areAllEnabled()
+
+ .revertToOriginalList()
+ .selectByIds("s2")
+ .areAllNotDynamic()
+ .areAllPinned()
+ .areAllEnabled()
+ ;
+ });
+ }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+ .haveIds("ms2", "s1", "s2")
+ .areAllWithKeyFieldsOnly();
- // Should get a callback with an empty list.
- waitOnMainThread();
- shortcuts = ArgumentCaptor.forClass(List.class);
- verify(c0).onShortcutsChanged(
- eq(CALLING_PACKAGE_2),
- shortcuts.capture(),
- eq(HANDLE_USER_0)
- );
- assertEquals(0, shortcuts.getValue().size());
+ // Remove CALLING_PACKAGE_2
+ assertForLauncherCallback(mLauncherApps, () -> {
+ uninstallPackage(USER_0, CALLING_PACKAGE_2);
+ mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_0, USER_0,
+ /* appStillExists = */ false);
+ }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_2, HANDLE_USER_0)
+ .isEmpty();
}
public void testLauncherCallback_crossProfile() throws Throwable {
@@ -2753,7 +3017,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Nonexistent package.
uninstallPackage(USER_0, "abc");
- mService.cleanUpPackageLocked("abc", USER_0, USER_0);
+ mService.cleanUpPackageLocked("abc", USER_0, USER_0, /* appStillExists = */ false);
// No changes.
assertEquals(set(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
@@ -2785,7 +3049,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Remove a package.
uninstallPackage(USER_0, CALLING_PACKAGE_1);
- mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0, USER_0);
+ mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0, USER_0,
+ /* appStillExists = */ false);
assertEquals(set(CALLING_PACKAGE_2),
hashSet(user0.getAllPackagesForTest().keySet()));
@@ -2816,7 +3081,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Remove a launcher.
uninstallPackage(USER_10, LAUNCHER_1);
- mService.cleanUpPackageLocked(LAUNCHER_1, USER_10, USER_10);
+ mService.cleanUpPackageLocked(LAUNCHER_1, USER_10, USER_10, /* appStillExists = */ false);
assertEquals(set(CALLING_PACKAGE_2),
hashSet(user0.getAllPackagesForTest().keySet()));
@@ -2844,7 +3109,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Remove a package.
uninstallPackage(USER_10, CALLING_PACKAGE_2);
- mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10, USER_10);
+ mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10, USER_10,
+ /* appStillExists = */ false);
assertEquals(set(CALLING_PACKAGE_2),
hashSet(user0.getAllPackagesForTest().keySet()));
@@ -2872,7 +3138,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Remove the other launcher from user 10 too.
uninstallPackage(USER_10, LAUNCHER_2);
- mService.cleanUpPackageLocked(LAUNCHER_2, USER_10, USER_10);
+ mService.cleanUpPackageLocked(LAUNCHER_2, USER_10, USER_10,
+ /* appStillExists = */ false);
assertEquals(set(CALLING_PACKAGE_2),
hashSet(user0.getAllPackagesForTest().keySet()));
@@ -2900,7 +3167,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// More remove.
uninstallPackage(USER_10, CALLING_PACKAGE_1);
- mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10, USER_10);
+ mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10, USER_10,
+ /* appStillExists = */ false);
assertEquals(set(CALLING_PACKAGE_2),
hashSet(user0.getAllPackagesForTest().keySet()));
@@ -2926,6 +3194,74 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mService.saveDirtyInfo();
}
+ public void testCleanupPackage_republishManifests() {
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_2);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+ });
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+ list("s2", "s3", "ms1", "ms2"), HANDLE_USER_0);
+ });
+
+ // Remove ms2 from manifest.
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_1);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"))));
+
+ // Make sure the shortcuts are in the intended state.
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1", "ms2", "s1", "s2", "s3")
+
+ .selectByIds("ms1")
+ .areAllManifest()
+ .areAllPinned()
+
+ .revertToOriginalList()
+ .selectByIds("ms2")
+ .areAllNotManifest()
+ .areAllPinned()
+
+ .revertToOriginalList()
+ .selectByIds("s1")
+ .areAllDynamic()
+ .areAllNotPinned()
+
+ .revertToOriginalList()
+ .selectByIds("s2")
+ .areAllDynamic()
+ .areAllPinned()
+
+ .revertToOriginalList()
+ .selectByIds("s3")
+ .areAllNotDynamic()
+ .areAllPinned();
+ });
+
+ // Clean up + re-publish manifests.
+ mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0, USER_0,
+ /* appStillExists = */ true);
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1")
+ .areAllManifest();
+ });
+ }
+
public void testHandleGonePackage_crossProfile() {
// Create some shortcuts.
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -3237,6 +3573,20 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertTrue(mManager.addDynamicShortcuts(list(
makeShortcutWithIcon("s1", bmp32x32), makeShortcutWithIcon("s2", bmp32x32)
)));
+ // Also add a manifest shortcut, which should be removed too.
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_1);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("s1", "s2", "ms1")
+
+ .selectManifest()
+ .haveIds("ms1");
+ });
setCaller(CALLING_PACKAGE_2, USER_0);
assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
@@ -3412,8 +3762,47 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
}
- public void testHandlePackageUpdate() throws Throwable {
+ public void testHandlePackageClearData_manifestRepublished() {
+
+ // Add two manifests and two dynamics.
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_2);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertTrue(mManager.addDynamicShortcuts(list(
+ makeShortcut("s1"), makeShortcut("s2"))));
+ });
+ runWithCaller(LAUNCHER_1, USER_10, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms2", "s2"), HANDLE_USER_10);
+ });
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1", "ms2", "s1", "s2")
+ .areAllEnabled()
+
+ .selectPinned()
+ .haveIds("ms2", "s2");
+ });
+
+ // Clear data
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageDataClear(CALLING_PACKAGE_1, USER_10));
+
+ // Only manifest shortcuts will remain, and are no longer pinned.
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1", "ms2")
+ .areAllEnabled()
+ .areAllNotPinned();
+ });
+ }
+ public void testHandlePackageUpdate() throws Throwable {
// Set up shortcuts and launchers.
final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
@@ -3677,6 +4066,202 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
+ public void testHandlePackageChanged() {
+ final ComponentName ACTIVITY1 = new ComponentName(CALLING_PACKAGE_1, "act1");
+ final ComponentName ACTIVITY2 = new ComponentName(CALLING_PACKAGE_1, "act2");
+
+ addManifestShortcutResource(ACTIVITY1, R.xml.shortcut_1);
+ addManifestShortcutResource(ACTIVITY2, R.xml.shortcut_1_alt);
+
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertTrue(mManager.addDynamicShortcuts(list(
+ makeShortcutWithActivity("s1", ACTIVITY1),
+ makeShortcutWithActivity("s2", ACTIVITY2)
+ )));
+ });
+ runWithCaller(LAUNCHER_1, USER_10, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1-alt", "s2"), HANDLE_USER_10);
+ });
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1", "ms1-alt", "s1", "s2")
+ .areAllEnabled()
+
+ .selectPinned()
+ .haveIds("ms1-alt", "s2")
+
+ .revertToOriginalList()
+ .selectByIds("ms1", "s1")
+ .areAllWithActivity(ACTIVITY1)
+
+ .revertToOriginalList()
+ .selectByIds("ms1-alt", "s2")
+ .areAllWithActivity(ACTIVITY2)
+ ;
+ });
+
+ // First, no changes.
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1", "ms1-alt", "s1", "s2")
+ .areAllEnabled()
+
+ .selectPinned()
+ .haveIds("ms1-alt", "s2")
+
+ .revertToOriginalList()
+ .selectByIds("ms1", "s1")
+ .areAllWithActivity(ACTIVITY1)
+
+ .revertToOriginalList()
+ .selectByIds("ms1-alt", "s2")
+ .areAllWithActivity(ACTIVITY2)
+ ;
+ });
+
+ // Disable activity 1
+ mEnabledActivityChecker = (activity, userId) -> !ACTIVITY1.equals(activity);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1-alt", "s2")
+ .areAllEnabled()
+
+ .selectPinned()
+ .haveIds("ms1-alt", "s2")
+
+ .revertToOriginalList()
+ .selectByIds("ms1-alt", "s2")
+ .areAllWithActivity(ACTIVITY2)
+ ;
+ });
+
+ // Re-enable activity 1.
+ // Manifest shortcuts will be re-published, but dynamic ones are not.
+ mEnabledActivityChecker = (activity, userId) -> true;
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1", "ms1-alt", "s2")
+ .areAllEnabled()
+
+ .selectPinned()
+ .haveIds("ms1-alt", "s2")
+
+ .revertToOriginalList()
+ .selectByIds("ms1")
+ .areAllWithActivity(ACTIVITY1)
+
+ .revertToOriginalList()
+ .selectByIds("ms1-alt", "s2")
+ .areAllWithActivity(ACTIVITY2)
+ ;
+ });
+
+ // Disable activity 2
+ // Because "ms1-alt" and "s2" are both pinned, they will remain, but disabled.
+ mEnabledActivityChecker = (activity, userId) -> !ACTIVITY2.equals(activity);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("ms1", "ms1-alt", "s2")
+
+ .selectDynamic().isEmpty().revertToOriginalList() // no dynamics.
+
+ .selectPinned()
+ .haveIds("ms1-alt", "s2")
+ .areAllDisabled()
+
+ .revertToOriginalList()
+ .selectByIds("ms1")
+ .areAllWithActivity(ACTIVITY1)
+ .areAllEnabled()
+ ;
+ });
+ }
+
+ public void testHandlePackageUpdate_activityNoLongerMain() throws Throwable {
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcutWithActivity("s1a",
+ new ComponentName(getCallingPackage(), "act1")),
+ makeShortcutWithActivity("s1b",
+ new ComponentName(getCallingPackage(), "act1")),
+ makeShortcutWithActivity("s2a",
+ new ComponentName(getCallingPackage(), "act2")),
+ makeShortcutWithActivity("s2b",
+ new ComponentName(getCallingPackage(), "act2")),
+ makeShortcutWithActivity("s3a",
+ new ComponentName(getCallingPackage(), "act3")),
+ makeShortcutWithActivity("s3b",
+ new ComponentName(getCallingPackage(), "act3"))
+ )));
+ assertWith(getCallerShortcuts())
+ .haveIds("s1a", "s1b", "s2a", "s2b", "s3a", "s3b")
+ .areAllDynamic();
+ });
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+ list("s1b", "s2b", "s3b"),
+ HANDLE_USER_0);
+ });
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("s1a", "s1b", "s2a", "s2b", "s3a", "s3b")
+ .areAllDynamic()
+
+ .selectByIds("s1b", "s2b", "s3b")
+ .areAllPinned();
+ });
+
+ // Update the app and act2 and act3 are no longer main.
+ mMainActivityChecker = (activity, userId) -> {
+ return activity.getClassName().equals("act1");
+ };
+
+ setCaller(LAUNCHER_1, USER_0);
+ assertForLauncherCallback(mLauncherApps, () -> {
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
+ }).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
+ // Make sure the launcher gets callbacks.
+ .haveIds("s1a", "s1b", "s2b", "s3b")
+ .areAllWithKeyFieldsOnly();
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ // s2a and s3a are gone, but s2b and s3b will remain because they're pinned, and
+ // disabled.
+ assertWith(getCallerShortcuts())
+ .haveIds("s1a", "s1b", "s2b", "s3b")
+
+ .selectByIds("s1a", "s1b")
+ .areAllDynamic()
+ .areAllEnabled()
+
+ .revertToOriginalList()
+ .selectByIds("s2b", "s3b")
+ .areAllNotDynamic()
+ .areAllDisabled()
+ .areAllPinned()
+ ;
+ });
+ }
+
protected void prepareForBackupTest() {
prepareCrossProfileDataSet();
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 428b8723c2d2..f570ff24ce36 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -15,8 +15,11 @@
*/
package com.android.server.pm;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBundlesEqual;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.parceled;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
@@ -35,12 +38,14 @@ import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
+import android.net.Uri;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.frameworks.servicestests.R;
+import com.android.server.pm.ShortcutService.ConfigConstants;
/**
* Tests for ShortcutService and ShortcutManager.
@@ -67,18 +72,68 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
"ID must be provided",
() -> new ShortcutInfo.Builder(getTestContext()).build());
- assertExpectException(NullPointerException.class, "Intent action must be set",
- () -> new ShortcutInfo.Builder(getTestContext()).setIntent(new Intent()));
+ assertExpectException(
+ RuntimeException.class,
+ "id cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), null));
- assertExpectException(NullPointerException.class, "Activity must be provided", () -> {
- ShortcutInfo si = new ShortcutInfo.Builder(getTestContext()).setId("id").build();
- assertTrue(getManager().setDynamicShortcuts(list(si)));
- });
+ assertExpectException(
+ RuntimeException.class,
+ "id cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), ""));
+
+ assertExpectException(
+ RuntimeException.class,
+ "intent cannot be null",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "action must be set",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
+
+ assertExpectException(
+ RuntimeException.class,
+ "activity cannot be null",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setActivity(null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "shortLabel cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setShortLabel(null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "shortLabel cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setShortLabel(""));
+
+ assertExpectException(
+ RuntimeException.class,
+ "longLabel cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setLongLabel(null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "longLabel cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setLongLabel(""));
+
+ assertExpectException(
+ RuntimeException.class,
+ "disabledMessage cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "disabledMessage cannot be empty",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(""));
+
+ assertExpectException(NullPointerException.class, "action must be set",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
+ // same for add.
assertExpectException(
IllegalArgumentException.class, "Short label must be provided", () -> {
- ShortcutInfo si = new ShortcutInfo.Builder(getTestContext())
- .setId("id")
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
.setActivity(new ComponentName(getTestContext().getPackageName(), "s"))
.build();
assertTrue(getManager().setDynamicShortcuts(list(si)));
@@ -86,25 +141,24 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertExpectException(
IllegalArgumentException.class, "Short label must be provided", () -> {
- ShortcutInfo si = new ShortcutInfo.Builder(getTestContext())
- .setId("id")
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
.setActivity(new ComponentName(getTestContext().getPackageName(), "s"))
.build();
assertTrue(getManager().addDynamicShortcuts(list(si)));
});
+ // same for add.
assertExpectException(NullPointerException.class, "Intent must be provided", () -> {
- ShortcutInfo si = new ShortcutInfo.Builder(getTestContext())
- .setId("id")
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
.setActivity(new ComponentName(getTestContext().getPackageName(), "s"))
.setShortLabel("x")
.build();
assertTrue(getManager().setDynamicShortcuts(list(si)));
});
+ // same for add.
assertExpectException(NullPointerException.class, "Intent must be provided", () -> {
- ShortcutInfo si = new ShortcutInfo.Builder(getTestContext())
- .setId("id")
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
.setActivity(new ComponentName(getTestContext().getPackageName(), "s"))
.setShortLabel("x")
.build();
@@ -112,18 +166,17 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
});
assertExpectException(
- IllegalStateException.class, "package name mismatch", () -> {
- ShortcutInfo si = new ShortcutInfo.Builder(getTestContext())
- .setId("id")
+ IllegalStateException.class, "does not belong to package", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
.setActivity(new ComponentName("xxx", "s"))
.build();
assertTrue(getManager().setDynamicShortcuts(list(si)));
});
+ // same for add.
assertExpectException(
- IllegalStateException.class, "package name mismatch", () -> {
- ShortcutInfo si = new ShortcutInfo.Builder(getTestContext())
- .setId("id")
+ IllegalStateException.class, "does not belong to package", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
.setActivity(new ComponentName("xxx", "s"))
.build();
assertTrue(getManager().addDynamicShortcuts(list(si)));
@@ -329,7 +382,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals("id", si.getId());
- assertEquals(null, si.getActivity());
+ assertEquals(new ComponentName("a", "b"), si.getActivity());
assertEquals(null, si.getIcon());
assertEquals(null, si.getTitle());
assertEquals(null, si.getText());
@@ -445,7 +498,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(mClientContext.getPackageName(), si.getPackage());
assertEquals("id", si.getId());
- assertEquals(null, si.getActivity());
+ assertEquals(new ComponentName("a", "b"), si.getActivity());
assertEquals(null, si.getIcon());
assertEquals(0, si.getTitleResId());
assertEquals(null, si.getTitleResName());
@@ -777,6 +830,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setRank(123)
.setExtras(pb)
.build();
+ sorig.setTimestamp(mInjectedCurrentTimeMillis);
ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
.setId("id2")
@@ -785,11 +839,13 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(456)
.build();
+ sorig2.setTimestamp(mInjectedCurrentTimeMillis);
mManager.addDynamicShortcuts(list(sorig, sorig2));
- Thread.sleep(2);
- final long now = System.currentTimeMillis();
+ mInjectedCurrentTimeMillis += 1;
+ final long now = mInjectedCurrentTimeMillis;
+ mInjectedCurrentTimeMillis += 1;
// Save and load.
mService.saveDirtyInfo();
@@ -845,6 +901,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setRank(123)
.setExtras(pb)
.build();
+ sorig.setTimestamp(mInjectedCurrentTimeMillis);
ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
.setId("id2")
@@ -853,11 +910,13 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(456)
.build();
+ sorig2.setTimestamp(mInjectedCurrentTimeMillis);
mManager.addDynamicShortcuts(list(sorig, sorig2));
- Thread.sleep(2);
- final long now = System.currentTimeMillis();
+ mInjectedCurrentTimeMillis += 1;
+ final long now = mInjectedCurrentTimeMillis;
+ mInjectedCurrentTimeMillis += 1;
// Save and load.
mService.saveDirtyInfo();
@@ -1030,6 +1089,63 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(0, si.getRank());
}
+ private void checkShortcutInfoSaveAndLoad_intents(Intent intent) {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcutWithIntent("s1", intent))));
+ initService();
+ mService.handleUnlockUser(USER_0);
+
+ assertWith(getCallerShortcuts())
+ .haveIds("s1")
+ .forShortcutWithId("s1", si -> {
+ assertEquals(intent.getAction(), si.getIntent().getAction());
+ assertEquals(intent.getData(), si.getIntent().getData());
+ assertEquals(intent.getComponent(), si.getIntent().getComponent());
+ assertBundlesEqual(intent.getExtras(), si.getExtras());
+ });
+ }
+
+ public void testShortcutInfoSaveAndLoad_intents() {
+ checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW));
+
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
+
+ checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN));
+
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
+
+ checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW,
+ Uri.parse("http://www.example.com/")));
+
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
+
+ checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN,
+ Uri.parse("http://www.example.com/")));
+
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
+
+ checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW)
+ .setComponent(new ComponentName("a", "b")));
+
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
+
+ checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN)
+ .setComponent(new ComponentName("a", "b")));
+
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
+
+ checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW)
+ .putExtras(makeBundle("a", "b")));
+
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
+
+
+ checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN)
+ .putExtras(makeBundle("a", "b")));
+
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
+ }
+
public void testThrottling() {
final ShortcutInfo si1 = makeShortcut("shortcut1");
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
new file mode 100644
index 000000000000..a36c0adea5dc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.pm;
+
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBundlesEqual;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makePersistableBundle;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+
+public class ShortcutManagerTest4 extends BaseShortcutManagerTest {
+
+ private static Bundle sIntentExtras = makeBundle(
+ "key{\u0000}", "value{\u0000}",
+ "key{\u0001}", "value{\u0001}",
+ "key{\u001f}", "value{\u001f}",
+ "key{\u007f}", "value{\u007f}",
+
+ "key{\ud800\udc00}", "value{\ud800\udc00}",
+ "key{\ud801\udc01}", "value{\ud801\udc01}",
+ "key{\udbff\udfff}", "value{\udbff\udfff}",
+
+ "key{\ud801}x", 1, // broken surrogate pair
+ "key{\uDC01}\"x", 2, // broken surrogate pair
+
+ "x1", "value{\ud801}x", // broken surrogate pair
+ "x2", "value{\uDC01}\"x" // broken surrogate pair
+ );
+
+ // Same as above, except broken surrogate pairs are replaced with '?'s.
+ private static Bundle sIntentExtrasDecoded = makeBundle(
+ "key{\u0000}", "value{\u0000}",
+ "key{\u0001}", "value{\u0001}",
+ "key{\u001f}", "value{\u001f}",
+ "key{\u007f}", "value{\u007f}",
+
+ "key{\ud800\udc00}", "value{\ud800\udc00}",
+ "key{\ud801\udc01}", "value{\ud801\udc01}",
+ "key{\udbff\udfff}", "value{\udbff\udfff}",
+
+ "key{?}x", 1,
+ "key{?}\"x", 2,
+
+ "x1", "value{?}x",
+ "x2", "value{?}\"x"
+ );
+
+ private static PersistableBundle sShortcutExtras = makePersistableBundle(
+ "key{\u0000}", "value{\u0000}",
+ "key{\u0001}", "value{\u0001}",
+ "key{\u001f}", "value{\u001f}",
+ "key{\u007f}", "value{\u007f}",
+
+ "key{\ud800\udc00}", "value{\ud800\udc00}",
+ "key{\ud801\udc01}", "value{\ud801\udc01}",
+ "key{\udbff\udfff}", "value{\udbff\udfff}",
+
+ "key{\ud801}", 1, // broken surrogate pair
+ "key{\uDC01}", 2, // broken surrogate pair
+
+ "x1", "value{\ud801}", // broken surrogate pair
+ "x2", "value{\uDC01}" // broken surrogate pair
+ );
+
+ // Same as above, except broken surrogate pairs are replaced with '?'s.
+ private static PersistableBundle sShortcutExtrasDecoded = makePersistableBundle(
+ "key{\u0000}", "value{\u0000}",
+ "key{\u0001}", "value{\u0001}",
+ "key{\u001f}", "value{\u001f}",
+ "key{\u007f}", "value{\u007f}",
+
+ "key{\ud800\udc00}", "value{\ud800\udc00}",
+ "key{\ud801\udc01}", "value{\ud801\udc01}",
+ "key{\udbff\udfff}", "value{\udbff\udfff}",
+
+ "key{?}", 1,
+ "key{?}", 2,
+
+ "x1", "value{?}",
+ "x2", "value{?}"
+ );
+
+ public void testPersistingWeirdCharacters() {
+ final Intent intent = new Intent(Intent.ACTION_VIEW)
+ .putExtras(sIntentExtras);
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcutWithExtras("s1", intent, sShortcutExtras),
+ makeShortcut("s{\u0000}{\u0001}{\uD800\uDC00}x[\uD801][\uDC01]")
+ )));
+ });
+
+ // Make sure save & load works fine. (i.e. shouldn't crash even with invalid characters.)
+ initService();
+ mService.handleUnlockUser(USER_0);
+
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerShortcuts())
+ .haveIds("s1", "s{\u0000}{\u0001}{\uD800\uDC00}x[?][?]")
+ .forShortcutWithId("s1", si -> {
+ assertBundlesEqual(si.getIntent().getExtras(), sIntentExtrasDecoded);
+ assertBundlesEqual(si.getExtras(), sShortcutExtrasDecoded);
+ });
+ });
+ }
+} \ No newline at end of file
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index 712bc1e8c301..7d7285a24a04 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -18,14 +18,17 @@ package com.android.server.pm.shortcutmanagertest;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNotSame;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyList;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -34,13 +37,17 @@ import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.Callback;
import android.content.pm.ShortcutInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.BaseBundle;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
import android.os.UserHandle;
import android.test.MoreAsserts;
import android.util.ArraySet;
@@ -52,6 +59,7 @@ import junit.framework.AssertionFailedError;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import java.io.BufferedReader;
@@ -67,6 +75,7 @@ import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.concurrent.CountDownLatch;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -166,7 +175,8 @@ public class ShortcutManagerTestUtils {
}
public static void setDefaultLauncher(Instrumentation instrumentation, String component) {
- runCommandForNoOutput(instrumentation, "cmd package set-home-activity " + component);
+ runCommand(instrumentation, "cmd package set-home-activity " + component,
+ result -> result.contains("Success"));
}
public static void setDefaultLauncher(Instrumentation instrumentation, Context packageContext) {
@@ -200,6 +210,7 @@ public class ShortcutManagerTestUtils {
if (!ENABLE_DUMPSYS) {
return;
}
+ Log.e(TAG, "Dumpsys shortcut");
for (String s : runCommand(instrumentation, "dumpsys shortcut")) {
Log.e(TAG, s);
}
@@ -232,6 +243,33 @@ public class ShortcutManagerTestUtils {
return ret;
}
+ public static PersistableBundle makePersistableBundle(Object... keysAndValues) {
+ assertTrue((keysAndValues.length % 2) == 0);
+
+ if (keysAndValues.length == 0) {
+ return null;
+ }
+ final PersistableBundle ret = new PersistableBundle();
+
+ for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
+ final String key = keysAndValues[i].toString();
+ final Object value = keysAndValues[i + 1];
+
+ if (value == null) {
+ ret.putString(key, null);
+ } else if (value instanceof Integer) {
+ ret.putInt(key, (Integer) value);
+ } else if (value instanceof String) {
+ ret.putString(key, (String) value);
+ } else if (value instanceof PersistableBundle) {
+ ret.putPersistableBundle(key, (PersistableBundle) value);
+ } else {
+ fail("Type not supported yet: " + value.getClass().getName());
+ }
+ }
+ return ret;
+ }
+
public static <T> List<T> list(T... array) {
return Arrays.asList(array);
}
@@ -280,7 +318,7 @@ public class ShortcutManagerTestUtils {
ComponentName activity) {
return filter(list, si ->
(si.getActivity().equals(activity)
- && (si.isManifestShortcut() || si.isDynamic())));
+ && (si.isDeclaredInManifest() || si.isDynamic())));
}
public static List<ShortcutInfo> changedSince(List<ShortcutInfo> list, long time) {
@@ -377,32 +415,6 @@ public class ShortcutManagerTestUtils {
return actualShortcuts;
}
- public static List<ShortcutInfo> assertAllHaveIconResId(
- List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource());
- assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile());
- }
- return actualShortcuts;
- }
-
- public static List<ShortcutInfo> assertAllHaveIconFile(
- List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource());
- assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile());
- }
- return actualShortcuts;
- }
-
- public static List<ShortcutInfo> assertAllHaveIcon(
- List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId() + " has no icon ", s.hasIconFile() || s.hasIconResource());
- }
- return actualShortcuts;
- }
-
public static List<ShortcutInfo> assertAllKeyFieldsOnly(
List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
@@ -444,7 +456,7 @@ public class ShortcutManagerTestUtils {
public static List<ShortcutInfo> assertAllManifest(
List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId(), s.isManifestShortcut());
+ assertTrue("ID " + s.getId(), s.isDeclaredInManifest());
}
return actualShortcuts;
}
@@ -452,7 +464,7 @@ public class ShortcutManagerTestUtils {
public static List<ShortcutInfo> assertAllNotManifest(
List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
- assertFalse("ID " + s.getId(), s.isManifestShortcut());
+ assertFalse("ID " + s.getId(), s.isDeclaredInManifest());
}
return actualShortcuts;
}
@@ -481,14 +493,6 @@ public class ShortcutManagerTestUtils {
return actualShortcuts;
}
- public static List<ShortcutInfo> assertAllStringsResolved(
- List<ShortcutInfo> actualShortcuts) {
- for (ShortcutInfo s : actualShortcuts) {
- assertTrue("ID " + s.getId(), s.hasStringResourcesResolved());
- }
- return actualShortcuts;
- }
-
public static void assertDynamicOnly(ShortcutInfo si) {
assertTrue(si.isDynamic());
assertFalse(si.isPinned());
@@ -496,7 +500,7 @@ public class ShortcutManagerTestUtils {
public static void assertPinnedOnly(ShortcutInfo si) {
assertFalse(si.isDynamic());
- assertFalse(si.isManifestShortcut());
+ assertFalse(si.isDeclaredInManifest());
assertTrue(si.isPinned());
}
@@ -667,8 +671,8 @@ public class ShortcutManagerTestUtils {
}
private ShortcutListAsserter(ShortcutListAsserter original, List<ShortcutInfo> list) {
- mOriginal = original == null ? this : original;
- mList = new ArrayList<>(list);
+ mOriginal = (original == null) ? this : original;
+ mList = (list == null) ? new ArrayList<>(0) : new ArrayList<>(list);
}
public ShortcutListAsserter revertToOriginalList() {
@@ -682,7 +686,7 @@ public class ShortcutManagerTestUtils {
public ShortcutListAsserter selectManifest() {
return new ShortcutListAsserter(this,
- filter(mList, ShortcutInfo::isManifestShortcut));
+ filter(mList, ShortcutInfo::isDeclaredInManifest));
}
public ShortcutListAsserter selectPinned() {
@@ -777,12 +781,12 @@ public class ShortcutManagerTestUtils {
}
public ShortcutListAsserter areAllManifest() {
- forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isManifestShortcut()));
+ forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.isDeclaredInManifest()));
return this;
}
public ShortcutListAsserter areAllNotManifest() {
- forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isManifestShortcut()));
+ forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.isDeclaredInManifest()));
return this;
}
@@ -806,11 +810,29 @@ public class ShortcutManagerTestUtils {
return this;
}
+ public ShortcutListAsserter areAllWithKeyFieldsOnly() {
+ forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.hasKeyFieldsOnly()));
+ return this;
+ }
+
+ public ShortcutListAsserter areAllNotWithKeyFieldsOnly() {
+ forAllShortcuts(s -> assertFalse("id=" + s.getId(), s.hasKeyFieldsOnly()));
+ return this;
+ }
+
+ public ShortcutListAsserter areAllWithActivity(ComponentName activity) {
+ forAllShortcuts(s -> assertTrue("id=" + s.getId(), s.getActivity().equals(activity)));
+ return this;
+ }
+
public ShortcutListAsserter forAllShortcuts(Consumer<ShortcutInfo> sa) {
+ boolean found = false;
for (int i = 0; i < mList.size(); i++) {
final ShortcutInfo si = mList.get(i);
+ found = true;
sa.accept(si);
}
+ assertTrue("No shortcuts found.", found);
return this;
}
@@ -838,4 +860,123 @@ public class ShortcutManagerTestUtils {
return this;
}
}
+
+ public static void assertBundlesEqual(BaseBundle b1, BaseBundle b2) {
+ if (b1 == null && b2 == null) {
+ return; // pass
+ }
+ assertNotNull(b1);
+ assertNotNull(b2);
+
+ // HashSet makes the error message readable.
+ assertEquals(set(b1.keySet()), set(b2.keySet()));
+
+ for (String key : b1.keySet()) {
+ final Object v1 = b1.get(key);
+ final Object v2 = b2.get(key);
+ if (v1 == null) {
+ if (v2 == null) {
+ return;
+ }
+ }
+ if (v1.equals(v2)) {
+ return;
+ }
+
+ assertTrue("Only either value is null: key=" + key
+ + " b1=" + b1 + " b2=" + b2, v1 != null && v2 != null);
+ assertEquals("Class mismatch: key=" + key, v1.getClass(), v2.getClass());
+
+ if (v1 instanceof BaseBundle) {
+ assertBundlesEqual((BaseBundle) v1, (BaseBundle) v2);
+
+ } else if (v1 instanceof boolean[]) {
+ assertTrue(Arrays.equals((boolean[]) v1, (boolean[]) v2));
+
+ } else if (v1 instanceof int[]) {
+ MoreAsserts.assertEquals((int[]) v1, (int[]) v2);
+
+ } else if (v1 instanceof double[]) {
+ MoreAsserts.assertEquals((double[]) v1, (double[]) v2);
+
+ } else if (v1 instanceof String[]) {
+ MoreAsserts.assertEquals((String[]) v1, (String[]) v2);
+
+ } else if (v1 instanceof Double) {
+ if (((Double) v1).isNaN()) {
+ assertTrue(((Double) v2).isNaN());
+ } else {
+ assertEquals(v1, v2);
+ }
+
+ } else {
+ assertEquals(v1, v2);
+ }
+ }
+ }
+
+ public static void waitOnMainThread() throws InterruptedException {
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ new Handler(Looper.getMainLooper()).post(() -> latch.countDown());
+
+ latch.await();
+ }
+
+ public static class LauncherCallbackAsserter {
+ private final LauncherApps.Callback mCallback = mock(LauncherApps.Callback.class);
+
+ private Callback getMockCallback() {
+ return mCallback;
+ }
+
+ public LauncherCallbackAsserter assertNoCallbackCalled() {
+ verify(mCallback, times(0)).onShortcutsChanged(
+ anyString(),
+ any(List.class),
+ any(UserHandle.class));
+ return this;
+ }
+
+ public LauncherCallbackAsserter assertNoCallbackCalledForPackage(
+ String publisherPackageName) {
+ verify(mCallback, times(0)).onShortcutsChanged(
+ eq(publisherPackageName),
+ any(List.class),
+ any(UserHandle.class));
+ return this;
+ }
+
+ public LauncherCallbackAsserter assertNoCallbackCalledForPackageAndUser(
+ String publisherPackageName, UserHandle publisherUserHandle) {
+ verify(mCallback, times(0)).onShortcutsChanged(
+ eq(publisherPackageName),
+ any(List.class),
+ eq(publisherUserHandle));
+ return this;
+ }
+
+ public ShortcutListAsserter assertCallbackCalledForPackageAndUser(
+ String publisherPackageName, UserHandle publisherUserHandle) {
+ final ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class);
+ verify(mCallback, times(1)).onShortcutsChanged(
+ eq(publisherPackageName),
+ shortcuts.capture(),
+ eq(publisherUserHandle));
+ return new ShortcutListAsserter(shortcuts.getValue());
+ }
+ }
+
+ public static LauncherCallbackAsserter assertForLauncherCallback(
+ LauncherApps launcherApps, Runnable body) throws InterruptedException {
+ final LauncherCallbackAsserter asserter = new LauncherCallbackAsserter();
+ launcherApps.registerCallback(asserter.getMockCallback(),
+ new Handler(Looper.getMainLooper()));
+
+ body.run();
+
+ waitOnMainThread();
+
+ return asserter;
+ }
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 5843fbbe7532..1b14d65b823c 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -367,6 +367,22 @@ public abstract class Connection extends Conferenceable {
public static final String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
/**
+ * Boolean connection extra key set on a {@link Connection} in
+ * {@link Connection#STATE_RINGING} state to indicate that answering the call will cause the
+ * current active foreground call to be dropped.
+ */
+ public static final String EXTRA_ANSWERING_DROPS_FG_CALL =
+ "android.telecom.extra.ANSWERING_DROPS_FG_CALL";
+
+ /**
+ * Boolean connection extra key on a {@link Connection} which indicates that adding an
+ * additional call is disallowed when there is a video call in progress.
+ * @hide
+ */
+ public static final String EXTRA_DISABLE_ADD_CALL_DURING_VIDEO_CALL =
+ "android.telecom.extra.DISABLE_ADD_CALL_DURING_VIDEO_CALL";
+
+ /**
* Connection event used to inform Telecom that it should play the on hold tone. This is used
* to play a tone when the peer puts the current call on hold. Sent to Telecom via
* {@link #sendConnectionEvent(String)}.
@@ -578,6 +594,8 @@ public abstract class Connection extends Conferenceable {
public void onExtrasChanged(Connection c, Bundle extras) {}
public void onExtrasRemoved(Connection c, List<String> keys) {}
public void onConnectionEvent(Connection c, String event, Bundle extras) {}
+ /** @hide */
+ public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {}
}
/**
@@ -2347,6 +2365,19 @@ public abstract class Connection extends Conferenceable {
}
/**
+ * Notifies listeners when a change has occurred to the Connection which impacts its ability to
+ * be a part of a conference call.
+ * @param isConferenceSupported {@code true} if the connection supports being part of a
+ * conference call, {@code false} otherwise.
+ * @hide
+ */
+ protected void notifyConferenceSupportedChanged(boolean isConferenceSupported) {
+ for (Listener l : mListeners) {
+ l.onConferenceSupportedChanged(this, isConferenceSupported);
+ }
+ }
+
+ /**
* Sends an event associated with this {@code Connection}, with associated event extras.
*
* Events are exposed to {@link InCallService} implementations via the
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 44d89c14486b..a5e50aa1ee5d 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -777,6 +777,53 @@ public class CarrierConfigManager {
/** @hide */
public static final int CDMA_ROAMING_MODE_ANY = 2;
+ /**
+ * The families of Radio Access Technologies that will get clustered and ratcheted,
+ * ie, we will report transitions up within the family, but not down until we change
+ * cells. This prevents flapping between base technologies and higher techs that are
+ * granted on demand within the cell.
+ * @hide
+ */
+ public static final String KEY_RATCHET_RAT_FAMILIES =
+ "ratchet_rat_families";
+
+ /**
+ * Flag indicating whether some telephony logic will treat a call which was formerly a video
+ * call as if it is still a video call. When {@code true}:
+ * <p>
+ * Logic which will automatically drop a video call which takes place over WIFI when a
+ * voice call is answered (see {@link #KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL}.
+ * <p>
+ * Logic which determines whether the user can use TTY calling.
+ */
+ public static final String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL =
+ "treat_downgraded_video_calls_as_video_calls_bool";
+
+ /**
+ * When {@code true}, if the user is in an ongoing video call over WIFI and answers an incoming
+ * audio call, the video call will be disconnected before the audio call is answered. This is
+ * in contrast to the usual expected behavior where a foreground video call would be put into
+ * the background and held when an incoming audio call is answered.
+ */
+ public static final String KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL =
+ "drop_video_call_when_answering_audio_call_bool";
+
+ /**
+ * Flag indicating whether the carrier supports merging wifi calls when VoWIFI is disabled.
+ * This can happen in the case of a carrier which allows offloading video calls to WIFI
+ * separately of whether voice over wifi is enabled. In such a scenario when two video calls
+ * are downgraded to voice, they remain over wifi. However, if VoWIFI is disabled, these calls
+ * cannot be merged.
+ */
+ public static final String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL =
+ "allow_merge_wifi_calls_when_vowifi_off_bool";
+
+ /**
+ * When true, indicates that adding a call is disabled when there is an ongoing video call.
+ */
+ public static final String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL =
+ "allow_add_call_during_video_call";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -922,6 +969,16 @@ public class CarrierConfigManager {
sDefaults.putStringArray(KEY_SIGNAL_DCFAILURE_RECEIVER_STRING_ARRAY, null);
sDefaults.putStringArray(KEY_SIGNAL_PCO_RECEIVER_STRING_ARRAY, null);
sDefaults.putString(KEY_CARRIER_SETUP_APP_STRING, "");
+
+ // Rat families: {GPRS, EDGE}, {EVDO, EVDO_A, EVDO_B}, {UMTS, HSPA, HSDPA, HSUPA, HSPAP},
+ // {LTE, LTE_CA}
+ // Order is important - lowest precidence first
+ sDefaults.putStringArray(KEY_RATCHET_RAT_FAMILIES,
+ new String[]{"1,2","7,8,12","3,11,9,10,15","14,19"});
+ sDefaults.putBoolean(KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL, false);
+ sDefaults.putBoolean(KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL, false);
+ sDefaults.putBoolean(KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL, true);
+ sDefaults.putBoolean(KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL, true);
}
/**
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index 2bfaf1bfd86d..b530a6405a62 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -47,6 +47,7 @@ public class RadioAccessFamily implements Parcelable {
public static final int RAF_HSPAP = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP);
public static final int RAF_GSM = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GSM);
public static final int RAF_TD_SCDMA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA);
+ public static final int RAF_LTE_CA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA);
// Grouping of RAFs
private static final int GSM = RAF_GSM | RAF_GPRS | RAF_EDGE;
@@ -54,6 +55,7 @@ public class RadioAccessFamily implements Parcelable {
private static final int CDMA = RAF_IS95A | RAF_IS95B | RAF_1xRTT;
private static final int EVDO = RAF_EVDO_0 | RAF_EVDO_A | RAF_EVDO_B | RAF_EHRPD;
private static final int WCDMA = HS | RAF_UMTS;
+ private static final int LTE = RAF_LTE | RAF_LTE_CA;
/* Phone ID of phone */
private int mPhoneId;
@@ -162,19 +164,19 @@ public class RadioAccessFamily implements Parcelable {
raf = CDMA | EVDO;
break;
case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO:
- raf = RAF_LTE | CDMA | EVDO;
+ raf = LTE | CDMA | EVDO;
break;
case RILConstants.NETWORK_MODE_LTE_GSM_WCDMA:
- raf = RAF_LTE | GSM | WCDMA;
+ raf = LTE | GSM | WCDMA;
break;
case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA:
- raf = RAF_LTE | CDMA | EVDO | GSM | WCDMA;
+ raf = LTE | CDMA | EVDO | GSM | WCDMA;
break;
case RILConstants.NETWORK_MODE_LTE_ONLY:
- raf = RAF_LTE;
+ raf = LTE;
break;
case RILConstants.NETWORK_MODE_LTE_WCDMA:
- raf = RAF_LTE | WCDMA;
+ raf = LTE | WCDMA;
break;
case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
raf = CDMA;
@@ -192,28 +194,28 @@ public class RadioAccessFamily implements Parcelable {
raf = RAF_TD_SCDMA | WCDMA;
break;
case RILConstants.NETWORK_MODE_LTE_TDSCDMA:
- raf = RAF_LTE | RAF_TD_SCDMA;
+ raf = LTE | RAF_TD_SCDMA;
break;
case RILConstants.NETWORK_MODE_TDSCDMA_GSM:
raf = RAF_TD_SCDMA | GSM;
break;
case RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM:
- raf = RAF_LTE | RAF_TD_SCDMA | GSM;
+ raf = LTE | RAF_TD_SCDMA | GSM;
break;
case RILConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
raf = RAF_TD_SCDMA | GSM | WCDMA;
break;
case RILConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA:
- raf = RAF_LTE | RAF_TD_SCDMA | WCDMA;
+ raf = LTE | RAF_TD_SCDMA | WCDMA;
break;
case RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA:
- raf = RAF_LTE | RAF_TD_SCDMA | GSM | WCDMA;
+ raf = LTE | RAF_TD_SCDMA | GSM | WCDMA;
break;
case RILConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
raf = RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
break;
case RILConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA:
- raf = RAF_LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
+ raf = LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA;
break;
default:
raf = RAF_UNKNOWN;
@@ -232,6 +234,7 @@ public class RadioAccessFamily implements Parcelable {
raf = ((WCDMA & raf) > 0) ? (WCDMA | raf) : raf;
raf = ((CDMA & raf) > 0) ? (CDMA | raf) : raf;
raf = ((EVDO & raf) > 0) ? (EVDO | raf) : raf;
+ raf = ((LTE & raf) > 0) ? (LTE | raf) : raf;
return raf;
}
@@ -254,19 +257,19 @@ public class RadioAccessFamily implements Parcelable {
case (CDMA | EVDO):
type = RILConstants.NETWORK_MODE_CDMA;
break;
- case (RAF_LTE | CDMA | EVDO):
+ case (LTE | CDMA | EVDO):
type = RILConstants.NETWORK_MODE_LTE_CDMA_EVDO;
break;
- case (RAF_LTE | GSM | WCDMA):
+ case (LTE | GSM | WCDMA):
type = RILConstants.NETWORK_MODE_LTE_GSM_WCDMA;
break;
- case (RAF_LTE | CDMA | EVDO | GSM | WCDMA):
+ case (LTE | CDMA | EVDO | GSM | WCDMA):
type = RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA;
break;
- case RAF_LTE:
+ case LTE:
type = RILConstants.NETWORK_MODE_LTE_ONLY;
break;
- case (RAF_LTE | WCDMA):
+ case (LTE | WCDMA):
type = RILConstants.NETWORK_MODE_LTE_WCDMA;
break;
case CDMA:
@@ -284,28 +287,28 @@ public class RadioAccessFamily implements Parcelable {
case (RAF_TD_SCDMA | WCDMA):
type = RILConstants.NETWORK_MODE_TDSCDMA_WCDMA;
break;
- case (RAF_LTE | RAF_TD_SCDMA):
+ case (LTE | RAF_TD_SCDMA):
type = RILConstants.NETWORK_MODE_LTE_TDSCDMA;
break;
case (RAF_TD_SCDMA | GSM):
type = RILConstants.NETWORK_MODE_TDSCDMA_GSM;
break;
- case (RAF_LTE | RAF_TD_SCDMA | GSM):
+ case (LTE | RAF_TD_SCDMA | GSM):
type = RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM;
break;
case (RAF_TD_SCDMA | GSM | WCDMA):
type = RILConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA;
break;
- case (RAF_LTE | RAF_TD_SCDMA | WCDMA):
+ case (LTE | RAF_TD_SCDMA | WCDMA):
type = RILConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA;
break;
- case (RAF_LTE | RAF_TD_SCDMA | GSM | WCDMA):
+ case (LTE | RAF_TD_SCDMA | GSM | WCDMA):
type = RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA;
break;
case (RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
type = RILConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
break;
- case (RAF_LTE | RAF_TD_SCDMA | RAF_LTE | CDMA | EVDO | GSM | WCDMA):
+ case (LTE | RAF_TD_SCDMA | CDMA | EVDO | GSM | WCDMA):
type = RILConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
break;
default:
@@ -339,6 +342,7 @@ public class RadioAccessFamily implements Parcelable {
case "CDMA": return CDMA;
case "EVDO": return EVDO;
case "WCDMA": return WCDMA;
+ case "LTE_CA": return RAF_LTE_CA;
default: return RAF_UNKNOWN;
}
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 39a9295ed8b6..8446dd04326c 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -155,6 +155,12 @@ public class ServiceState implements Parcelable {
*/
public static final int RIL_RADIO_TECHNOLOGY_IWLAN = 18;
+ /**
+ * LTE_CA
+ * @hide
+ */
+ public static final int RIL_RADIO_TECHNOLOGY_LTE_CA = 19;
+
/** @hide */
public static final int RIL_RADIO_CDMA_TECHNOLOGY_BITMASK =
(1 << (RIL_RADIO_TECHNOLOGY_IS95A - 1))
@@ -746,6 +752,9 @@ public class ServiceState implements Parcelable {
case RIL_RADIO_TECHNOLOGY_TD_SCDMA:
rtString = "TD-SCDMA";
break;
+ case RIL_RADIO_TECHNOLOGY_LTE_CA:
+ rtString = "LTE_CA";
+ break;
default:
rtString = "Unexpected";
Rlog.w(LOG_TAG, "Unexpected radioTechnology=" + rt);
@@ -1088,6 +1097,8 @@ public class ServiceState implements Parcelable {
return TelephonyManager.NETWORK_TYPE_TD_SCDMA;
case ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN:
return TelephonyManager.NETWORK_TYPE_IWLAN;
+ case ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA:
+ return TelephonyManager.NETWORK_TYPE_LTE_CA;
default:
return TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
@@ -1139,7 +1150,9 @@ public class ServiceState implements Parcelable {
|| radioTechnology == RIL_RADIO_TECHNOLOGY_HSPAP
|| radioTechnology == RIL_RADIO_TECHNOLOGY_GSM
|| radioTechnology == RIL_RADIO_TECHNOLOGY_TD_SCDMA
- || radioTechnology == RIL_RADIO_TECHNOLOGY_IWLAN;
+ || radioTechnology == RIL_RADIO_TECHNOLOGY_IWLAN
+ || radioTechnology == RIL_RADIO_TECHNOLOGY_LTE_CA;
+
}
/** @hide */
@@ -1154,6 +1167,12 @@ public class ServiceState implements Parcelable {
}
/** @hide */
+ public static boolean isLte(int radioTechnology) {
+ return radioTechnology == RIL_RADIO_TECHNOLOGY_LTE ||
+ radioTechnology == RIL_RADIO_TECHNOLOGY_LTE_CA;
+ }
+
+ /** @hide */
public static boolean bearerBitmapHasCdma(int radioTechnologyBitmap) {
return (RIL_RADIO_CDMA_TECHNOLOGY_BITMASK & radioTechnologyBitmap) != 0;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index e72fe49e1cfa..2fb9409ed6a4 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1445,13 +1445,14 @@ public class TelephonyManager {
public static final int NETWORK_TYPE_EHRPD = 14;
/** Current network is HSPA+ */
public static final int NETWORK_TYPE_HSPAP = 15;
- /** Current network is GSM {@hide} */
+ /** Current network is GSM */
public static final int NETWORK_TYPE_GSM = 16;
- /** Current network is TD_SCDMA {@hide} */
+ /** Current network is TD_SCDMA */
public static final int NETWORK_TYPE_TD_SCDMA = 17;
- /** Current network is IWLAN {@hide} */
+ /** Current network is IWLAN */
public static final int NETWORK_TYPE_IWLAN = 18;
-
+ /** Current network is LTE_CA {@hide} */
+ public static final int NETWORK_TYPE_LTE_CA = 19;
/**
* @return the NETWORK_TYPE_xxxx for current data connection.
*/
@@ -1654,6 +1655,7 @@ public class TelephonyManager {
return NETWORK_CLASS_3_G;
case NETWORK_TYPE_LTE:
case NETWORK_TYPE_IWLAN:
+ case NETWORK_TYPE_LTE_CA:
return NETWORK_CLASS_4_G;
default:
return NETWORK_CLASS_UNKNOWN;
@@ -1717,6 +1719,8 @@ public class TelephonyManager {
return "TD_SCDMA";
case NETWORK_TYPE_IWLAN:
return "IWLAN";
+ case NETWORK_TYPE_LTE_CA:
+ return "LTE_CA";
default:
return "UNKNOWN";
}
@@ -5419,7 +5423,7 @@ public class TelephonyManager {
return null;
}
- /*
+ /**
* Get snapshot of Telephony histograms
* @return List of Telephony histograms
* Requires Permission:
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index 92b70e86cb06..65254d8abc88 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -448,6 +448,15 @@ public class ImsCallProfile implements Parcelable {
}
/**
+ * Determines if the {@link ImsCallProfile} represents a video call.
+ *
+ * @return {@code true} if the profile is for a video call, {@code false} otherwise.
+ */
+ public boolean isVideoCall() {
+ return VideoProfile.isVideo(getVideoStateFromCallType(mCallType));
+ }
+
+ /**
* Determines if a video state is set in a video state bit-mask.
*
* @param videoState The video state bit mask.
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 1680fe33ead7..b417a1c9e206 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -208,4 +208,14 @@ public class PhoneConstants {
public static final int AUTH_CONTEXT_EAP_SIM = 128;
public static final int AUTH_CONTEXT_EAP_AKA = 129;
public static final int AUTH_CONTEXT_UNDEFINED = -1;
+
+ /**
+ * Value for the global property CELL_ON
+ * 0: Cell radio is off
+ * 1: Cell radio is on
+ * 2: Cell radio is off because airplane mode is enabled
+ */
+ public static final int CELL_OFF_FLAG = 0;
+ public static final int CELL_ON_FLAG = 1;
+ public static final int CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG = 2;
}
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index b14fc41632b3..9471326627a5 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -702,6 +702,12 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public Display getDisplay() {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public File[] getExternalFilesDirs(String type) {
throw new UnsupportedOperationException();
diff --git a/tools/aapt/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp
index 8693999c7cc4..ed06f605eaeb 100644
--- a/tools/aapt/ResourceFilter.cpp
+++ b/tools/aapt/ResourceFilter.cpp
@@ -54,6 +54,46 @@ WeakResourceFilter::parse(const String8& str)
return NO_ERROR;
}
+// Returns true if the locale script of the config should be considered matching
+// the locale script of entry.
+//
+// If both the scripts are empty, the scripts are considered matching for
+// backward compatibility reasons.
+//
+// If only one script is empty, we try to compute it based on the provided
+// language and country. If we could not compute it, we assume it's either a
+// new language we don't know about, or a private use language. We return true
+// since we don't know any better and they might as well be a match.
+//
+// Finally, when we have two scripts (one of which could be computed), we return
+// true if and only if they are an exact match.
+inline bool
+scriptsMatch(const ResTable_config& config, const ResTable_config& entry) {
+ const char* configScript = config.localeScript;
+ const char* entryScript = entry.localeScript;
+ if (configScript[0] == '\0' && entryScript[0] == '\0') {
+ return true; // both scripts are empty. We match for backward compatibility reasons.
+ }
+
+ char scriptBuffer[sizeof(config.localeScript)];
+ if (configScript[0] == '\0') {
+ localeDataComputeScript(scriptBuffer, config.language, config.country);
+ if (scriptBuffer[0] == '\0') { // We can't compute the script, so we match.
+ return true;
+ }
+ configScript = scriptBuffer;
+ } else if (entryScript[0] == '\0') {
+ localeDataComputeScript(
+ scriptBuffer, entry.language, entry.country);
+ if (scriptBuffer[0] == '\0') { // We can't compute the script, so we match.
+ return true;
+ }
+ entryScript = scriptBuffer;
+ }
+ return (memcmp(configScript, entryScript, sizeof(config.localeScript)) == 0);
+}
+
+
bool
WeakResourceFilter::match(const ResTable_config& config) const
{
@@ -75,11 +115,19 @@ WeakResourceFilter::match(const ResTable_config& config) const
// If the locales differ, but the languages are the same and
// the locale we are matching only has a language specified,
// we match.
- if (config.language[0] &&
- memcmp(config.language, entry.first.language, sizeof(config.language)) == 0) {
- if (config.country[0] == 0) {
- matchedAxis |= ResTable_config::CONFIG_LOCALE;
- }
+ //
+ // Exception: we won't match if a script is specified for at least
+ // one of the locales and it's different from the other locale's
+ // script. (We will compute the other script if at least one of the
+ // scripts were explicitly set. In cases we can't compute an script,
+ // we match.)
+ if (config.language[0] != '\0' &&
+ config.country[0] == '\0' &&
+ config.localeVariant[0] == '\0' &&
+ config.language[0] == entry.first.language[0] &&
+ config.language[1] == entry.first.language[1] &&
+ scriptsMatch(config, entry.first)) {
+ matchedAxis |= ResTable_config::CONFIG_LOCALE;
}
} else if ((diff & entry.second) == ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE) {
// Special case if the smallest screen width doesn't match. We check that the
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 f87269b7c9f7..616cb5761402 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
@@ -1799,6 +1799,12 @@ public final class BridgeContext extends Context {
}
@Override
+ public Display getDisplay() {
+ // pass
+ return null;
+ }
+
+ @Override
public int getUserId() {
return 0; // not used
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index 3f276c9375ba..ab73a8b820cd 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -16,11 +16,13 @@
package com.android.layoutlib.bridge.android;
+import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.InputBindResult;
+import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -239,4 +241,11 @@ public class BridgeIInputMethodManager implements IInputMethodManager {
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ public IInputContentUriToken createInputContentUriToken(IBinder token, Uri contentUri,
+ String packageName) {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index b614a8660509..08ad35ed2808 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -375,7 +375,15 @@ public class WifiEnterpriseConfig implements Parcelable {
return false;
}
+ // wpa_supplicant can update the anonymous identity for these kinds of networks after
+ // framework reads them, so make sure the framework doesn't try to overwrite them.
+ boolean shouldNotWriteAnonIdentity = mEapMethod == WifiEnterpriseConfig.Eap.SIM
+ || mEapMethod == WifiEnterpriseConfig.Eap.AKA
+ || mEapMethod == WifiEnterpriseConfig.Eap.AKA_PRIME;
for (String key : mFields.keySet()) {
+ if (shouldNotWriteAnonIdentity && ANON_IDENTITY_KEY.equals(key)) {
+ continue;
+ }
if (!saver.saveValue(key, mFields.get(key))) {
return false;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 1cd32b6bff0f..bbc3d2fd5927 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -561,6 +561,12 @@ public class WifiManager {
public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
/**
+ * Internally used Wi-Fi lock mode representing the case were no locks are held.
+ * @hide
+ */
+ public static final int WIFI_MODE_NO_LOCKS_HELD = 0;
+
+ /**
* In this Wi-Fi lock mode, Wi-Fi will be kept active,
* and will behave normally, i.e., it will attempt to automatically
* establish a connection to a remembered access point that is
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 2636c3f3e079..716f1d32ec84 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -656,6 +656,40 @@ public class WifiScanner {
void onPnoNetworkFound(ScanResult[] results);
}
+ /**
+ * Register a listener that will receive results from all single scans
+ * Either the onSuccess/onFailure will be called once when the listener is registered. After
+ * (assuming onSuccess was called) all subsequent single scan results will be delivered to the
+ * listener. It is possible that onFullResult will not be called for all results of the first
+ * scan if the listener was registered during the scan.
+ *
+ * @param listener specifies the object to report events to. This object is also treated as a
+ * key for this request, and must also be specified to cancel the request.
+ * Multiple requests should also not share this object.
+ * {@hide}
+ */
+ public void registerScanListener(ScanListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ int key = addListener(listener);
+ if (key == INVALID_KEY) return;
+ validateChannel();
+ mAsyncChannel.sendMessage(CMD_REGISTER_SCAN_LISTENER, 0, key);
+ }
+
+ /**
+ * Deregister a listener for ongoing single scans
+ * @param listener specifies which scan to cancel; must be same object as passed in {@link
+ * #registerScanListener}
+ * {@hide}
+ */
+ public void deregisterScanListener(ScanListener listener) {
+ Preconditions.checkNotNull(listener, "listener cannot be null");
+ int key = removeListener(listener);
+ if (key == INVALID_KEY) return;
+ validateChannel();
+ mAsyncChannel.sendMessage(CMD_DEREGISTER_SCAN_LISTENER, 0, key);
+ }
+
/** start wifi scan in background
* @param settings specifies various parameters for the scan; for more information look at
* {@link ScanSettings}
@@ -1129,6 +1163,10 @@ public class WifiScanner {
public static final int CMD_STOP_PNO_SCAN = BASE + 25;
/** @hide */
public static final int CMD_PNO_NETWORK_FOUND = BASE + 26;
+ /** @hide */
+ public static final int CMD_REGISTER_SCAN_LISTENER = BASE + 27;
+ /** @hide */
+ public static final int CMD_DEREGISTER_SCAN_LISTENER = BASE + 28;
private Context mContext;
private IWifiScanner mService;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
index ca737f9e64d9..32673c771baa 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -146,7 +146,6 @@ public class WifiP2pGroup implements Parcelable {
}
if (nameValue[0].equals("persistent")) {
- mOwner = new WifiP2pDevice(sa);
mNetId = Integer.parseInt(nameValue[1]);
continue;
}