summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt31
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java332
-rw-r--r--core/java/android/app/ActivityTransitionCoordinator.java3
-rw-r--r--core/java/android/app/ApplicationPackageManager.java12
-rw-r--r--core/java/android/app/EnterTransitionCoordinator.java9
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java5
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java2
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl1
-rw-r--r--core/java/android/content/pm/LauncherApps.java16
-rw-r--r--core/java/android/content/pm/PackageManager.java7
-rw-r--r--core/java/android/content/res/Configuration.java2
-rw-r--r--core/java/android/content/res/Resources.java14
-rw-r--r--core/java/android/content/res/TypedArray.java24
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java8
-rw-r--r--core/java/android/net/PskKeyManager.java7
-rw-r--r--core/java/android/os/INetworkManagementService.aidl5
-rw-r--r--core/java/android/os/IPowerManager.aidl1
-rw-r--r--core/java/android/os/PowerManager.java22
-rw-r--r--core/java/android/print/IPrintDocumentAdapter.aidl1
-rw-r--r--core/java/android/print/PrintManager.java21
-rw-r--r--core/java/android/provider/Settings.java15
-rw-r--r--core/java/android/util/TypedValue.java23
-rw-r--r--core/java/android/view/IWindow.aidl5
-rw-r--r--core/java/android/view/ThreadedRenderer.java3
-rw-r--r--core/java/android/view/View.java227
-rw-r--r--core/java/android/view/ViewGroup.java12
-rw-r--r--core/java/android/view/ViewRootImpl.java107
-rw-r--r--core/java/android/view/ViewTreeObserver.java86
-rw-r--r--core/java/android/view/Window.java29
-rw-r--r--core/java/android/view/WindowManager.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java168
-rw-r--r--core/java/android/widget/AbsListView.java14
-rw-r--r--core/java/android/widget/AbsSeekBar.java6
-rw-r--r--core/java/android/widget/ActionMenuView.java2
-rw-r--r--core/java/android/widget/CheckedTextView.java6
-rw-r--r--core/java/android/widget/CompoundButton.java6
-rw-r--r--core/java/android/widget/FrameLayout.java6
-rw-r--r--core/java/android/widget/ImageView.java29
-rw-r--r--core/java/android/widget/OverScroller.java4
-rw-r--r--core/java/android/widget/ProgressBar.java24
-rw-r--r--core/java/android/widget/RemoteViews.java20
-rw-r--r--core/java/android/widget/Toolbar.java3
-rw-r--r--core/java/com/android/internal/app/AlertController.java87
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java4
-rw-r--r--core/java/com/android/internal/app/ToolbarActionBar.java48
-rw-r--r--core/java/com/android/internal/app/WindowDecorActionBar.java17
-rw-r--r--core/java/com/android/internal/util/MemInfoReader.java4
-rw-r--r--core/java/com/android/internal/view/BaseIWindow.java4
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java16
-rw-r--r--core/java/com/android/internal/widget/DecorToolbar.java9
-rw-r--r--core/java/com/android/internal/widget/ResolverDrawerLayout.java80
-rw-r--r--core/java/com/android/internal/widget/ToolbarWidgetWrapper.java32
-rw-r--r--core/jni/AndroidRuntime.cpp4
-rw-r--r--core/jni/android/graphics/pdf/PdfEditor.cpp217
-rw-r--r--core/jni/android/graphics/pdf/PdfRenderer.cpp13
-rw-r--r--core/jni/android_hardware_SoundTrigger.cpp9
-rw-r--r--core/jni/android_media_AudioSystem.cpp2
-rw-r--r--core/jni/android_util_AssetManager.cpp10
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp3
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp32
-rw-r--r--core/res/AndroidManifest.xml21
-rw-r--r--core/res/res/drawable/view_accessibility_focused.xml4
-rw-r--r--core/res/res/layout/alert_dialog_material.xml20
-rw-r--r--core/res/res/layout/select_dialog_item_material.xml4
-rw-r--r--core/res/res/values-af/strings.xml10
-rw-r--r--core/res/res/values-am/strings.xml10
-rw-r--r--core/res/res/values-ar/strings.xml10
-rw-r--r--core/res/res/values-bg/strings.xml10
-rw-r--r--core/res/res/values-bn-rBD/strings.xml10
-rw-r--r--core/res/res/values-ca/strings.xml10
-rw-r--r--core/res/res/values-cs/strings.xml10
-rw-r--r--core/res/res/values-da/strings.xml10
-rw-r--r--core/res/res/values-de/strings.xml10
-rw-r--r--core/res/res/values-el/strings.xml10
-rw-r--r--core/res/res/values-en-rGB/strings.xml10
-rw-r--r--core/res/res/values-en-rIN/strings.xml10
-rw-r--r--core/res/res/values-es-rUS/strings.xml10
-rw-r--r--core/res/res/values-es/strings.xml10
-rw-r--r--core/res/res/values-et-rEE/strings.xml10
-rw-r--r--core/res/res/values-eu-rES/strings.xml12
-rw-r--r--core/res/res/values-fa/strings.xml10
-rw-r--r--core/res/res/values-fi/strings.xml14
-rw-r--r--core/res/res/values-fr-rCA/strings.xml10
-rw-r--r--core/res/res/values-fr/strings.xml10
-rw-r--r--core/res/res/values-gl-rES/strings.xml10
-rw-r--r--core/res/res/values-hi/strings.xml14
-rw-r--r--core/res/res/values-hr/strings.xml10
-rw-r--r--core/res/res/values-hu/strings.xml10
-rw-r--r--core/res/res/values-hy-rAM/strings.xml14
-rw-r--r--core/res/res/values-in/strings.xml10
-rw-r--r--core/res/res/values-is-rIS/strings.xml10
-rw-r--r--core/res/res/values-it/strings.xml10
-rw-r--r--core/res/res/values-iw/strings.xml10
-rw-r--r--core/res/res/values-ja/strings.xml12
-rw-r--r--core/res/res/values-ka-rGE/strings.xml16
-rw-r--r--core/res/res/values-kk-rKZ/strings.xml14
-rw-r--r--core/res/res/values-km-rKH/strings.xml10
-rw-r--r--core/res/res/values-kn-rIN/strings.xml12
-rw-r--r--core/res/res/values-ko/strings.xml14
-rw-r--r--core/res/res/values-ky-rKG/strings.xml14
-rw-r--r--core/res/res/values-lo-rLA/strings.xml14
-rw-r--r--core/res/res/values-lt/strings.xml10
-rw-r--r--core/res/res/values-lv/strings.xml10
-rw-r--r--core/res/res/values-mcc204-mnc04/config.xml7
-rw-r--r--core/res/res/values-mcc311-mnc480/config.xml7
-rw-r--r--core/res/res/values-mk-rMK/strings.xml10
-rw-r--r--core/res/res/values-ml-rIN/strings.xml10
-rw-r--r--core/res/res/values-mn-rMN/strings.xml10
-rw-r--r--core/res/res/values-mr-rIN/strings.xml10
-rw-r--r--core/res/res/values-ms-rMY/strings.xml14
-rw-r--r--core/res/res/values-my-rMM/strings.xml10
-rw-r--r--core/res/res/values-nb/strings.xml10
-rw-r--r--core/res/res/values-ne-rNP/strings.xml10
-rw-r--r--core/res/res/values-nl/strings.xml10
-rw-r--r--core/res/res/values-pl/strings.xml10
-rw-r--r--core/res/res/values-pt-rPT/strings.xml10
-rw-r--r--core/res/res/values-pt/strings.xml10
-rw-r--r--core/res/res/values-ro/strings.xml14
-rw-r--r--core/res/res/values-ru/strings.xml10
-rw-r--r--core/res/res/values-si-rLK/strings.xml14
-rw-r--r--core/res/res/values-sk/strings.xml10
-rw-r--r--core/res/res/values-sl/strings.xml10
-rw-r--r--core/res/res/values-sr/strings.xml10
-rw-r--r--core/res/res/values-sv/strings.xml10
-rw-r--r--core/res/res/values-sw/strings.xml10
-rw-r--r--core/res/res/values-ta-rIN/strings.xml10
-rw-r--r--core/res/res/values-te-rIN/strings.xml10
-rw-r--r--core/res/res/values-th/strings.xml10
-rw-r--r--core/res/res/values-tl/strings.xml10
-rw-r--r--core/res/res/values-tr/strings.xml14
-rw-r--r--core/res/res/values-uk/strings.xml10
-rw-r--r--core/res/res/values-ur-rPK/strings.xml14
-rw-r--r--core/res/res/values-uz-rUZ/strings.xml14
-rw-r--r--core/res/res/values-vi/strings.xml16
-rw-r--r--core/res/res/values-zh-rCN/strings.xml14
-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.xml10
-rw-r--r--core/res/res/values/attrs.xml15
-rw-r--r--core/res/res/values/config.xml22
-rw-r--r--core/res/res/values/public.xml9
-rw-r--r--core/res/res/values/strings.xml15
-rw-r--r--core/res/res/values/styles.xml1
-rw-r--r--core/res/res/values/styles_material.xml20
-rw-r--r--core/res/res/values/symbols.xml10
-rw-r--r--core/res/res/values/themes_material.xml16
-rw-r--r--docs/html/design/wear/patterns.jd28
-rw-r--r--docs/html/design/wear/structure.jd10
-rw-r--r--docs/html/distribute/tools/promote/badges.jd12
-rw-r--r--docs/html/google/gcm/adv.jd3
-rw-r--r--docs/html/google/gcm/ccs.jd58
-rw-r--r--docs/html/google/gcm/client.jd22
-rw-r--r--docs/html/google/gcm/gcm.jd2
-rw-r--r--docs/html/google/gcm/gs.jd8
-rw-r--r--docs/html/google/gcm/http.jd17
-rw-r--r--docs/html/google/gcm/index.jd6
-rw-r--r--docs/html/google/gcm/notifications.jd4
-rw-r--r--docs/html/google/gcm/server.jd132
-rw-r--r--docs/html/guide/topics/text/creating-input-method.jd345
-rw-r--r--docs/html/images/tools/studio-build-variant.pngbin0 -> 20405 bytes
-rw-r--r--docs/html/images/ui/notifications/heads-up.pngbin84810 -> 84832 bytes
-rw-r--r--docs/html/sdk/installing/adding-packages.jd2
-rw-r--r--docs/html/sdk/installing/index.jd53
-rw-r--r--docs/html/sdk/installing/studio.jd95
-rw-r--r--docs/html/tools/building/multidex.jd458
-rw-r--r--docs/html/tools/revisions/build-tools.jd12
-rw-r--r--docs/html/tools/revisions/platforms.jd2
-rw-r--r--docs/html/tools/support-library/features.jd29
-rw-r--r--docs/html/tools/testing/activity_testing.jd2
-rw-r--r--docs/html/tools/tools_toc.cs13
-rw-r--r--docs/html/training/basics/firstapp/building-ui.jd2
-rw-r--r--docs/html/training/basics/firstapp/creating-project.jd2
-rw-r--r--docs/html/training/basics/firstapp/starting-activity.jd2
-rw-r--r--docs/html/training/wearables/apps/layouts.jd12
-rw-r--r--docs/html/training/wearables/data-layer/index.jd2
-rw-r--r--docs/html/training/wearables/notifications/pages.jd13
-rw-r--r--docs/html/training/wearables/notifications/voice-input.jd7
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java160
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java72
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java11
-rw-r--r--graphics/java/android/graphics/drawable/AnimationDrawable.java58
-rw-r--r--graphics/java/android/graphics/drawable/ClipDrawable.java163
-rw-r--r--graphics/java/android/graphics/drawable/DrawableContainer.java8
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/InsetDrawable.java159
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/RotateDrawable.java188
-rw-r--r--graphics/java/android/graphics/drawable/ScaleDrawable.java204
-rw-r--r--graphics/java/android/graphics/drawable/StateListDrawable.java66
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java6
-rw-r--r--graphics/java/android/graphics/pdf/PdfEditor.java159
-rw-r--r--graphics/java/android/graphics/pdf/PdfRenderer.java4
-rw-r--r--include/androidfw/ResourceTypes.h11
-rw-r--r--libs/androidfw/ResourceTypes.cpp16
-rw-r--r--libs/hwui/Caches.cpp42
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp21
-rw-r--r--libs/hwui/DisplayList.cpp5
-rw-r--r--libs/hwui/DisplayList.h7
-rw-r--r--libs/hwui/DisplayListRenderer.cpp24
-rw-r--r--libs/hwui/DisplayListRenderer.h6
-rw-r--r--libs/hwui/Layer.cpp19
-rw-r--r--libs/hwui/Layer.h8
-rw-r--r--libs/hwui/LayerCache.cpp2
-rw-r--r--libs/hwui/LayerRenderer.cpp14
-rw-r--r--libs/hwui/LayerRenderer.h1
-rwxr-xr-xlibs/hwui/OpenGLRenderer.cpp25
-rwxr-xr-xlibs/hwui/OpenGLRenderer.h3
-rw-r--r--libs/hwui/RenderNode.cpp7
-rw-r--r--libs/hwui/RenderNode.h2
-rw-r--r--libs/hwui/RenderState.cpp37
-rw-r--r--libs/hwui/RenderState.h19
-rw-r--r--libs/hwui/ResourceCache.cpp23
-rw-r--r--libs/hwui/ResourceCache.h7
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp2
-rw-r--r--libs/hwui/renderthread/EglManager.cpp16
-rw-r--r--libs/hwui/renderthread/EglManager.h7
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp42
-rw-r--r--libs/hwui/renderthread/RenderProxy.h4
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp2
-rw-r--r--media/java/android/media/AudioAttributes.java7
-rw-r--r--media/java/android/media/AudioManager.java6
-rw-r--r--media/java/android/media/AudioService.java77
-rw-r--r--media/java/android/media/IAudioService.aidl2
-rw-r--r--media/java/android/media/audiopolicy/AudioMix.java13
-rw-r--r--media/java/android/media/audiopolicy/AudioMixingRule.java2
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicy.java134
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicyConfig.java22
-rw-r--r--media/java/android/media/tv/ITvInputSessionWrapper.java1
-rw-r--r--media/java/android/media/tv/TvContract.java6
-rw-r--r--media/java/android/media/tv/TvInputService.java178
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/model/OpenDocumentCallback.java37
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java50
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java12
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl2
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java119
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java29
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java51
-rw-r--r--packages/SystemUI/res/drawable/ic_dismiss_all.xml1
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_1.xml12
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml4
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_signal_1.xml12
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml4
-rw-r--r--packages/SystemUI/res/layout/navigation_bar.xml50
-rw-r--r--packages/SystemUI/res/values-am/strings.xml3
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml3
-rw-r--r--packages/SystemUI/res/values-bn-rBD/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml3
-rw-r--r--packages/SystemUI/res/values-da/strings.xml3
-rw-r--r--packages/SystemUI/res/values-el/strings.xml3
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml3
-rw-r--r--packages/SystemUI/res/values-es/strings.xml3
-rw-r--r--packages/SystemUI/res/values-et-rEE/strings.xml3
-rw-r--r--packages/SystemUI/res/values-eu-rES/strings.xml5
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml3
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml3
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-gl-rES/strings.xml3
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml3
-rw-r--r--packages/SystemUI/res/values-hy-rAM/strings.xml3
-rw-r--r--packages/SystemUI/res/values-is-rIS/strings.xml3
-rw-r--r--packages/SystemUI/res/values-it/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml3
-rw-r--r--packages/SystemUI/res/values-kk-rKZ/strings.xml3
-rw-r--r--packages/SystemUI/res/values-kn-rIN/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ky-rKG/strings.xml3
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings.xml3
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml3
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml3
-rw-r--r--packages/SystemUI/res/values-mk-rMK/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ml-rIN/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings.xml3
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml9
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml3
-rw-r--r--packages/SystemUI/res/values-si-rLK/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sw360dp/dimens.xml30
-rw-r--r--packages/SystemUI/res/values-sw400dp/dimens.xml27
-rw-r--r--packages/SystemUI/res/values-ta-rIN/strings.xml3
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ur-rPK/strings.xml3
-rw-r--r--packages/SystemUI/res/values-uz-rUZ/strings.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml3
-rw-r--r--packages/SystemUI/res/values/config.xml7
-rw-r--r--packages/SystemUI/res/values/dimens.xml10
-rw-r--r--packages/SystemUI/src/com/android/systemui/ExpandHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java161
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java99
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java7
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java16
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java521
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java6
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java11
-rw-r--r--services/core/java/com/android/server/TextServicesManagerService.java98
-rw-r--r--services/core/java/com/android/server/Watchdog.java22
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityManagerService.java520
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java4
-rw-r--r--services/core/java/com/android/server/am/UserSwitchingDialog.java37
-rw-r--r--services/core/java/com/android/server/connectivity/Nat464Xlat.java45
-rw-r--r--services/core/java/com/android/server/connectivity/PacManager.java9
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java3
-rw-r--r--services/core/java/com/android/server/location/GpsLocationProvider.java20
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java34
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java27
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java109
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java25
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java28
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java14
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsDatabase.java69
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java42
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsXml.java19
-rw-r--r--services/usage/java/com/android/server/usage/UserUsageStatsService.java124
-rw-r--r--telecomm/java/android/telecom/AudioState.java7
-rw-r--r--telecomm/java/android/telecom/Conference.java13
-rw-r--r--telecomm/java/android/telecom/ConferenceParticipant.aidl22
-rw-r--r--telecomm/java/android/telecom/ConferenceParticipant.java158
-rw-r--r--telecomm/java/android/telecom/Connection.java15
-rw-r--r--telecomm/java/android/telecom/ConnectionService.java123
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapter.java16
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapterServant.java20
-rw-r--r--telecomm/java/android/telecom/DisconnectCause.java8
-rw-r--r--telecomm/java/android/telecom/GatewayInfo.java30
-rw-r--r--telecomm/java/android/telecom/PhoneAccountHandle.java11
-rw-r--r--telecomm/java/android/telecom/PhoneCapabilities.java27
-rw-r--r--telecomm/java/android/telecom/RemoteConnection.java25
-rw-r--r--telecomm/java/android/telecom/RemoteConnectionService.java12
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java49
-rw-r--r--telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl2
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl5
-rw-r--r--telephony/java/android/telephony/SignalStrength.java28
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java11
-rw-r--r--telephony/java/com/android/ims/ImsConferenceState.java28
-rw-r--r--test-runner/src/android/test/mock/MockPackageManager.java8
-rw-r--r--tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java59
-rw-r--r--tools/layoutlib/bridge/src/android/animation/FakeAnimator.java52
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/BridgeResources.java2
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java10
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java48
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java20
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java5
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java4
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java14
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java2
375 files changed, 7680 insertions, 2430 deletions
diff --git a/api/current.txt b/api/current.txt
index 4cfab54129b1..6851bbf36df6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -113,8 +113,9 @@ package android {
field public static final java.lang.String RECEIVE_SMS = "android.permission.RECEIVE_SMS";
field public static final java.lang.String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
+ field public static final java.lang.String REGISTER_CALL_PROVIDER = "android.permission.REGISTER_CALL_PROVIDER";
field public static final java.lang.String REGISTER_CONNECTION_MANAGER = "android.permission.REGISTER_CONNECTION_MANAGER";
- field public static final java.lang.String REGISTER_PROVIDER_OR_SUBSCRIPTION = "android.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION";
+ field public static final java.lang.String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION";
field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS";
field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
@@ -239,6 +240,8 @@ package android {
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
field public static final int accessibilityFlags = 16843652; // 0x1010384
field public static final int accessibilityLiveRegion = 16843758; // 0x10103ee
+ field public static final int accessibilityTraversalAfter = 16844036; // 0x1010504
+ field public static final int accessibilityTraversalBefore = 16844035; // 0x1010503
field public static final int accountPreferences = 16843423; // 0x101029f
field public static final int accountType = 16843407; // 0x101028f
field public static final int action = 16842797; // 0x101002d
@@ -402,6 +405,7 @@ package android {
field public static final int closeIcon = 16843905; // 0x1010481
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
+ field public static final int collapseContentDescription = 16844034; // 0x1010502
field public static final int color = 16843173; // 0x10101a5
field public static final int colorAccent = 16843829; // 0x1010435
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
@@ -9259,6 +9263,7 @@ package android.content.res {
method public int getType(int);
method public boolean getValue(int, android.util.TypedValue);
method public boolean hasValue(int);
+ method public boolean hasValueOrEmpty(int);
method public int length();
method public android.util.TypedValue peekValue(int);
method public void recycle();
@@ -25144,6 +25149,7 @@ package android.provider {
field public static final java.lang.String ACTION_APPLICATION_DETAILS_SETTINGS = "android.settings.APPLICATION_DETAILS_SETTINGS";
field public static final java.lang.String ACTION_APPLICATION_DEVELOPMENT_SETTINGS = "android.settings.APPLICATION_DEVELOPMENT_SETTINGS";
field public static final java.lang.String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS";
+ field public static final java.lang.String ACTION_BATTERY_SAVER_SETTINGS = "android.settings.BATTERY_SAVER_SETTINGS";
field public static final java.lang.String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS";
field public static final java.lang.String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS";
field public static final java.lang.String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS";
@@ -25165,6 +25171,7 @@ package android.provider {
field public static final java.lang.String ACTION_NFCSHARING_SETTINGS = "android.settings.NFCSHARING_SETTINGS";
field public static final java.lang.String ACTION_NFC_PAYMENT_SETTINGS = "android.settings.NFC_PAYMENT_SETTINGS";
field public static final java.lang.String ACTION_NFC_SETTINGS = "android.settings.NFC_SETTINGS";
+ field public static final java.lang.String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
field public static final java.lang.String ACTION_PRINT_SETTINGS = "android.settings.ACTION_PRINT_SETTINGS";
field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
@@ -28089,6 +28096,7 @@ package android.telecom {
method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
method public final java.util.List<android.telecom.Connection> getConnections();
method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle();
+ method public android.telecom.Connection getPrimaryConnection();
method public final int getState();
method public void onAudioStateChanged(android.telecom.AudioState);
method public void onDisconnect();
@@ -28178,6 +28186,7 @@ package android.telecom {
public abstract class ConnectionService extends android.app.Service {
ctor public ConnectionService();
method public final void addConference(android.telecom.Conference);
+ method public final void addExistingConnection(android.telecom.PhoneAccountHandle, android.telecom.Connection);
method public final void conferenceRemoteConnections(android.telecom.RemoteConnection, android.telecom.RemoteConnection);
method public final android.telecom.RemoteConnection createRemoteIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public final android.telecom.RemoteConnection createRemoteOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
@@ -28187,6 +28196,7 @@ package android.telecom {
method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
+ method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
}
@@ -28385,6 +28395,7 @@ package android.telecom {
method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
method public boolean handleMmi(java.lang.String);
+ method public boolean handleMmi(android.telecom.PhoneAccountHandle, java.lang.String);
method public boolean hasMultipleCallCapableAccounts();
method public boolean isInCall();
method public void registerPhoneAccount(android.telecom.PhoneAccount);
@@ -28767,6 +28778,7 @@ package android.telephony {
field public static final int MMS_ERROR_RETRY = 6; // 0x6
field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3
field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1
+ field public static final java.lang.String MMS_SHOW_CELL_BROADCAST_APP_LINKS = "config_cellBroadcastAppLinks";
field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1
field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4
field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3
@@ -32147,6 +32159,7 @@ package android.util {
method public static int complexToDimensionPixelSize(int, android.util.DisplayMetrics);
method public static float complexToFloat(int);
method public static float complexToFraction(int, float, float);
+ method public int getComplexUnit();
method public float getDimension(android.util.DisplayMetrics);
method public final float getFloat();
method public float getFraction(float, float);
@@ -32169,6 +32182,8 @@ package android.util {
field public static final int COMPLEX_UNIT_PX = 0; // 0x0
field public static final int COMPLEX_UNIT_SHIFT = 0; // 0x0
field public static final int COMPLEX_UNIT_SP = 2; // 0x2
+ field public static final int DATA_NULL_EMPTY = 1; // 0x1
+ field public static final int DATA_NULL_UNDEFINED = 0; // 0x0
field public static final int DENSITY_DEFAULT = 0; // 0x0
field public static final int DENSITY_NONE = 65535; // 0xffff
field public static final int TYPE_ATTRIBUTE = 2; // 0x2
@@ -33600,6 +33615,8 @@ package android.view {
method public static int generateViewId();
method public int getAccessibilityLiveRegion();
method public android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider();
+ method public int getAccessibilityTraversalAfter();
+ method public int getAccessibilityTraversalBefore();
method public float getAlpha();
method public android.view.animation.Animation getAnimation();
method public android.os.IBinder getApplicationWindowToken();
@@ -33876,6 +33893,8 @@ package android.view {
method public void sendAccessibilityEventUnchecked(android.view.accessibility.AccessibilityEvent);
method public void setAccessibilityDelegate(android.view.View.AccessibilityDelegate);
method public void setAccessibilityLiveRegion(int);
+ method public void setAccessibilityTraversalAfter(int);
+ method public void setAccessibilityTraversalBefore(int);
method public void setActivated(boolean);
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
@@ -34726,12 +34745,14 @@ package android.view {
method public void setCallback(android.view.Window.Callback);
method public abstract void setChildDrawable(int, android.graphics.drawable.Drawable);
method public abstract void setChildInt(int, int);
+ method public void setClipToOutline(boolean);
method public void setContainer(android.view.Window);
method public abstract void setContentView(int);
method public abstract void setContentView(android.view.View);
method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method protected void setDefaultWindowFormat(int);
method public void setDimAmount(float);
+ method public void setElevation(float);
method public void setEnterTransition(android.transition.Transition);
method public void setExitTransition(android.transition.Transition);
method public abstract void setFeatureDrawable(int, android.graphics.drawable.Drawable);
@@ -35153,6 +35174,8 @@ package android.view.accessibility {
method public java.lang.CharSequence getText();
method public int getTextSelectionEnd();
method public int getTextSelectionStart();
+ method public android.view.accessibility.AccessibilityNodeInfo getTraversalAfter();
+ method public android.view.accessibility.AccessibilityNodeInfo getTraversalBefore();
method public java.lang.String getViewIdResourceName();
method public android.view.accessibility.AccessibilityWindowInfo getWindow();
method public int getWindowId();
@@ -35223,6 +35246,10 @@ package android.view.accessibility {
method public void setSource(android.view.View, int);
method public void setText(java.lang.CharSequence);
method public void setTextSelection(int, int);
+ method public void setTraversalAfter(android.view.View);
+ method public void setTraversalAfter(android.view.View, int);
+ method public void setTraversalBefore(android.view.View);
+ method public void setTraversalBefore(android.view.View, int);
method public void setViewIdResourceName(java.lang.String);
method public void setVisibleToUser(boolean);
method public void writeToParcel(android.os.Parcel, int);
@@ -38420,6 +38447,8 @@ package android.widget {
method public boolean onLoadClass(java.lang.Class);
method public void reapply(android.content.Context, android.view.View);
method public void removeAllViews(int);
+ method public void setAccessibilityTraversalAfter(int, int);
+ method public void setAccessibilityTraversalBefore(int, int);
method public void setBitmap(int, java.lang.String, android.graphics.Bitmap);
method public void setBoolean(int, java.lang.String, boolean);
method public void setBundle(int, java.lang.String, android.os.Bundle);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 5e9d8f74f342..7fd586f31516 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -96,8 +96,9 @@ public final class Pm {
"Error: Could not access the Package Manager. Is the system running?";
public static void main(String[] args) {
+ int exitCode = 1;
try {
- new Pm().run(args);
+ exitCode = new Pm().run(args);
} catch (Exception e) {
Log.e(TAG, "Error", e);
System.err.println("Error: " + e);
@@ -105,20 +106,20 @@ public final class Pm {
System.err.println(PM_NOT_RUNNING_ERR);
}
}
+ System.exit(exitCode);
}
- public void run(String[] args) throws IOException, RemoteException {
+ public int run(String[] args) throws IOException, RemoteException {
boolean validCommand = false;
if (args.length < 1) {
- showUsage();
- return;
+ return showUsage();
}
mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user"));
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
if (mPm == null) {
System.err.println(PM_NOT_RUNNING_ERR);
- return;
+ return 1;
}
mInstaller = mPm.getPackageInstaller();
@@ -127,155 +128,129 @@ public final class Pm {
mNextArg = 1;
if ("list".equals(op)) {
- runList();
- return;
+ return runList();
}
if ("path".equals(op)) {
- runPath();
- return;
+ return runPath();
}
if ("dump".equals(op)) {
- runDump();
- return;
+ return runDump();
}
if ("install".equals(op)) {
- runInstall();
- return;
+ return runInstall();
}
if ("install-create".equals(op)) {
- runInstallCreate();
- return;
+ return runInstallCreate();
}
if ("install-write".equals(op)) {
- runInstallWrite();
- return;
+ return runInstallWrite();
}
if ("install-commit".equals(op)) {
- runInstallCommit();
- return;
+ return runInstallCommit();
}
if ("install-abandon".equals(op) || "install-destroy".equals(op)) {
- runInstallAbandon();
- return;
+ return runInstallAbandon();
}
if ("set-installer".equals(op)) {
- runSetInstaller();
- return;
+ return runSetInstaller();
}
if ("uninstall".equals(op)) {
- runUninstall();
- return;
+ return runUninstall();
}
if ("clear".equals(op)) {
- runClear();
- return;
+ return runClear();
}
if ("enable".equals(op)) {
- runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
- return;
+ return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
}
if ("disable".equals(op)) {
- runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
- return;
+ return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
}
if ("disable-user".equals(op)) {
- runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
- return;
+ return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
}
if ("disable-until-used".equals(op)) {
- runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
- return;
+ return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
}
if ("hide".equals(op)) {
- runSetHiddenSetting(true);
- return;
+ return runSetHiddenSetting(true);
}
if ("unhide".equals(op)) {
- runSetHiddenSetting(false);
- return;
+ return runSetHiddenSetting(false);
}
if ("grant".equals(op)) {
- runGrantRevokePermission(true);
- return;
+ return runGrantRevokePermission(true);
}
if ("revoke".equals(op)) {
- runGrantRevokePermission(false);
- return;
+ return runGrantRevokePermission(false);
}
if ("set-permission-enforced".equals(op)) {
- runSetPermissionEnforced();
- return;
+ return runSetPermissionEnforced();
}
if ("set-install-location".equals(op)) {
- runSetInstallLocation();
- return;
+ return runSetInstallLocation();
}
if ("get-install-location".equals(op)) {
- runGetInstallLocation();
- return;
+ return runGetInstallLocation();
}
if ("trim-caches".equals(op)) {
- runTrimCaches();
- return;
+ return runTrimCaches();
}
if ("create-user".equals(op)) {
- runCreateUser();
- return;
+ return runCreateUser();
}
if ("remove-user".equals(op)) {
- runRemoveUser();
- return;
+ return runRemoveUser();
}
if ("get-max-users".equals(op)) {
- runGetMaxUsers();
- return;
+ return runGetMaxUsers();
}
if ("force-dex-opt".equals(op)) {
- runForceDexOpt();
- return;
+ return runForceDexOpt();
}
try {
if (args.length == 1) {
if (args[0].equalsIgnoreCase("-l")) {
validCommand = true;
- runListPackages(false);
+ return runListPackages(false);
} else if (args[0].equalsIgnoreCase("-lf")){
validCommand = true;
- runListPackages(true);
+ return runListPackages(true);
}
} else if (args.length == 2) {
if (args[0].equalsIgnoreCase("-p")) {
validCommand = true;
- displayPackageFilePath(args[1]);
+ return displayPackageFilePath(args[1]);
}
}
+ return 1;
} finally {
if (validCommand == false) {
if (op != null) {
@@ -296,35 +271,36 @@ public final class Pm {
* pm list libraries
* pm list instrumentation
*/
- private void runList() {
+ private int runList() {
String type = nextArg();
if (type == null) {
System.err.println("Error: didn't specify type of data to list");
- return;
+ return 1;
}
if ("package".equals(type) || "packages".equals(type)) {
- runListPackages(false);
+ return runListPackages(false);
} else if ("permission-groups".equals(type)) {
- runListPermissionGroups();
+ return runListPermissionGroups();
} else if ("permissions".equals(type)) {
- runListPermissions();
+ return runListPermissions();
} else if ("features".equals(type)) {
- runListFeatures();
+ return runListFeatures();
} else if ("libraries".equals(type)) {
- runListLibraries();
+ return runListLibraries();
} else if ("instrumentation".equals(type)) {
- runListInstrumentation();
+ return runListInstrumentation();
} else if ("users".equals(type)) {
- runListUsers();
+ return runListUsers();
} else {
System.err.println("Error: unknown list type '" + type + "'");
+ return 1;
}
}
/**
* Lists all the installed packages.
*/
- private void runListPackages(boolean showApplicationPackage) {
+ private int runListPackages(boolean showApplicationPackage) {
int getFlags = 0;
boolean listDisabled = false, listEnabled = false;
boolean listSystem = false, listThirdParty = false;
@@ -355,12 +331,12 @@ public final class Pm {
getFlags |= PackageManager.GET_UNINSTALLED_PACKAGES;
} else {
System.err.println("Error: Unknown option: " + opt);
- return;
+ return 1;
}
}
} catch (RuntimeException ex) {
System.err.println("Error: " + ex.toString());
- return;
+ return 1;
}
String filter = nextArg();
@@ -393,9 +369,11 @@ public final class Pm {
System.out.println();
}
}
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
@@ -411,7 +389,7 @@ public final class Pm {
*
* pm list features
*/
- private void runListFeatures() {
+ private int runListFeatures() {
try {
List<FeatureInfo> list = new ArrayList<FeatureInfo>();
FeatureInfo[] rawList = mPm.getSystemAvailableFeatures();
@@ -438,9 +416,11 @@ public final class Pm {
else System.out.println("reqGlEsVersion=0x"
+ Integer.toHexString(fi.reqGlEsVersion));
}
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
@@ -449,7 +429,7 @@ public final class Pm {
*
* pm list libraries
*/
- private void runListLibraries() {
+ private int runListLibraries() {
try {
List<String> list = new ArrayList<String>();
String[] rawList = mPm.getSystemSharedLibraryNames();
@@ -474,9 +454,11 @@ public final class Pm {
System.out.print("library:");
System.out.println(lib);
}
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
@@ -485,7 +467,7 @@ public final class Pm {
*
* pm list instrumentation [package] [-f]
*/
- private void runListInstrumentation() {
+ private int runListInstrumentation() {
int flags = 0; // flags != 0 is only used to request meta-data
boolean showPackage = false;
String targetPackage = null;
@@ -499,12 +481,12 @@ public final class Pm {
targetPackage = opt;
} else {
System.err.println("Error: Unknown option: " + opt);
- return;
+ return 1;
}
}
} catch (RuntimeException ex) {
System.err.println("Error: " + ex.toString());
- return;
+ return 1;
}
try {
@@ -531,16 +513,18 @@ public final class Pm {
System.out.print(ii.targetPackage);
System.out.println(")");
}
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
/**
* Lists all the known permission groups.
*/
- private void runListPermissionGroups() {
+ private int runListPermissionGroups() {
try {
List<PermissionGroupInfo> pgs = mPm.getAllPermissionGroups(0);
@@ -550,9 +534,11 @@ public final class Pm {
System.out.print("permission group:");
System.out.println(pgi.name);
}
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
@@ -572,7 +558,7 @@ public final class Pm {
/**
* Lists all the permissions in a group.
*/
- private void runListPermissions() {
+ private int runListPermissions() {
try {
boolean labels = false;
boolean groups = false;
@@ -595,7 +581,7 @@ public final class Pm {
dangerousOnly = true;
} else {
System.err.println("Error: Unknown option: " + opt);
- return;
+ return 1;
}
}
@@ -637,9 +623,11 @@ public final class Pm {
doListPermissions(groupList, groups, labels, summary,
-10000, 10000);
}
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
@@ -739,22 +727,23 @@ public final class Pm {
}
}
- private void runPath() {
+ private int runPath() {
String pkg = nextArg();
if (pkg == null) {
System.err.println("Error: no package specified");
- return;
+ return 1;
}
- displayPackageFilePath(pkg);
+ return displayPackageFilePath(pkg);
}
- private void runDump() {
+ private int runDump() {
String pkg = nextArg();
if (pkg == null) {
System.err.println("Error: no package specified");
- return;
+ return 1;
}
ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg);
+ return 0;
}
class LocalPackageInstallObserver extends PackageInstallObserver {
@@ -822,31 +811,34 @@ public final class Pm {
return Integer.toString(result);
}
- private void runSetInstallLocation() {
+ private int runSetInstallLocation() {
int loc;
String arg = nextArg();
if (arg == null) {
System.err.println("Error: no install location specified.");
- return;
+ return 1;
}
try {
loc = Integer.parseInt(arg);
} catch (NumberFormatException e) {
System.err.println("Error: install location has to be a number.");
- return;
+ return 1;
}
try {
if (!mPm.setInstallLocation(loc)) {
System.err.println("Error: install location has to be a number.");
+ return 1;
}
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
- private void runGetInstallLocation() {
+ private int runGetInstallLocation() {
try {
int loc = mPm.getInstallLocation();
String locStr = "invalid";
@@ -858,13 +850,15 @@ public final class Pm {
locStr = "external";
}
System.out.println(loc + "[" + locStr + "]");
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
- private void runInstall() {
+ private int runInstall() {
int installFlags = 0;
int userId = UserHandle.USER_ALL;
String installerPackageName = null;
@@ -884,7 +878,7 @@ public final class Pm {
installerPackageName = nextOptionData();
if (installerPackageName == null) {
System.err.println("Error: no value specified for -i");
- return;
+ return 1;
}
} else if (opt.equals("-t")) {
installFlags |= PackageManager.INSTALL_ALLOW_TEST;
@@ -900,13 +894,13 @@ public final class Pm {
originatingUriString = nextOptionData();
if (originatingUriString == null) {
System.err.println("Error: must supply argument for --originating-uri");
- return;
+ return 1;
}
} else if (opt.equals("--referrer")) {
referrer = nextOptionData();
if (referrer == null) {
System.err.println("Error: must supply argument for --referrer");
- return;
+ return 1;
}
} else if (opt.equals("--abi")) {
abi = checkAbiArgument(nextOptionData());
@@ -914,7 +908,7 @@ public final class Pm {
userId = Integer.parseInt(nextOptionData());
} else {
System.err.println("Error: Unknown option: " + opt);
- return;
+ return 1;
}
}
@@ -944,7 +938,7 @@ public final class Pm {
System.err.println("\tpkg: " + apkFilePath);
if (apkFilePath == null) {
System.err.println("Error: no package specified");
- return;
+ return 1;
}
// Populate verificationURI, optionally present
@@ -973,19 +967,22 @@ public final class Pm {
}
if (obs.result == PackageManager.INSTALL_SUCCEEDED) {
System.out.println("Success");
+ return 0;
} else {
System.err.println("Failure ["
+ installFailureToString(obs)
+ "]");
+ return 1;
}
}
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
- private void runInstallCreate() throws RemoteException {
+ private int runInstallCreate() throws RemoteException {
int userId = UserHandle.USER_ALL;
String installerPackageName = null;
@@ -1040,9 +1037,10 @@ public final class Pm {
// NOTE: adb depends on parsing this string
System.out.println("Success: created install session [" + sessionId + "]");
+ return 0;
}
- private void runInstallWrite() throws IOException, RemoteException {
+ private int runInstallWrite() throws IOException, RemoteException {
long sizeBytes = -1;
String opt;
@@ -1097,6 +1095,7 @@ public final class Pm {
session.fsync(out);
System.out.println("Success: streamed " + total + " bytes");
+ return 0;
} finally {
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(in);
@@ -1104,7 +1103,7 @@ public final class Pm {
}
}
- private void runInstallCommit() throws RemoteException {
+ private int runInstallCommit() throws RemoteException {
final int sessionId = Integer.parseInt(nextArg());
PackageInstaller.Session session = null;
@@ -1119,18 +1118,19 @@ public final class Pm {
PackageInstaller.STATUS_FAILURE);
if (status == PackageInstaller.STATUS_SUCCESS) {
System.out.println("Success");
+ return 0;
} else {
Log.e(TAG, "Failure details: " + result.getExtras());
- System.out.println("Failure ["
+ System.err.println("Failure ["
+ result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
- return;
+ return 1;
}
} finally {
IoUtils.closeQuietly(session);
}
}
- private void runInstallAbandon() throws RemoteException {
+ private int runInstallAbandon() throws RemoteException {
final int sessionId = Integer.parseInt(nextArg());
PackageInstaller.Session session = null;
@@ -1138,12 +1138,13 @@ public final class Pm {
session = new PackageInstaller.Session(mInstaller.openSession(sessionId));
session.abandon();
System.out.println("Success");
+ return 0;
} finally {
IoUtils.closeQuietly(session);
}
}
- private void runSetInstaller() throws RemoteException {
+ private int runSetInstaller() throws RemoteException {
final String targetPackage = nextArg();
final String installerPackageName = nextArg();
@@ -1154,9 +1155,10 @@ public final class Pm {
mPm.setInstallerPackageName(targetPackage, installerPackageName);
System.out.println("Success");
+ return 0;
}
- public void runCreateUser() {
+ public int runCreateUser() {
String name;
int userId = -1;
int flags = 0;
@@ -1167,7 +1169,7 @@ public final class Pm {
if (optionData == null || !isNumber(optionData)) {
System.err.println("Error: no USER_ID specified");
showUsage();
- return;
+ return 1;
} else {
userId = Integer.parseInt(optionData);
}
@@ -1176,13 +1178,13 @@ public final class Pm {
} else {
System.err.println("Error: unknown option " + opt);
showUsage();
- return;
+ return 1;
}
}
String arg = nextArg();
if (arg == null) {
System.err.println("Error: no user name specified.");
- return;
+ return 1;
}
name = arg;
try {
@@ -1194,75 +1196,85 @@ public final class Pm {
}
if (info != null) {
System.out.println("Success: created user id " + info.id);
+ return 1;
} else {
System.err.println("Error: couldn't create User.");
+ return 1;
}
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
-
}
- public void runRemoveUser() {
+ public int runRemoveUser() {
int userId;
String arg = nextArg();
if (arg == null) {
System.err.println("Error: no user id specified.");
- return;
+ return 1;
}
try {
userId = Integer.parseInt(arg);
} catch (NumberFormatException e) {
System.err.println("Error: user id '" + arg + "' is not a number.");
- return;
+ return 1;
}
try {
if (mUm.removeUser(userId)) {
System.out.println("Success: removed user");
+ return 0;
} else {
System.err.println("Error: couldn't remove user id " + userId);
+ return 1;
}
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
- public void runListUsers() {
+ public int runListUsers() {
try {
IActivityManager am = ActivityManagerNative.getDefault();
List<UserInfo> users = mUm.getUsers(false);
if (users == null) {
System.err.println("Error: couldn't get users");
+ return 1;
} else {
System.out.println("Users:");
for (int i = 0; i < users.size(); i++) {
String running = am.isUserRunning(users.get(i).id, false) ? " running" : "";
System.out.println("\t" + users.get(i).toString() + running);
}
+ return 0;
}
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
- public void runGetMaxUsers() {
+ public int runGetMaxUsers() {
System.out.println("Maximum supported users: " + UserManager.getMaxSupportedUsers());
+ return 0;
}
- public void runForceDexOpt() {
+ public int runForceDexOpt() {
final String packageName = nextArg();
try {
mPm.forceDexOpt(packageName);
+ return 0;
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
- private void runUninstall() throws RemoteException {
+ private int runUninstall() throws RemoteException {
int flags = 0;
int userId = UserHandle.USER_ALL;
@@ -1277,11 +1289,11 @@ public final class Pm {
} else {
showUsage();
System.err.println("Error: Invalid user: " + param);
- return;
+ return 1;
}
} else {
System.err.println("Error: Unknown option: " + opt);
- return;
+ return 1;
}
}
@@ -1289,7 +1301,7 @@ public final class Pm {
if (pkg == null) {
System.err.println("Error: no package specified");
showUsage();
- return;
+ return 1;
}
if (userId == UserHandle.USER_ALL) {
@@ -1302,11 +1314,11 @@ public final class Pm {
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
- return;
+ return 1;
}
if (info == null) {
System.err.println("Failure - not installed for " + userId);
- return;
+ return 1;
}
final boolean isSystem =
(info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
@@ -1326,10 +1338,12 @@ public final class Pm {
PackageInstaller.STATUS_FAILURE);
if (status == PackageInstaller.STATUS_SUCCESS) {
System.out.println("Success");
+ return 0;
} else {
Log.e(TAG, "Failure details: " + result.getExtras());
- System.out.println("Failure ["
+ System.err.println("Failure ["
+ result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
+ return 1;
}
}
@@ -1347,7 +1361,7 @@ public final class Pm {
}
}
- private void runClear() {
+ private int runClear() {
int userId = 0;
String option = nextOption();
if (option != null && option.equals("--user")) {
@@ -1355,7 +1369,7 @@ public final class Pm {
if (optionData == null || !isNumber(optionData)) {
System.err.println("Error: no USER_ID specified");
showUsage();
- return;
+ return 1;
} else {
userId = Integer.parseInt(optionData);
}
@@ -1365,7 +1379,7 @@ public final class Pm {
if (pkg == null) {
System.err.println("Error: no package specified");
showUsage();
- return;
+ return 1;
}
ClearDataObserver obs = new ClearDataObserver();
@@ -1381,13 +1395,16 @@ public final class Pm {
}
if (obs.result) {
- System.err.println("Success");
+ System.out.println("Success");
+ return 0;
} else {
System.err.println("Failed");
+ return 1;
}
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
@@ -1416,7 +1433,7 @@ public final class Pm {
return true;
}
- private void runSetEnabledSetting(int state) {
+ private int runSetEnabledSetting(int state) {
int userId = 0;
String option = nextOption();
if (option != null && option.equals("--user")) {
@@ -1424,7 +1441,7 @@ public final class Pm {
if (optionData == null || !isNumber(optionData)) {
System.err.println("Error: no USER_ID specified");
showUsage();
- return;
+ return 1;
} else {
userId = Integer.parseInt(optionData);
}
@@ -1434,34 +1451,38 @@ public final class Pm {
if (pkg == null) {
System.err.println("Error: no package or component specified");
showUsage();
- return;
+ return 1;
}
ComponentName cn = ComponentName.unflattenFromString(pkg);
if (cn == null) {
try {
mPm.setApplicationEnabledSetting(pkg, state, 0, userId,
"shell:" + android.os.Process.myUid());
- System.err.println("Package " + pkg + " new state: "
+ System.out.println("Package " + pkg + " new state: "
+ enabledSettingToString(
mPm.getApplicationEnabledSetting(pkg, userId)));
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
} else {
try {
mPm.setComponentEnabledSetting(cn, state, 0, userId);
- System.err.println("Component " + cn.toShortString() + " new state: "
+ System.out.println("Component " + cn.toShortString() + " new state: "
+ enabledSettingToString(
mPm.getComponentEnabledSetting(cn, userId)));
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
}
- private void runSetHiddenSetting(boolean state) {
+ private int runSetHiddenSetting(boolean state) {
int userId = 0;
String option = nextOption();
if (option != null && option.equals("--user")) {
@@ -1469,7 +1490,7 @@ public final class Pm {
if (optionData == null || !isNumber(optionData)) {
System.err.println("Error: no USER_ID specified");
showUsage();
- return;
+ return 1;
} else {
userId = Integer.parseInt(optionData);
}
@@ -1479,30 +1500,32 @@ public final class Pm {
if (pkg == null) {
System.err.println("Error: no package or component specified");
showUsage();
- return;
+ return 1;
}
try {
mPm.setApplicationHiddenSettingAsUser(pkg, state, userId);
- System.err.println("Package " + pkg + " new hidden state: "
+ System.out.println("Package " + pkg + " new hidden state: "
+ mPm.getApplicationHiddenSettingAsUser(pkg, userId));
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
}
}
- private void runGrantRevokePermission(boolean grant) {
+ private int runGrantRevokePermission(boolean grant) {
String pkg = nextArg();
if (pkg == null) {
System.err.println("Error: no package specified");
showUsage();
- return;
+ return 1;
}
String perm = nextArg();
if (perm == null) {
System.err.println("Error: no permission specified");
showUsage();
- return;
+ return 1;
}
try {
if (grant) {
@@ -1510,41 +1533,49 @@ public final class Pm {
} else {
mPm.revokePermission(pkg, perm);
}
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
} catch (IllegalArgumentException e) {
System.err.println("Bad argument: " + e.toString());
showUsage();
+ return 1;
} catch (SecurityException e) {
System.err.println("Operation not allowed: " + e.toString());
+ return 1;
}
}
- private void runSetPermissionEnforced() {
+ private int runSetPermissionEnforced() {
final String permission = nextArg();
if (permission == null) {
System.err.println("Error: no permission specified");
showUsage();
- return;
+ return 1;
}
final String enforcedRaw = nextArg();
if (enforcedRaw == null) {
System.err.println("Error: no enforcement specified");
showUsage();
- return;
+ return 1;
}
final boolean enforced = Boolean.parseBoolean(enforcedRaw);
try {
mPm.setPermissionEnforced(permission, enforced);
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
} catch (IllegalArgumentException e) {
System.err.println("Bad argument: " + e.toString());
showUsage();
+ return 1;
} catch (SecurityException e) {
System.err.println("Operation not allowed: " + e.toString());
+ return 1;
}
}
@@ -1563,12 +1594,12 @@ public final class Pm {
}
- private void runTrimCaches() {
+ private int runTrimCaches() {
String size = nextArg();
if (size == null) {
System.err.println("Error: no size specified");
showUsage();
- return;
+ return 1;
}
int len = size.length();
long multiplier = 1;
@@ -1583,7 +1614,7 @@ public final class Pm {
} else {
System.err.println("Invalid suffix: " + c);
showUsage();
- return;
+ return 1;
}
size = size.substring(0, len-1);
}
@@ -1593,7 +1624,7 @@ public final class Pm {
} catch (NumberFormatException e) {
System.err.println("Error: expected number at: " + size);
showUsage();
- return;
+ return 1;
}
ClearDataObserver obs = new ClearDataObserver();
try {
@@ -1606,14 +1637,18 @@ public final class Pm {
}
}
}
+ return 0;
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
+ return 1;
} catch (IllegalArgumentException e) {
System.err.println("Bad argument: " + e.toString());
showUsage();
+ return 1;
} catch (SecurityException e) {
System.err.println("Operation not allowed: " + e.toString());
+ return 1;
}
}
@@ -1621,7 +1656,7 @@ public final class Pm {
* Displays the package file for a package.
* @param pckg
*/
- private void displayPackageFilePath(String pckg) {
+ private int displayPackageFilePath(String pckg) {
try {
PackageInfo info = mPm.getPackageInfo(pckg, 0, 0);
if (info != null && info.applicationInfo != null) {
@@ -1632,12 +1667,14 @@ public final class Pm {
System.out.print("package:");
System.out.println(splitSourceDir);
}
+ return 0;
}
}
} catch (RemoteException e) {
System.err.println(e.toString());
System.err.println(PM_NOT_RUNNING_ERR);
}
+ return 1;
}
private Resources getResources(PackageItemInfo pii) {
@@ -1752,7 +1789,7 @@ public final class Pm {
return arg;
}
- private static void showUsage() {
+ private static int showUsage() {
System.err.println("usage: pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]");
System.err.println(" pm list permission-groups");
System.err.println(" pm list permissions [-g] [-f] [-d] [-u] [GROUP]");
@@ -1873,5 +1910,6 @@ public final class Pm {
System.err.println("pm remove-user: remove the user with the given USER_IDENTIFIER,");
System.err.println(" deleting all data associated with that user");
System.err.println("");
+ return 1;
}
}
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 82b6e35f9abf..9062892efde9 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -638,6 +638,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
if (decorView != null) {
decorView.getLocationOnScreen(decorLoc);
}
+ Matrix tempMatrix = new Matrix();
for (String name: names) {
Bundle sharedElementBundle = state.getBundle(name);
if (sharedElementBundle != null) {
@@ -647,7 +648,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
snapshot = mListener.onCreateSnapshotView(context, parcelable);
}
if (snapshot != null) {
- setSharedElementState(snapshot, name, state, null, null, decorLoc);
+ setSharedElementState(snapshot, name, state, tempMatrix, null, decorLoc);
}
snapshots.add(snapshot);
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 854719d18350..967e97e5af66 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1609,6 +1609,18 @@ final class ApplicationPackageManager extends PackageManager {
return null;
}
+ /**
+ * @hide
+ */
+ @Override
+ public boolean isUpgrade() {
+ try {
+ return mPM.isUpgrade();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
@Override
public PackageInstaller getPackageInstaller() {
synchronized (mLock) {
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 78948877bfe8..ecf19c783e83 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -133,16 +133,17 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
return;
}
mAreViewsReady = true;
+ final ViewGroup decor = getDecor();
// Ensure the views have been laid out before capturing the views -- we need the epicenter.
- if (sharedElements.isEmpty() || !sharedElements.valueAt(0).isLayoutRequested()) {
+ if (decor == null || (decor.isAttachedToWindow() &&
+ (sharedElements.isEmpty() || !sharedElements.valueAt(0).isLayoutRequested()))) {
viewsReady(sharedElements);
} else {
- final View sharedElement = sharedElements.valueAt(0);
- sharedElement.getViewTreeObserver()
+ decor.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- sharedElement.getViewTreeObserver().removeOnPreDrawListener(this);
+ decor.getViewTreeObserver().removeOnPreDrawListener(this);
viewsReady(sharedElements);
return true;
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a30ae573066d..74502fce9a52 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3133,9 +3133,10 @@ public class DevicePolicyManager {
}
/**
- * Called by a profile owner to disable account management for a specific type of account.
+ * Called by a device owner or profile owner to disable account management for a specific type
+ * of account.
*
- * <p>The calling device admin must be a profile owner. If it is not, a
+ * <p>The calling device admin must be a device owner or profile owner. If it is not, a
* security exception will be thrown.
*
* <p>When account management is disabled for an account type, adding or removing an account
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index f2e03cf89285..c262baed4f23 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1445,7 +1445,7 @@ public final class BluetoothAdapter {
if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
synchronized (mManagerCallback) {
mService = null;
- mLeScanClients.clear();
+ if (mLeScanClients != null) mLeScanClients.clear();
if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup();
if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup();
for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c37534aa0334..0dc86ad0cabf 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -436,6 +436,7 @@ interface IPackageManager {
boolean isFirstBoot();
boolean isOnlyCoreApps();
+ boolean isUpgrade();
void setPermissionEnforced(String permission, boolean enforced);
boolean isPermissionEnforced(String permission);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 5ee0b673e3e5..c16434073a78 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -499,20 +499,4 @@ public class LauncherApps {
obtainMessage(MSG_UNAVAILABLE, info).sendToTarget();
}
}
-
- /**
- * TODO Remove after 2014-09-22
- * @hide
- */
- public void addCallback(Callback callback) {
- registerCallback(callback);
- }
-
- /**
- * TODO Remove after 2014-09-22
- * @hide
- */
- public void removeCallback(Callback callback) {
- unregisterCallback(callback);
- }
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ab90b665c4d2..e9f7c50431b5 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3867,6 +3867,13 @@ public abstract class PackageManager {
public abstract VerifierDeviceIdentity getVerifierDeviceIdentity();
/**
+ * Returns true if the device is upgrading, such as first boot after OTA.
+ *
+ * @hide
+ */
+ public abstract boolean isUpgrade();
+
+ /**
* Return interface that offers the ability to install, upgrade, and remove
* applications on the device.
*/
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index acdd87e30798..14af58481f05 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1371,7 +1371,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
}
}
- if (!config.locale.getLanguage().isEmpty()) {
+ if (config.locale != null && !config.locale.getLanguage().isEmpty()) {
parts.add(localeToResourceQualifier(config.locale));
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 6e9efe1fdc1b..0145e05a86e4 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -18,6 +18,7 @@ package android.content.res;
import android.animation.Animator;
import android.animation.StateListAnimator;
+import android.annotation.NonNull;
import android.util.Pools.SynchronizedPool;
import android.view.ViewDebug;
import com.android.internal.util.XmlUtils;
@@ -1548,20 +1549,21 @@ public class Resources {
* contents of the typed array are ultimately filled in by
* {@link Resources#getValue}.
*
- * @param values The base set of attribute values, must be equal
- * in length to {@code attrs} or {@code null}. All values
- * must be of type {@link TypedValue#TYPE_ATTRIBUTE}.
+ * @param values The base set of attribute values, must be equal in
+ * length to {@code attrs}. All values must be of type
+ * {@link TypedValue#TYPE_ATTRIBUTE}.
* @param attrs The desired attributes to be retrieved.
* @return Returns a TypedArray holding an array of the attribute
* values. Be sure to call {@link TypedArray#recycle()}
* when done with it.
* @hide
*/
- public TypedArray resolveAttributes(int[] values, int[] attrs) {
+ @NonNull
+ public TypedArray resolveAttributes(@NonNull int[] values, @NonNull int[] attrs) {
final int len = attrs.length;
- if (values != null && len != values.length) {
+ if (values == null || len != values.length) {
throw new IllegalArgumentException(
- "Base attribute values must be null or the same length as attrs");
+ "Base attribute values must the same length as attrs");
}
final TypedArray array = TypedArray.obtain(Resources.this, len);
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 73b93c64d524..02602fb67f2a 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -807,6 +807,9 @@ public class TypedArray {
/**
* Determines whether there is an attribute at <var>index</var>.
+ * <p>
+ * <strong>Note:</strong> If the attribute was set to {@code @empty} or
+ * {@code @undefined}, this method returns {@code false}.
*
* @param index Index of attribute to retrieve.
*
@@ -824,6 +827,27 @@ public class TypedArray {
}
/**
+ * Determines whether there is an attribute at <var>index</var>, returning
+ * {@code true} if the attribute was explicitly set to {@code @empty} and
+ * {@code false} only if the attribute was undefined.
+ *
+ * @param index Index of attribute to retrieve.
+ *
+ * @return True if the attribute has a value or is empty, false otherwise.
+ */
+ public boolean hasValueOrEmpty(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
+ index *= AssetManager.STYLE_NUM_ENTRIES;
+ final int[] data = mData;
+ final int type = data[index+AssetManager.STYLE_TYPE];
+ return type != TypedValue.TYPE_NULL
+ || data[index+AssetManager.STYLE_DATA] == TypedValue.DATA_NULL_EMPTY;
+ }
+
+ /**
* Retrieve the raw TypedValue for the attribute at <var>index</var>
* and return a temporary object holding its data. This object is only
* valid until the next call on to {@link TypedArray}.
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 8447dde333d1..bb16215322ee 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -172,9 +172,12 @@ public abstract class DisplayManagerInternal {
// If true, enables automatic brightness control.
public boolean useAutoBrightness;
- //If true, scales the brightness to half of desired.
+ // If true, scales the brightness to half of desired.
public boolean lowPowerMode;
+ // If true, applies a brightness boost.
+ public boolean boostScreenBrightness;
+
// If true, prevents the screen from completely turning on if it is currently off.
// The display does not enter a "ready" state if this flag is true and screen on is
// blocked. The window manager policy blocks screen on while it prepares the keyguard to
@@ -216,6 +219,7 @@ public abstract class DisplayManagerInternal {
useAutoBrightness = other.useAutoBrightness;
blockScreenOn = other.blockScreenOn;
lowPowerMode = other.lowPowerMode;
+ boostScreenBrightness = other.boostScreenBrightness;
dozeScreenBrightness = other.dozeScreenBrightness;
dozeScreenState = other.dozeScreenState;
}
@@ -235,6 +239,7 @@ public abstract class DisplayManagerInternal {
&& useAutoBrightness == other.useAutoBrightness
&& blockScreenOn == other.blockScreenOn
&& lowPowerMode == other.lowPowerMode
+ && boostScreenBrightness == other.boostScreenBrightness
&& dozeScreenBrightness == other.dozeScreenBrightness
&& dozeScreenState == other.dozeScreenState;
}
@@ -253,6 +258,7 @@ public abstract class DisplayManagerInternal {
+ ", useAutoBrightness=" + useAutoBrightness
+ ", blockScreenOn=" + blockScreenOn
+ ", lowPowerMode=" + lowPowerMode
+ + ", boostScreenBrightness=" + boostScreenBrightness
+ ", dozeScreenBrightness=" + dozeScreenBrightness
+ ", dozeScreenState=" + Display.stateToString(dozeScreenState);
}
diff --git a/core/java/android/net/PskKeyManager.java b/core/java/android/net/PskKeyManager.java
index d1622823acd9..f82e6355961c 100644
--- a/core/java/android/net/PskKeyManager.java
+++ b/core/java/android/net/PskKeyManager.java
@@ -81,6 +81,13 @@ import javax.net.ssl.SSLEngine;
* Subclasses should normally provide their own implementation of {@code getKey} because the default
* implementation returns no key, which aborts the handshake.
*
+ * <h3>Known issues</h3>
+ * The implementation of {@code ECDHE_PSK} cipher suites in API Level 21 contains a bug which breaks
+ * compatibility with other implementations. {@code ECDHE_PSK} cipher suites are enabled by default
+ * on platforms with API Level 21 when an {@code SSLContext} is initialized with a
+ * {@code PskKeyManager}. A workaround is to disable {@code ECDHE_PSK} cipher suites on platforms
+ * with API Level 21.
+ *
* <h3>Example</h3>
* The following example illustrates how to create an {@code SSLContext} which enables the use of
* TLS-PSK in {@code SSLSocket}, {@code SSLServerSocket} and {@code SSLEngine} instances obtained
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index d0ba4b81c973..5d5d2b384e04 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -92,6 +92,11 @@ interface INetworkManagementService
void enableIpv6(String iface);
/**
+ * Enables or enables IPv6 ND offload.
+ */
+ void setInterfaceIpv6NdOffload(String iface, boolean enable);
+
+ /**
* Retrieves the network routes currently configured on the specified
* interface
*/
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 182dbee0a85c..ec3068431ea1 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -50,6 +50,7 @@ interface IPowerManager
void setStayOnSetting(int val);
void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs);
+ void boostScreenBrightness(long time);
// temporarily overrides the screen brightness settings to allow the user to
// see the effect of a settings change without applying it immediately
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 3b6ce53fd620..8307d9b11144 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -669,6 +669,28 @@ public final class PowerManager {
}
/**
+ * Boosts the brightness of the screen to maximum for a predetermined
+ * period of time. This is used to make the screen more readable in bright
+ * daylight for a short duration.
+ * <p>
+ * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+ * </p>
+ *
+ * @param time The time when the request to boost was issued, in the
+ * {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
+ * order the boost request with other power management functions. It should be set
+ * to the timestamp of the input event that caused the request to boost.
+ *
+ * @hide Requires signature permission.
+ */
+ public void boostScreenBrightness(long time) {
+ try {
+ mService.boostScreenBrightness(time);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Sets the brightness of the backlights (screen, keyboard, button).
* <p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
diff --git a/core/java/android/print/IPrintDocumentAdapter.aidl b/core/java/android/print/IPrintDocumentAdapter.aidl
index 9d384fba874d..8f33e0b2c003 100644
--- a/core/java/android/print/IPrintDocumentAdapter.aidl
+++ b/core/java/android/print/IPrintDocumentAdapter.aidl
@@ -37,4 +37,5 @@ oneway interface IPrintDocumentAdapter {
void write(in PageRange[] pages, in ParcelFileDescriptor fd,
IWriteResultCallback callback, int sequence);
void finish();
+ void kill(String reason);
}
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index bf8ac651ed51..3fb812e401f7 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -634,6 +634,17 @@ public final class PrintManager {
}
@Override
+ public void kill(String reason) {
+ synchronized (mLock) {
+ // If destroyed the handler is null.
+ if (!isDestroyedLocked()) {
+ mHandler.obtainMessage(MyHandler.MSG_ON_KILL,
+ reason).sendToTarget();
+ }
+ }
+ }
+
+ @Override
public void onActivityPaused(Activity activity) {
/* do nothing */
}
@@ -719,6 +730,7 @@ public final class PrintManager {
public static final int MSG_ON_LAYOUT = 2;
public static final int MSG_ON_WRITE = 3;
public static final int MSG_ON_FINISH = 4;
+ public static final int MSG_ON_KILL = 5;
public MyHandler(Looper looper) {
super(looper, null, true);
@@ -794,6 +806,15 @@ public final class PrintManager {
}
} break;
+ case MSG_ON_KILL: {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onKill()");
+ }
+
+ String reason = (String) message.obj;
+ throw new RuntimeException(reason);
+ }
+
default: {
throw new IllegalArgumentException("Unknown message: "
+ message.what);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a1652797a842..c54a5ba80548 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -787,11 +787,10 @@ public final class Settings {
* <p>
* Output: Nothing.
* @see android.service.notification.NotificationListenerService
- * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_NOTIFICATION_LISTENER_SETTINGS
- = "android.settings.NOTIFICATION_LISTENER_SETTINGS";
+ = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
/**
* @hide
@@ -873,8 +872,9 @@ public final class Settings {
/**
* Activity Action: Show battery saver settings.
- *
- * @hide
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you safeguard
+ * against this.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_BATTERY_SAVER_SETTINGS
@@ -4738,8 +4738,8 @@ public final class Settings {
public static final String SMS_DEFAULT_APPLICATION = "sms_default_application";
/**
- * Name of a package that the current user has explicitly allowed to see all of that
- * user's notifications.
+ * Names of the packages that the current user has explicitly allowed to
+ * see all of the user's notifications, separated by ':'.
*
* @hide
*/
@@ -6629,7 +6629,8 @@ public final class Settings {
WIFI_NUM_OPEN_NETWORKS_KEPT,
EMERGENCY_TONE,
CALL_AUTO_RETRY,
- DOCK_AUDIO_MEDIA_ENABLED
+ DOCK_AUDIO_MEDIA_ENABLED,
+ LOW_POWER_MODE_TRIGGER_LEVEL
};
// Populated lazily, guarded by class object:
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 931fb8114716..74d42452503e 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -139,6 +139,17 @@ public class TypedValue {
/* ------------------------------------------------------------ */
/**
+ * {@link #TYPE_NULL} data indicating the value was not specified.
+ */
+ public static final int DATA_NULL_UNDEFINED = 0;
+ /**
+ * {@link #TYPE_NULL} data indicating the value was explicitly set to null.
+ */
+ public static final int DATA_NULL_EMPTY = 1;
+
+ /* ------------------------------------------------------------ */
+
+ /**
* If {@link #density} is equal to this value, then the density should be
* treated as the system's default density value: {@link DisplayMetrics#DENSITY_DEFAULT}.
*/
@@ -301,6 +312,18 @@ public class TypedValue {
}
/**
+ * Return the complex unit type for this value. For example, a dimen type
+ * with value 12sp will return {@link #COMPLEX_UNIT_SP}. Only use for values
+ * whose type is {@link #TYPE_DIMENSION}.
+ *
+ * @return The complex unit type.
+ */
+ public int getComplexUnit()
+ {
+ return COMPLEX_UNIT_MASK & (data>>TypedValue.COMPLEX_UNIT_SHIFT);
+ }
+
+ /**
* Converts an unpacked complex data value holding a dimension to its final floating
* point value. The two parameters <var>unit</var> and <var>value</var>
* are as in {@link #TYPE_DIMENSION}.
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 3e7aae00af64..9fc80fcf4235 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -85,4 +85,9 @@ oneway interface IWindow {
* is done.
*/
void doneAnimating();
+
+ /**
+ * Called for non-application windows when the enter animation has completed.
+ */
+ void dispatchWindowShown();
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 0711aed3aa57..00a88846a56a 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -191,7 +191,8 @@ public class ThreadedRenderer extends HardwareRenderer {
final float lightX = width / 2.0f;
mWidth = width;
mHeight = height;
- if (surfaceInsets != null && !surfaceInsets.isEmpty()) {
+ if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0
+ || surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) {
mHasInsets = true;
mInsetLeft = surfaceInsets.left;
mInsetTop = surfaceInsets.top;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e7b98ca4b3fd..1d09696c517f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3109,6 +3109,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private MatchLabelForPredicate mMatchLabelForPredicate;
/**
+ * Specifies a view before which this one is visited in accessibility traversal.
+ */
+ private int mAccessibilityTraversalBeforeId = NO_ID;
+
+ /**
+ * Specifies a view after which this one is visited in accessibility traversal.
+ */
+ private int mAccessibilityTraversalAfterId = NO_ID;
+
+ /**
* Predicate for matching a view by its id.
*/
private MatchIdPredicate mMatchIdPredicate;
@@ -3229,6 +3239,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
+ protected OnScrollChangeListener mOnScrollChangeListener;
+
/**
* Listeners for attach events.
*/
@@ -3886,6 +3898,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
case com.android.internal.R.styleable.View_contentDescription:
setContentDescription(a.getString(attr));
break;
+ case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
+ setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
+ break;
+ case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
+ setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
+ break;
case com.android.internal.R.styleable.View_labelFor:
setLabelFor(a.getResourceId(attr, NO_ID));
break;
@@ -4606,6 +4624,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Register a callback to be invoked when the scroll position of this view
+ * changed.
+ *
+ * @param l The callback that will run.
+ * @hide Only used internally.
+ */
+ public void setOnScrollChangeListener(OnScrollChangeListener l) {
+ getListenerInfo().mOnScrollChangeListener = l;
+ }
+
+ /**
* Register a callback to be invoked when focus of this view changed.
*
* @param l The callback that will run.
@@ -5598,6 +5627,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (rootView == null) {
rootView = this;
}
+
View label = rootView.findLabelForView(this, mID);
if (label != null) {
info.setLabeledBy(label);
@@ -5626,6 +5656,30 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
+ if (mAccessibilityTraversalBeforeId != View.NO_ID) {
+ View rootView = getRootView();
+ if (rootView == null) {
+ rootView = this;
+ }
+ View next = rootView.findViewInsideOutShouldExist(this,
+ mAccessibilityTraversalBeforeId);
+ if (next != null) {
+ info.setTraversalBefore(next);
+ }
+ }
+
+ if (mAccessibilityTraversalAfterId != View.NO_ID) {
+ View rootView = getRootView();
+ if (rootView == null) {
+ rootView = this;
+ }
+ View next = rootView.findViewInsideOutShouldExist(this,
+ mAccessibilityTraversalAfterId);
+ if (next != null) {
+ info.setTraversalAfter(next);
+ }
+ }
+
info.setVisibleToUser(isVisibleToUser());
info.setPackageName(mContext.getPackageName());
@@ -6030,6 +6084,94 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Sets the id of a view before which this one is visited in accessibility traversal.
+ * A screen-reader must visit the content of this view before the content of the one
+ * it precedes. For example, if view B is set to be before view A, then a screen-reader
+ * will traverse the entire content of B before traversing the entire content of A,
+ * regardles of what traversal strategy it is using.
+ * <p>
+ * Views that do not have specified before/after relationships are traversed in order
+ * determined by the screen-reader.
+ * </p>
+ * <p>
+ * Setting that this view is before a view that is not important for accessibility
+ * or if this view is not important for accessibility will have no effect as the
+ * screen-reader is not aware of unimportant views.
+ * </p>
+ *
+ * @param beforeId The id of a view this one precedes in accessibility traversal.
+ *
+ * @attr ref android.R.styleable#View_accessibilityTraversalBefore
+ *
+ * @see #setImportantForAccessibility(int)
+ */
+ @RemotableViewMethod
+ public void setAccessibilityTraversalBefore(int beforeId) {
+ if (mAccessibilityTraversalBeforeId == beforeId) {
+ return;
+ }
+ mAccessibilityTraversalBeforeId = beforeId;
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+ }
+
+ /**
+ * Gets the id of a view before which this one is visited in accessibility traversal.
+ *
+ * @return The id of a view this one precedes in accessibility traversal if
+ * specified, otherwise {@link #NO_ID}.
+ *
+ * @see #setAccessibilityTraversalBefore(int)
+ */
+ public int getAccessibilityTraversalBefore() {
+ return mAccessibilityTraversalBeforeId;
+ }
+
+ /**
+ * Sets the id of a view after which this one is visited in accessibility traversal.
+ * A screen-reader must visit the content of the other view before the content of this
+ * one. For example, if view B is set to be after view A, then a screen-reader
+ * will traverse the entire content of A before traversing the entire content of B,
+ * regardles of what traversal strategy it is using.
+ * <p>
+ * Views that do not have specified before/after relationships are traversed in order
+ * determined by the screen-reader.
+ * </p>
+ * <p>
+ * Setting that this view is after a view that is not important for accessibility
+ * or if this view is not important for accessibility will have no effect as the
+ * screen-reader is not aware of unimportant views.
+ * </p>
+ *
+ * @param afterId The id of a view this one succedees in accessibility traversal.
+ *
+ * @attr ref android.R.styleable#View_accessibilityTraversalAfter
+ *
+ * @see #setImportantForAccessibility(int)
+ */
+ @RemotableViewMethod
+ public void setAccessibilityTraversalAfter(int afterId) {
+ if (mAccessibilityTraversalAfterId == afterId) {
+ return;
+ }
+ mAccessibilityTraversalAfterId = afterId;
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+ }
+
+ /**
+ * Gets the id of a view after which this one is visited in accessibility traversal.
+ *
+ * @return The id of a view this one succeedes in accessibility traversal if
+ * specified, otherwise {@link #NO_ID}.
+ *
+ * @see #setAccessibilityTraversalAfter(int)
+ */
+ public int getAccessibilityTraversalAfter() {
+ return mAccessibilityTraversalAfterId;
+ }
+
+ /**
* Gets the id of a view for which this view serves as a label for
* accessibility purposes.
*
@@ -6048,11 +6190,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@RemotableViewMethod
public void setLabelFor(int id) {
+ if (mLabelForId == id) {
+ return;
+ }
mLabelForId = id;
if (mLabelForId != View.NO_ID
&& mID == View.NO_ID) {
mID = generateViewId();
}
+ notifyViewAccessibilityStateChangedIfNeeded(
+ AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
/**
@@ -9794,6 +9941,29 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (ai != null) {
ai.mViewScrollChanged = true;
}
+
+ if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
+ mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
+ }
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when the scroll
+ * position of a view changes.
+ *
+ * @hide Only used internally.
+ */
+ public interface OnScrollChangeListener {
+ /**
+ * Called when the scroll position of a view changes.
+ *
+ * @param v The view whose scroll position has changed.
+ * @param scrollX Current horizontal scroll origin.
+ * @param scrollY Current vertical scroll origin.
+ * @param oldScrollX Previous horizontal scroll origin.
+ * @param oldScrollY Previous vertical scroll origin.
+ */
+ void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
}
/**
@@ -14062,7 +14232,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} else {
draw(canvas);
}
- drawAccessibilityFocus(canvas);
}
} finally {
renderNode.end(canvas);
@@ -14357,7 +14526,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} else {
draw(canvas);
}
- drawAccessibilityFocus(canvas);
canvas.restoreToCount(restoreCount);
canvas.setBitmap(null);
@@ -14432,7 +14600,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} else {
draw(canvas);
}
- drawAccessibilityFocus(canvas);
mPrivateFlags = flags;
@@ -15030,13 +15197,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
dispatchDraw(canvas);
- if (mOverlay != null && !mOverlay.isEmpty()) {
- mOverlay.getOverlayView().draw(canvas);
- }
} else {
draw(canvas);
}
- drawAccessibilityFocus(canvas);
} else {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
@@ -15288,50 +15451,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Draws the accessibility focus rect onto the specified canvas.
- *
- * @param canvas Canvas on which to draw the focus rect
- */
- private void drawAccessibilityFocus(Canvas canvas) {
- if (mAttachInfo == null) {
- return;
- }
-
- final Rect bounds = mAttachInfo.mTmpInvalRect;
- final ViewRootImpl viewRoot = getViewRootImpl();
- if (viewRoot == null || viewRoot.getAccessibilityFocusedHost() != this) {
- return;
- }
-
- final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
- if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
- return;
- }
-
- final Drawable drawable = viewRoot.getAccessibilityFocusedDrawable();
- if (drawable == null) {
- return;
- }
-
- final AccessibilityNodeInfo virtualView = viewRoot.getAccessibilityFocusedVirtualView();
- if (virtualView != null) {
- virtualView.getBoundsInScreen(bounds);
- final int[] offset = mAttachInfo.mTmpLocation;
- getLocationOnScreen(offset);
- bounds.offset(-offset[0], -offset[1]);
- } else {
- bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
- }
-
- canvas.save();
- canvas.translate(mScrollX, mScrollY);
- canvas.clipRect(bounds, Region.Op.REPLACE);
- drawable.setBounds(bounds);
- drawable.draw(canvas);
- canvas.restore();
- }
-
- /**
* Draws the background onto the specified canvas.
*
* @param canvas Canvas on which to draw the background
@@ -16353,6 +16472,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (tintInfo.mHasTintMode) {
mBackground.setTintMode(tintInfo.mTintMode);
}
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (mBackground.isStateful()) {
+ mBackground.setState(getDrawableState());
+ }
}
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7c7e3e7c9b2a..654a8edea2fe 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4250,9 +4250,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
clearChildFocus = true;
}
- if (view.isAccessibilityFocused()) {
- view.clearAccessibilityFocus();
- }
+ view.clearAccessibilityFocus();
cancelTouchTarget(view);
cancelHoverTarget(view);
@@ -4345,9 +4343,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
clearChildFocus = true;
}
- if (view.isAccessibilityFocused()) {
- view.clearAccessibilityFocus();
- }
+ view.clearAccessibilityFocus();
cancelTouchTarget(view);
cancelHoverTarget(view);
@@ -4432,9 +4428,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
clearChildFocus = true;
}
- if (view.isAccessibilityFocused()) {
- view.clearAccessibilityFocus();
- }
+ view.clearAccessibilityFocus();
cancelTouchTarget(view);
cancelHoverTarget(view);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 81fc96619128..f0d52528807d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -727,7 +727,10 @@ public final class ViewRootImpl implements ViewParent,
mAttachInfo.mHardwareRenderer.destroy();
}
- final boolean translucent = attrs.format != PixelFormat.OPAQUE;
+ final Rect insets = attrs.surfaceInsets;
+ final boolean hasSurfaceInsets = insets.left == 0 || insets.right == 0
+ || insets.top == 0 || insets.bottom == 0;
+ final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
mAttachInfo.mHardwareRenderer = HardwareRenderer.create(mContext, translucent);
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.setName(attrs.getTitle().toString());
@@ -2255,6 +2258,7 @@ public final class ViewRootImpl implements ViewParent,
canvas.drawHardwareLayer(mResizeBuffer, mHardwareXOffset, mHardwareYOffset,
mResizePaint);
}
+ drawAccessibilityFocusedDrawableIfNeeded(canvas);
}
/**
@@ -2474,18 +2478,38 @@ public final class ViewRootImpl implements ViewParent,
dirty.offset(surfaceInsets.left, surfaceInsets.right);
}
- if (!dirty.isEmpty() || mIsAnimating) {
+ boolean accessibilityFocusDirty = false;
+ final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
+ if (drawable != null) {
+ final Rect bounds = mAttachInfo.mTmpInvalRect;
+ final boolean hasFocus = getAccessibilityFocusedRect(bounds);
+ if (!hasFocus) {
+ bounds.setEmpty();
+ }
+ if (!bounds.equals(drawable.getBounds())) {
+ accessibilityFocusDirty = true;
+ }
+ }
+
+ if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
+ // If accessibility focus moved, always invalidate the root.
+ boolean invalidateRoot = accessibilityFocusDirty;
+
// Draw with hardware renderer.
mIsAnimating = false;
- boolean invalidateRoot = false;
+
if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
mHardwareYOffset = yOffset;
mHardwareXOffset = xOffset;
- mAttachInfo.mHardwareRenderer.invalidateRoot();
+ invalidateRoot = true;
}
mResizeAlpha = resizeAlpha;
+ if (invalidateRoot) {
+ mAttachInfo.mHardwareRenderer.invalidateRoot();
+ }
+
dirty.setEmpty();
mBlockResizeBuffer = false;
@@ -2604,6 +2628,8 @@ public final class ViewRootImpl implements ViewParent,
attachInfo.mSetIgnoreDirtyState = false;
mView.draw(canvas);
+
+ drawAccessibilityFocusedDrawableIfNeeded(canvas);
} finally {
if (!attachInfo.mSetIgnoreDirtyState) {
// Only clear the flag if it was not set during the mView.draw() call
@@ -2627,7 +2653,56 @@ public final class ViewRootImpl implements ViewParent,
return true;
}
- Drawable getAccessibilityFocusedDrawable() {
+ /**
+ * We want to draw a highlight around the current accessibility focused.
+ * Since adding a style for all possible view is not a viable option we
+ * have this specialized drawing method.
+ *
+ * Note: We are doing this here to be able to draw the highlight for
+ * virtual views in addition to real ones.
+ *
+ * @param canvas The canvas on which to draw.
+ */
+ private void drawAccessibilityFocusedDrawableIfNeeded(Canvas canvas) {
+ final Rect bounds = mAttachInfo.mTmpInvalRect;
+ if (getAccessibilityFocusedRect(bounds)) {
+ final Drawable drawable = getAccessibilityFocusedDrawable();
+ if (drawable != null) {
+ drawable.setBounds(bounds);
+ drawable.draw(canvas);
+ }
+ } else if (mAttachInfo.mAccessibilityFocusDrawable != null) {
+ mAttachInfo.mAccessibilityFocusDrawable.setBounds(0, 0, 0, 0);
+ }
+ }
+
+ private boolean getAccessibilityFocusedRect(Rect bounds) {
+ final AccessibilityManager manager = AccessibilityManager.getInstance(mView.mContext);
+ if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
+ return false;
+ }
+
+ final View host = mAccessibilityFocusedHost;
+ if (host == null || host.mAttachInfo == null) {
+ return false;
+ }
+
+ final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
+ if (provider == null) {
+ host.getBoundsOnScreen(bounds);
+ } else if (mAccessibilityFocusedVirtualView != null) {
+ mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds);
+ } else {
+ return false;
+ }
+
+ final AttachInfo attachInfo = mAttachInfo;
+ bounds.offset(-attachInfo.mWindowLeft, -attachInfo.mWindowTop);
+ bounds.intersect(0, 0, attachInfo.mViewRootImpl.mWidth, attachInfo.mViewRootImpl.mHeight);
+ return !bounds.isEmpty();
+ }
+
+ private Drawable getAccessibilityFocusedDrawable() {
// Lazily load the accessibility focus drawable.
if (mAttachInfo.mAccessibilityFocusDrawable == null) {
final TypedValue value = new TypedValue();
@@ -3014,6 +3089,7 @@ public final class ViewRootImpl implements ViewParent,
private final static int MSG_INVALIDATE_WORLD = 23;
private final static int MSG_WINDOW_MOVED = 24;
private final static int MSG_SYNTHESIZE_INPUT_EVENT = 25;
+ private final static int MSG_DISPATCH_WINDOW_SHOWN = 26;
final class ViewRootHandler extends Handler {
@Override
@@ -3063,6 +3139,8 @@ public final class ViewRootImpl implements ViewParent,
return "MSG_WINDOW_MOVED";
case MSG_SYNTHESIZE_INPUT_EVENT:
return "MSG_SYNTHESIZE_INPUT_EVENT";
+ case MSG_DISPATCH_WINDOW_SHOWN:
+ return "MSG_DISPATCH_WINDOW_SHOWN";
}
return super.getMessageName(message);
}
@@ -3291,6 +3369,9 @@ public final class ViewRootImpl implements ViewParent,
invalidateWorld(mView);
}
} break;
+ case MSG_DISPATCH_WINDOW_SHOWN: {
+ handleDispatchWindowShown();
+ }
}
}
}
@@ -5137,6 +5218,10 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ public void handleDispatchWindowShown() {
+ mAttachInfo.mTreeObserver.dispatchOnWindowShown();
+ }
+
public void getLastTouchPoint(Point outLocation) {
outLocation.x = (int) mLastTouchPoint.x;
outLocation.y = (int) mLastTouchPoint.y;
@@ -5997,6 +6082,10 @@ public final class ViewRootImpl implements ViewParent,
mHandler.sendMessage(msg);
}
+ public void dispatchWindowShown() {
+ mHandler.sendEmptyMessage(MSG_DISPATCH_WINDOW_SHOWN);
+ }
+
public void dispatchCloseSystemDialogs(String reason) {
Message msg = Message.obtain();
msg.what = MSG_CLOSE_SYSTEM_DIALOGS;
@@ -6507,6 +6596,14 @@ public final class ViewRootImpl implements ViewParent,
viewAncestor.dispatchDoneAnimating();
}
}
+
+ @Override
+ public void dispatchWindowShown() {
+ final ViewRootImpl viewAncestor = mViewAncestor.get();
+ if (viewAncestor != null) {
+ viewAncestor.dispatchWindowShown();
+ }
+ }
}
public static final class CalledFromWrongThreadException extends AndroidRuntimeException {
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index a9444b44760a..b85fec8a0c08 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -44,10 +44,15 @@ public final class ViewTreeObserver {
private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners;
private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners;
+ private CopyOnWriteArray<OnWindowShownListener> mOnWindowShownListeners;
// These listeners cannot be mutated during dispatch
private ArrayList<OnDrawListener> mOnDrawListeners;
+ /** Remains false until #dispatchOnWindowShown() is called. If a listener registers after
+ * that the listener will be immediately called. */
+ private boolean mWindowShown;
+
private boolean mAlive = true;
/**
@@ -174,6 +179,19 @@ public final class ViewTreeObserver {
}
/**
+ * Interface definition for a callback noting when a system window has been displayed.
+ * This is only used for non-Activity windows. Activity windows can use
+ * Activity.onEnterAnimationComplete() to get the same signal.
+ * @hide
+ */
+ public interface OnWindowShownListener {
+ /**
+ * Callback method to be invoked when a non-activity window is fully shown.
+ */
+ void onWindowShown();
+ }
+
+ /**
* Parameters used with OnComputeInternalInsetsListener.
*
* We are not yet ready to commit to this API and support it, so
@@ -375,6 +393,14 @@ public final class ViewTreeObserver {
}
}
+ if (observer.mOnWindowShownListeners != null) {
+ if (mOnWindowShownListeners != null) {
+ mOnWindowShownListeners.addAll(observer.mOnWindowShownListeners);
+ } else {
+ mOnWindowShownListeners = observer.mOnWindowShownListeners;
+ }
+ }
+
observer.kill();
}
@@ -568,6 +594,45 @@ public final class ViewTreeObserver {
}
/**
+ * Register a callback to be invoked when the view tree window has been shown
+ *
+ * @param listener The callback to add
+ *
+ * @throws IllegalStateException If {@link #isAlive()} returns false
+ * @hide
+ */
+ public void addOnWindowShownListener(OnWindowShownListener listener) {
+ checkIsAlive();
+
+ if (mOnWindowShownListeners == null) {
+ mOnWindowShownListeners = new CopyOnWriteArray<OnWindowShownListener>();
+ }
+
+ mOnWindowShownListeners.add(listener);
+ if (mWindowShown) {
+ listener.onWindowShown();
+ }
+ }
+
+ /**
+ * Remove a previously installed window shown callback
+ *
+ * @param victim The callback to remove
+ *
+ * @throws IllegalStateException If {@link #isAlive()} returns false
+ *
+ * @see #addOnWindowShownListener(OnWindowShownListener)
+ * @hide
+ */
+ public void removeOnWindowShownListener(OnWindowShownListener victim) {
+ checkIsAlive();
+ if (mOnWindowShownListeners == null) {
+ return;
+ }
+ mOnWindowShownListeners.remove(victim);
+ }
+
+ /**
* <p>Register a callback to be invoked when the view tree is about to be drawn.</p>
* <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from
* {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p>
@@ -854,6 +919,27 @@ public final class ViewTreeObserver {
}
/**
+ * Notifies registered listeners that the window is now shown
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ public final void dispatchOnWindowShown() {
+ mWindowShown = true;
+ final CopyOnWriteArray<OnWindowShownListener> listeners = mOnWindowShownListeners;
+ if (listeners != null && listeners.size() > 0) {
+ CopyOnWriteArray.Access<OnWindowShownListener> access = listeners.start();
+ try {
+ int count = access.size();
+ for (int i = 0; i < count; i++) {
+ access.get(i).onWindowShown();
+ }
+ } finally {
+ listeners.end();
+ }
+ }
+ }
+
+ /**
* Notifies registered listeners that the drawing pass is about to start.
*/
public final void dispatchOnDraw() {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 20edeb8da627..0076abff2f09 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1074,17 +1074,36 @@ public abstract class Window {
public abstract void onConfigurationChanged(Configuration newConfig);
/**
+ * Sets the window elevation.
+ *
+ * @param elevation The window elevation.
+ * @see View#setElevation(float)
+ * @see android.R.styleable#Window_windowElevation
+ */
+ public void setElevation(float elevation) {}
+
+ /**
+ * Sets whether window content should be clipped to the outline of the
+ * window background.
+ *
+ * @param clipToOutline Whether window content should be clipped to the
+ * outline of the window background.
+ * @see View#setClipToOutline(boolean)
+ * @see android.R.styleable#Window_windowClipToOutline
+ */
+ public void setClipToOutline(boolean clipToOutline) {}
+
+ /**
* Change the background of this window to a Drawable resource. Setting the
* background to null will make the window be opaque. To make the window
* transparent, you can use an empty drawable (for instance a ColorDrawable
* with the color 0 or the system drawable android:drawable/empty.)
*
- * @param resid The resource identifier of a drawable resource which will be
- * installed as the new background.
+ * @param resId The resource identifier of a drawable resource which will
+ * be installed as the new background.
*/
- public void setBackgroundDrawableResource(int resid)
- {
- setBackgroundDrawable(mContext.getDrawable(resid));
+ public void setBackgroundDrawableResource(int resId) {
+ setBackgroundDrawable(mContext.getDrawable(resId));
}
/**
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 5b48c0d2d433..f4f047e60230 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1324,7 +1324,7 @@ public interface WindowManager extends ViewManager {
*
* @hide
*/
- public Rect surfaceInsets = new Rect();
+ public final Rect surfaceInsets = new Rect();
/**
* The desired bitmap format. May be one of the constants in
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 3987fbc02989..b5afdf78d123 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -547,6 +547,8 @@ public class AccessibilityNodeInfo implements Parcelable {
private long mParentNodeId = ROOT_NODE_ID;
private long mLabelForId = ROOT_NODE_ID;
private long mLabeledById = ROOT_NODE_ID;
+ private long mTraversalBefore = ROOT_NODE_ID;
+ private long mTraversalAfter = ROOT_NODE_ID;
private int mBooleanProperties;
private final Rect mBoundsInParent = new Rect();
@@ -1046,6 +1048,126 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Gets the node before which this one is visited during traversal. A screen-reader
+ * must visit the content of this node before the content of the one it precedes.
+ *
+ * @return The succeeding node if such or <code>null</code>.
+ *
+ * @see #setTraversalBefore(android.view.View)
+ * @see #setTraversalBefore(android.view.View, int)
+ */
+ public AccessibilityNodeInfo getTraversalBefore() {
+ enforceSealed();
+ return getNodeForAccessibilityId(mTraversalBefore);
+ }
+
+ /**
+ * Sets the view before whose node this one should be visited during traversal. A
+ * screen-reader must visit the content of this node before the content of the one
+ * it precedes.
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
+ * This class is made immutable before being delivered to an AccessibilityService.
+ * </p>
+ *
+ * @param view The view providing the preceding node.
+ *
+ * @see #getTraversalBefore()
+ */
+ public void setTraversalBefore(View view) {
+ setTraversalBefore(view, UNDEFINED_ITEM_ID);
+ }
+
+ /**
+ * Sets the node before which this one is visited during traversal. A screen-reader
+ * must visit the content of this node before the content of the one it precedes.
+ * The successor is a virtual descendant of the given <code>root</code>. If
+ * <code>virtualDescendantId</code> equals to {@link View#NO_ID} the root is set
+ * as the successor.
+ * <p>
+ * A virtual descendant is an imaginary View that is reported as a part of the view
+ * hierarchy for accessibility purposes. This enables custom views that draw complex
+ * content to report them selves as a tree of virtual views, thus conveying their
+ * logical structure.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
+ * This class is made immutable before being delivered to an AccessibilityService.
+ * </p>
+ *
+ * @param root The root of the virtual subtree.
+ * @param virtualDescendantId The id of the virtual descendant.
+ */
+ public void setTraversalBefore(View root, int virtualDescendantId) {
+ enforceNotSealed();
+ final int rootAccessibilityViewId = (root != null)
+ ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
+ mTraversalBefore = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
+ }
+
+ /**
+ * Gets the node after which this one is visited in accessibility traversal.
+ * A screen-reader must visit the content of the other node before the content
+ * of this one.
+ *
+ * @return The succeeding node if such or <code>null</code>.
+ *
+ * @see #setTraversalAfter(android.view.View)
+ * @see #setTraversalAfter(android.view.View, int)
+ */
+ public AccessibilityNodeInfo getTraversalAfter() {
+ enforceSealed();
+ return getNodeForAccessibilityId(mTraversalAfter);
+ }
+
+ /**
+ * Sets the view whose node is visited after this one in accessibility traversal.
+ * A screen-reader must visit the content of the other node before the content
+ * of this one.
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
+ * This class is made immutable before being delivered to an AccessibilityService.
+ * </p>
+ *
+ * @param view The previous view.
+ *
+ * @see #getTraversalAfter()
+ */
+ public void setTraversalAfter(View view) {
+ setTraversalAfter(view, UNDEFINED_ITEM_ID);
+ }
+
+ /**
+ * Sets the node after which this one is visited in accessibility traversal.
+ * A screen-reader must visit the content of the other node before the content
+ * of this one. If <code>virtualDescendantId</code> equals to {@link View#NO_ID}
+ * the root is set as the predecessor.
+ * <p>
+ * A virtual descendant is an imaginary View that is reported as a part of the view
+ * hierarchy for accessibility purposes. This enables custom views that draw complex
+ * content to report them selves as a tree of virtual views, thus conveying their
+ * logical structure.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}.
+ * This class is made immutable before being delivered to an AccessibilityService.
+ * </p>
+ *
+ * @param root The root of the virtual subtree.
+ * @param virtualDescendantId The id of the virtual descendant.
+ */
+ public void setTraversalAfter(View root, int virtualDescendantId) {
+ enforceNotSealed();
+ final int rootAccessibilityViewId = (root != null)
+ ? root.getAccessibilityViewId() : UNDEFINED_ITEM_ID;
+ mTraversalAfter = makeNodeId(rootAccessibilityViewId, virtualDescendantId);
+ }
+
+ /**
* Sets the maximum text length, or -1 for no limit.
* <p>
* Typically used to indicate that an editable text field has a limit on
@@ -1229,13 +1351,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getParent() {
enforceSealed();
- if (!canPerformRequestOverConnection(mParentNodeId)) {
- return null;
- }
- AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
- mWindowId, mParentNodeId, false, FLAG_PREFETCH_PREDECESSORS
- | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+ return getNodeForAccessibilityId(mParentNodeId);
}
/**
@@ -2055,13 +2171,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getLabelFor() {
enforceSealed();
- if (!canPerformRequestOverConnection(mLabelForId)) {
- return null;
- }
- AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
- mWindowId, mLabelForId, false, FLAG_PREFETCH_PREDECESSORS
- | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+ return getNodeForAccessibilityId(mLabelForId);
}
/**
@@ -2113,13 +2223,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo getLabeledBy() {
enforceSealed();
- if (!canPerformRequestOverConnection(mLabeledById)) {
- return null;
- }
- AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
- return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
- mWindowId, mLabeledById, false, FLAG_PREFETCH_PREDECESSORS
- | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+ return getNodeForAccessibilityId(mLabeledById);
}
/**
@@ -2453,6 +2557,9 @@ public class AccessibilityNodeInfo implements Parcelable {
parcel.writeLong(mParentNodeId);
parcel.writeLong(mLabelForId);
parcel.writeLong(mLabeledById);
+ parcel.writeLong(mTraversalBefore);
+ parcel.writeLong(mTraversalAfter);
+
parcel.writeInt(mConnectionId);
final LongArray childIds = mChildNodeIds;
@@ -2571,6 +2678,8 @@ public class AccessibilityNodeInfo implements Parcelable {
mParentNodeId = other.mParentNodeId;
mLabelForId = other.mLabelForId;
mLabeledById = other.mLabeledById;
+ mTraversalBefore = other.mTraversalBefore;
+ mTraversalAfter = other.mTraversalAfter;
mWindowId = other.mWindowId;
mConnectionId = other.mConnectionId;
mBoundsInParent.set(other.mBoundsInParent);
@@ -2633,6 +2742,9 @@ public class AccessibilityNodeInfo implements Parcelable {
mParentNodeId = parcel.readLong();
mLabelForId = parcel.readLong();
mLabeledById = parcel.readLong();
+ mTraversalBefore = parcel.readLong();
+ mTraversalAfter = parcel.readLong();
+
mConnectionId = parcel.readInt();
final int childrenSize = parcel.readInt();
@@ -2725,6 +2837,8 @@ public class AccessibilityNodeInfo implements Parcelable {
mParentNodeId = ROOT_NODE_ID;
mLabelForId = ROOT_NODE_ID;
mLabeledById = ROOT_NODE_ID;
+ mTraversalBefore = ROOT_NODE_ID;
+ mTraversalAfter = ROOT_NODE_ID;
mWindowId = UNDEFINED_ITEM_ID;
mConnectionId = UNDEFINED_CONNECTION_ID;
mMaxTextLength = -1;
@@ -2911,6 +3025,8 @@ public class AccessibilityNodeInfo implements Parcelable {
builder.append("; accessibilityViewId: " + getAccessibilityViewId(mSourceNodeId));
builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
builder.append("; mParentNodeId: " + mParentNodeId);
+ builder.append("; traversalBefore: ").append(mTraversalBefore);
+ builder.append("; traversalAfter: ").append(mTraversalAfter);
int granularities = mMovementGranularities;
builder.append("; MovementGranularities: [");
@@ -2963,6 +3079,16 @@ public class AccessibilityNodeInfo implements Parcelable {
return builder.toString();
}
+ private AccessibilityNodeInfo getNodeForAccessibilityId(long accessibilityId) {
+ if (!canPerformRequestOverConnection(accessibilityId)) {
+ return null;
+ }
+ AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
+ return client.findAccessibilityNodeInfoByAccessibilityId(mConnectionId,
+ mWindowId, accessibilityId, false, FLAG_PREFETCH_PREDECESSORS
+ | FLAG_PREFETCH_DESCENDANTS | FLAG_PREFETCH_SIBLINGS);
+ }
+
/**
* A class defining an action that can be performed on an {@link AccessibilityNodeInfo}.
* Each action has a unique id that is mandatory and optional data.
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 4aebaae90b03..6927660d2a12 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2663,7 +2663,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* @return True if the selector should be shown
*/
boolean shouldShowSelector() {
- return (!isInTouchMode()) || (touchModeDrawsInPressedState() && isPressed());
+ return (isFocused() && !isInTouchMode()) || (touchModeDrawsInPressedState() && isPressed());
}
private void drawSelector(Canvas canvas) {
@@ -4910,9 +4910,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (position >= headerViewsCount && position < footerViewsStart) {
// The view will be rebound to new data, clear any
// system-managed transient state.
- if (child.isAccessibilityFocused()) {
- child.clearAccessibilityFocus();
- }
+ child.clearAccessibilityFocus();
mRecycler.addScrapView(child, position);
}
}
@@ -4933,9 +4931,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (position >= headerViewsCount && position < footerViewsStart) {
// The view will be rebound to new data, clear any
// system-managed transient state.
- if (child.isAccessibilityFocused()) {
- child.clearAccessibilityFocus();
- }
+ child.clearAccessibilityFocus();
mRecycler.addScrapView(child, position);
}
}
@@ -6776,9 +6772,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
private void clearAccessibilityFromScrap(View view) {
- if (view.isAccessibilityFocused()) {
- view.clearAccessibilityFocus();
- }
+ view.clearAccessibilityFocus();
view.setAccessibilityDelegate(null);
}
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index b2cfdf7da22f..d39960f6b915 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -267,6 +267,12 @@ public abstract class AbsSeekBar extends ProgressBar {
if (mHasThumbTintMode) {
mThumb.setTintMode(mThumbTintMode);
}
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (mThumb.isStateful()) {
+ mThumb.setState(getDrawableState());
+ }
}
}
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 7198e522f3ae..0a8a01f2dfe9 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -429,7 +429,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
}
final int childCount = getChildCount();
- final int midVertical = (top + bottom) / 2;
+ final int midVertical = (bottom - top) / 2;
final int dividerWidth = getDividerWidth();
int overflowWidth = 0;
int nonOverflowWidth = 0;
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index eb8e8aa66360..69969a940db8 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -267,6 +267,12 @@ public class CheckedTextView extends TextView implements Checkable {
if (mHasCheckMarkTintMode) {
mCheckMarkDrawable.setTintMode(mCheckMarkTintMode);
}
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (mCheckMarkDrawable.isStateful()) {
+ mCheckMarkDrawable.setState(getDrawableState());
+ }
}
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 092e31c5a6b4..447ccc2692a2 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -315,6 +315,12 @@ public abstract class CompoundButton extends Button implements Checkable {
if (mHasButtonTintMode) {
mButtonDrawable.setTintMode(mButtonTintMode);
}
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (mButtonDrawable.isStateful()) {
+ mButtonDrawable.setState(getDrawableState());
+ }
}
}
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index e3175242d19e..d974c29c39eb 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -384,6 +384,12 @@ public class FrameLayout extends ViewGroup {
if (mHasForegroundTintMode) {
mForeground.setTintMode(mForegroundTintMode);
}
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (mForeground.isStateful()) {
+ mForeground.setState(getDrawableState());
+ }
}
}
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 75dfccad3728..c68bfcaa5bc2 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -386,21 +386,21 @@ public class ImageView extends View {
*/
@android.view.RemotableViewMethod
public void setImageResource(int resId) {
- if (mUri != null || mResource != resId) {
- final int oldWidth = mDrawableWidth;
- final int oldHeight = mDrawableHeight;
+ // The resource configuration may have changed, so we should always
+ // try to load the resource even if the resId hasn't changed.
+ final int oldWidth = mDrawableWidth;
+ final int oldHeight = mDrawableHeight;
- updateDrawable(null);
- mResource = resId;
- mUri = null;
+ updateDrawable(null);
+ mResource = resId;
+ mUri = null;
- resolveUri();
+ resolveUri();
- if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
- requestLayout();
- }
- invalidate();
+ if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
+ requestLayout();
}
+ invalidate();
}
/**
@@ -527,6 +527,12 @@ public class ImageView extends View {
if (mHasDrawableTintMode) {
mDrawable.setTintMode(mDrawableTintMode);
}
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (mDrawable.isStateful()) {
+ mDrawable.setState(getDrawableState());
+ }
}
}
@@ -820,6 +826,7 @@ public class ImageView extends View {
mDrawableHeight = d.getIntrinsicHeight();
applyImageTint();
applyColorMod();
+
configureBounds();
} else {
mDrawableWidth = mDrawableHeight = -1;
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index 7b3dd31fd159..a40d4f83a17b 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -904,6 +904,10 @@ public class OverScroller {
final long time = AnimationUtils.currentAnimationTimeMillis();
final long currentTime = time - mStartTime;
+ if (currentTime == 0) {
+ // Skip work but report that we're still going if we have a nonzero duration.
+ return mDuration > 0;
+ }
if (currentTime > mDuration) {
return false;
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 1c190c3da833..887a93b8425f 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -673,6 +673,12 @@ public class ProgressBar extends View {
if (tintInfo.mHasIndeterminateTintMode) {
mIndeterminateDrawable.setTintMode(tintInfo.mIndeterminateTintMode);
}
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (mIndeterminateDrawable.isStateful()) {
+ mIndeterminateDrawable.setState(getDrawableState());
+ }
}
}
}
@@ -781,6 +787,12 @@ public class ProgressBar extends View {
if (mProgressTintInfo.mHasProgressTintMode) {
target.setTintMode(mProgressTintInfo.mProgressTintMode);
}
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (target.isStateful()) {
+ target.setState(getDrawableState());
+ }
}
}
}
@@ -800,6 +812,12 @@ public class ProgressBar extends View {
if (mProgressTintInfo.mHasProgressBackgroundTintMode) {
target.setTintMode(mProgressTintInfo.mProgressBackgroundTintMode);
}
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (target.isStateful()) {
+ target.setState(getDrawableState());
+ }
}
}
}
@@ -819,6 +837,12 @@ public class ProgressBar extends View {
if (mProgressTintInfo.mHasSecondaryProgressTintMode) {
target.setTintMode(mProgressTintInfo.mSecondaryProgressTintMode);
}
+
+ // The drawable (or one of its children) may not have been
+ // stateful before applying the tint, so let's try again.
+ if (target.isStateful()) {
+ target.setState(getDrawableState());
+ }
}
}
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 80f364b25ff8..dd7fa18468c2 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -2528,6 +2528,26 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
+ * Equivalent to calling {@link android.view.View#setAccessibilityTraversalBefore(int)}.
+ *
+ * @param viewId The id of the view whose before view in accessibility traversal to set.
+ * @param nextId The id of the next in the accessibility traversal.
+ **/
+ public void setAccessibilityTraversalBefore(int viewId, int nextId) {
+ setInt(viewId, "setAccessibilityTraversalBefore", nextId);
+ }
+
+ /**
+ * Equivalent to calling {@link android.view.View#setAccessibilityTraversalAfter(int)}.
+ *
+ * @param viewId The id of the view whose after view in accessibility traversal to set.
+ * @param nextId The id of the next in the accessibility traversal.
+ **/
+ public void setAccessibilityTraversalAfter(int viewId, int nextId) {
+ setInt(viewId, "setAccessibilityTraversalAfter", nextId);
+ }
+
+ /**
* Equivalent to calling View.setLabelFor(int).
*
* @param viewId The id of the view whose property to set.
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index d8e39e3788c6..d4d186c94e23 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -104,6 +104,7 @@ public class Toolbar extends ViewGroup {
private ImageView mLogoView;
private Drawable mCollapseIcon;
+ private CharSequence mCollapseDescription;
private ImageButton mCollapseButtonView;
View mExpandedActionView;
@@ -238,6 +239,7 @@ public class Toolbar extends ViewGroup {
}
mCollapseIcon = a.getDrawable(R.styleable.Toolbar_collapseIcon);
+ mCollapseDescription = a.getText(R.styleable.Toolbar_collapseContentDescription);
final CharSequence title = a.getText(R.styleable.Toolbar_title);
if (!TextUtils.isEmpty(title)) {
@@ -998,6 +1000,7 @@ public class Toolbar extends ViewGroup {
if (mCollapseButtonView == null) {
mCollapseButtonView = new ImageButton(getContext(), null, 0, mNavButtonStyle);
mCollapseButtonView.setImageDrawable(mCollapseIcon);
+ mCollapseButtonView.setContentDescription(mCollapseDescription);
final LayoutParams lp = generateDefaultLayoutParams();
lp.gravity = Gravity.START | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
lp.mViewType = LayoutParams.EXPANDED;
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 0183e4511721..35e03c3b7a80 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -26,7 +26,6 @@ import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
@@ -38,9 +37,12 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.ViewParent;
+import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
+import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
@@ -449,11 +451,11 @@ public class AlertController {
}
private void setupView() {
- final LinearLayout contentPanel = (LinearLayout) mWindow.findViewById(R.id.contentPanel);
+ final ViewGroup contentPanel = (ViewGroup) mWindow.findViewById(R.id.contentPanel);
setupContent(contentPanel);
final boolean hasButtons = setupButtons();
- final LinearLayout topPanel = (LinearLayout) mWindow.findViewById(R.id.topPanel);
+ final ViewGroup topPanel = (ViewGroup) mWindow.findViewById(R.id.topPanel);
final TypedArray a = mContext.obtainStyledAttributes(
null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
final boolean hasTitle = setupTitle(topPanel);
@@ -521,13 +523,13 @@ public class AlertController {
a.recycle();
}
- private boolean setupTitle(LinearLayout topPanel) {
+ private boolean setupTitle(ViewGroup topPanel) {
boolean hasTitle = true;
if (mCustomTitleView != null) {
// Add the custom title view directly to the topPanel layout
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
- LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ LayoutParams lp = new LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
topPanel.addView(mCustomTitleView, 0, lp);
@@ -571,7 +573,7 @@ public class AlertController {
return hasTitle;
}
- private void setupContent(LinearLayout contentPanel) {
+ private void setupContent(ViewGroup contentPanel) {
mScrollView = (ScrollView) mWindow.findViewById(R.id.scrollView);
mScrollView.setFocusable(false);
@@ -588,14 +590,77 @@ public class AlertController {
mScrollView.removeView(mMessageView);
if (mListView != null) {
- contentPanel.removeView(mWindow.findViewById(R.id.scrollView));
- contentPanel.addView(mListView,
- new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
- contentPanel.setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, 0, 1.0f));
+ final ViewGroup scrollParent = (ViewGroup) mScrollView.getParent();
+ final int childIndex = scrollParent.indexOfChild(mScrollView);
+ scrollParent.removeViewAt(childIndex);
+ scrollParent.addView(mListView, childIndex,
+ new LayoutParams(MATCH_PARENT, MATCH_PARENT));
} else {
contentPanel.setVisibility(View.GONE);
}
}
+
+ // Set up scroll indicators (if present).
+ final View indicatorUp = mWindow.findViewById(R.id.scrollIndicatorUp);
+ final View indicatorDown = mWindow.findViewById(R.id.scrollIndicatorDown);
+ if (indicatorUp != null || indicatorDown != null) {
+ if (mMessage != null) {
+ // We're just showing the ScrollView, set up listener.
+ mScrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
+ @Override
+ public void onScrollChange(View v, int scrollX, int scrollY,
+ int oldScrollX, int oldScrollY) {
+ manageScrollIndicators(v, indicatorUp, indicatorDown);
+ }
+ });
+ // Set up the indicators following layout.
+ mScrollView.post(new Runnable() {
+ @Override
+ public void run() {
+ manageScrollIndicators(mScrollView, indicatorUp, indicatorDown);
+ }
+ });
+
+ } else if (mListView != null) {
+ // We're just showing the AbsListView, set up listener.
+ mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ // That's cool, I guess?
+ }
+
+ @Override
+ public void onScroll(AbsListView v, int firstVisibleItem,
+ int visibleItemCount, int totalItemCount) {
+ manageScrollIndicators(v, indicatorUp, indicatorDown);
+ }
+ });
+ // Set up the indicators following layout.
+ mListView.post(new Runnable() {
+ @Override
+ public void run() {
+ manageScrollIndicators(mListView, indicatorUp, indicatorDown);
+ }
+ });
+ } else {
+ // We don't have any content to scroll, remove the indicators.
+ if (indicatorUp != null) {
+ contentPanel.removeView(indicatorUp);
+ }
+ if (indicatorDown != null) {
+ contentPanel.removeView(indicatorDown);
+ }
+ }
+ }
+ }
+
+ private static void manageScrollIndicators(View v, View upIndicator, View downIndicator) {
+ if (upIndicator != null) {
+ upIndicator.setVisibility(v.canScrollVertically(-1) ? View.VISIBLE : View.INVISIBLE);
+ }
+ if (downIndicator != null) {
+ downIndicator.setVisibility(v.canScrollVertically(1) ? View.VISIBLE : View.INVISIBLE);
+ }
}
private boolean setupButtons() {
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ccffa1985dbc..7df76e533e74 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -278,9 +278,9 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
final ResolverDrawerLayout rdl = (ResolverDrawerLayout) findViewById(R.id.contentPanel);
if (rdl != null) {
- rdl.setOnClickOutsideListener(new View.OnClickListener() {
+ rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() {
@Override
- public void onClick(View v) {
+ public void onDismissed() {
finish();
}
});
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index 4410f2544624..34b9dcb9366f 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -40,7 +40,6 @@ import com.android.internal.widget.ToolbarWidgetWrapper;
import java.util.ArrayList;
public class ToolbarActionBar extends ActionBar {
- private Toolbar mToolbar;
private DecorToolbar mDecorToolbar;
private boolean mToolbarMenuPrepared;
private Window.Callback mWindowCallback;
@@ -66,7 +65,6 @@ public class ToolbarActionBar extends ActionBar {
};
public ToolbarActionBar(Toolbar toolbar, CharSequence title, Window.Callback windowCallback) {
- mToolbar = toolbar;
mDecorToolbar = new ToolbarWidgetWrapper(toolbar, false);
mWindowCallback = new ToolbarCallbackWrapper(windowCallback);
mDecorToolbar.setWindowCallback(mWindowCallback);
@@ -91,8 +89,8 @@ public class ToolbarActionBar extends ActionBar {
@Override
public void setCustomView(int resId) {
- final LayoutInflater inflater = LayoutInflater.from(mToolbar.getContext());
- setCustomView(inflater.inflate(resId, mToolbar, false));
+ final LayoutInflater inflater = LayoutInflater.from(mDecorToolbar.getContext());
+ setCustomView(inflater.inflate(resId, mDecorToolbar.getViewGroup(), false));
}
@Override
@@ -132,17 +130,17 @@ public class ToolbarActionBar extends ActionBar {
@Override
public void setElevation(float elevation) {
- mToolbar.setElevation(elevation);
+ mDecorToolbar.getViewGroup().setElevation(elevation);
}
@Override
public float getElevation() {
- return mToolbar.getElevation();
+ return mDecorToolbar.getViewGroup().getElevation();
}
@Override
public Context getThemedContext() {
- return mToolbar.getContext();
+ return mDecorToolbar.getContext();
}
@Override
@@ -152,12 +150,12 @@ public class ToolbarActionBar extends ActionBar {
@Override
public void setHomeAsUpIndicator(Drawable indicator) {
- mToolbar.setNavigationIcon(indicator);
+ mDecorToolbar.setNavigationIcon(indicator);
}
@Override
public void setHomeAsUpIndicator(int resId) {
- mToolbar.setNavigationIcon(resId);
+ mDecorToolbar.setNavigationIcon(resId);
}
@Override
@@ -280,7 +278,7 @@ public class ToolbarActionBar extends ActionBar {
@Override
public void setBackgroundDrawable(@Nullable Drawable d) {
- mToolbar.setBackground(d);
+ mDecorToolbar.setBackgroundDrawable(d);
}
@Override
@@ -290,12 +288,12 @@ public class ToolbarActionBar extends ActionBar {
@Override
public CharSequence getTitle() {
- return mToolbar.getTitle();
+ return mDecorToolbar.getTitle();
}
@Override
public CharSequence getSubtitle() {
- return mToolbar.getSubtitle();
+ return mDecorToolbar.getSubtitle();
}
@Override
@@ -389,44 +387,44 @@ public class ToolbarActionBar extends ActionBar {
@Override
public int getHeight() {
- return mToolbar.getHeight();
+ return mDecorToolbar.getHeight();
}
@Override
public void show() {
// TODO: Consider a better transition for this.
// Right now use no automatic transition so that the app can supply one if desired.
- mToolbar.setVisibility(View.VISIBLE);
+ mDecorToolbar.setVisibility(View.VISIBLE);
}
@Override
public void hide() {
// TODO: Consider a better transition for this.
// Right now use no automatic transition so that the app can supply one if desired.
- mToolbar.setVisibility(View.GONE);
+ mDecorToolbar.setVisibility(View.GONE);
}
@Override
public boolean isShowing() {
- return mToolbar.getVisibility() == View.VISIBLE;
+ return mDecorToolbar.getVisibility() == View.VISIBLE;
}
@Override
public boolean openOptionsMenu() {
- return mToolbar.showOverflowMenu();
+ return mDecorToolbar.showOverflowMenu();
}
@Override
public boolean invalidateOptionsMenu() {
- mToolbar.removeCallbacks(mMenuInvalidator);
- mToolbar.postOnAnimation(mMenuInvalidator);
+ mDecorToolbar.getViewGroup().removeCallbacks(mMenuInvalidator);
+ mDecorToolbar.getViewGroup().postOnAnimation(mMenuInvalidator);
return true;
}
@Override
public boolean collapseActionView() {
- if (mToolbar.hasExpandedActionView()) {
- mToolbar.collapseActionView();
+ if (mDecorToolbar.hasExpandedActionView()) {
+ mDecorToolbar.collapseActionView();
return true;
}
return false;
@@ -434,10 +432,10 @@ public class ToolbarActionBar extends ActionBar {
void populateOptionsMenu() {
if (!mMenuCallbackSet) {
- mToolbar.setMenuCallbacks(new ActionMenuPresenterCallback(), new MenuBuilderCallback());
+ mDecorToolbar.setMenuCallbacks(new ActionMenuPresenterCallback(), new MenuBuilderCallback());
mMenuCallbackSet = true;
}
- final Menu menu = mToolbar.getMenu();
+ final Menu menu = mDecorToolbar.getMenu();
final MenuBuilder mb = menu instanceof MenuBuilder ? (MenuBuilder) menu : null;
if (mb != null) {
mb.stopDispatchingItemsChanged();
@@ -518,7 +516,7 @@ public class ToolbarActionBar extends ActionBar {
}
mClosingActionMenu = true;
- mToolbar.dismissPopupMenus();
+ mDecorToolbar.dismissPopupMenus();
if (mWindowCallback != null) {
mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu);
}
@@ -536,7 +534,7 @@ public class ToolbarActionBar extends ActionBar {
@Override
public void onMenuModeChange(MenuBuilder menu) {
if (mWindowCallback != null) {
- if (mToolbar.isOverflowMenuShowing()) {
+ if (mDecorToolbar.isOverflowMenuShowing()) {
mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu);
} else if (mWindowCallback.onPreparePanel(Window.FEATURE_OPTIONS_PANEL,
null, menu)) {
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index 785b30386175..d95f0e591e0e 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -876,7 +876,7 @@ public class WindowDecorActionBar extends ActionBar implements
currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme,
outValue, true);
final int targetThemeRes = outValue.resourceId;
-
+
if (targetThemeRes != 0 && mContext.getThemeResId() != targetThemeRes) {
mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes);
} else {
@@ -885,7 +885,7 @@ public class WindowDecorActionBar extends ActionBar implements
}
return mThemedContext;
}
-
+
@Override
public boolean isTitleTruncated() {
return mDecorToolbar != null && mDecorToolbar.isTitleTruncated();
@@ -933,14 +933,17 @@ public class WindowDecorActionBar extends ActionBar implements
}
/**
- * @hide
+ * @hide
*/
public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback {
+ private final Context mActionModeContext;
+ private final MenuBuilder mMenu;
+
private ActionMode.Callback mCallback;
- private MenuBuilder mMenu;
private WeakReference<View> mCustomView;
-
+
public ActionModeImpl(Context context, ActionMode.Callback callback) {
+ mActionModeContext = context;
mCallback = callback;
mMenu = new MenuBuilder(context)
.setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
@@ -949,7 +952,7 @@ public class WindowDecorActionBar extends ActionBar implements
@Override
public MenuInflater getMenuInflater() {
- return new MenuInflater(getThemedContext());
+ return new MenuInflater(mActionModeContext);
}
@Override
@@ -1042,7 +1045,7 @@ public class WindowDecorActionBar extends ActionBar implements
public CharSequence getSubtitle() {
return mContextView.getSubtitle();
}
-
+
@Override
public void setTitleOptionalHint(boolean titleOptional) {
super.setTitleOptionalHint(titleOptional);
diff --git a/core/java/com/android/internal/util/MemInfoReader.java b/core/java/com/android/internal/util/MemInfoReader.java
index 1dd946494d4d..b71fa0674b4e 100644
--- a/core/java/com/android/internal/util/MemInfoReader.java
+++ b/core/java/com/android/internal/util/MemInfoReader.java
@@ -106,4 +106,8 @@ public final class MemInfoReader {
public long getZramTotalSizeKb() {
return mInfos[Debug.MEMINFO_ZRAM_TOTAL];
}
+
+ public long[] getRawInfo() {
+ return mInfos;
+ }
}
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 50a7a5e17be1..993ab58c6e44 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -102,4 +102,8 @@ public class BaseIWindow extends IWindow.Stub {
@Override
public void doneAnimating() {
}
+
+ @Override
+ public void dispatchWindowShown() {
+ }
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index b9a85e59eb96..654d08b40763 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -1341,6 +1341,22 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
updateHomeAccessibility(mUpGoerFive.isEnabled());
}
+ @Override
+ public void setMenuCallbacks(MenuPresenter.Callback presenterCallback,
+ MenuBuilder.Callback menuBuilderCallback) {
+ if (mActionMenuPresenter != null) {
+ mActionMenuPresenter.setCallback(presenterCallback);
+ }
+ if (mOptionsMenu != null) {
+ mOptionsMenu.setCallback(menuBuilderCallback);
+ }
+ }
+
+ @Override
+ public Menu getMenu() {
+ return mOptionsMenu;
+ }
+
static class SavedState extends BaseSavedState {
int expandedMenuItemId;
boolean isOverflowOpen;
diff --git a/core/java/com/android/internal/widget/DecorToolbar.java b/core/java/com/android/internal/widget/DecorToolbar.java
index f89f0b7d6ef7..fb413b573d2e 100644
--- a/core/java/com/android/internal/widget/DecorToolbar.java
+++ b/core/java/com/android/internal/widget/DecorToolbar.java
@@ -27,6 +27,8 @@ import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.SpinnerAdapter;
+
+import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuPresenter;
/**
@@ -93,4 +95,11 @@ public interface DecorToolbar {
void setDefaultNavigationIcon(Drawable icon);
void saveHierarchyState(SparseArray<Parcelable> toolbarStates);
void restoreHierarchyState(SparseArray<Parcelable> toolbarStates);
+ void setBackgroundDrawable(Drawable d);
+ int getHeight();
+ void setVisibility(int visible);
+ int getVisibility();
+ void setMenuCallbacks(MenuPresenter.Callback presenterCallback,
+ MenuBuilder.Callback menuBuilderCallback);
+ Menu getMenu();
}
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 375822fa184a..25b494528a98 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -63,18 +63,22 @@ public class ResolverDrawerLayout extends ViewGroup {
private float mCollapseOffset;
private int mCollapsibleHeight;
+ private int mUncollapsibleHeight;
private int mTopOffset;
private boolean mIsDragging;
private boolean mOpenOnClick;
private boolean mOpenOnLayout;
+ private boolean mDismissOnScrollerFinished;
private final int mTouchSlop;
private final float mMinFlingVelocity;
private final OverScroller mScroller;
private final VelocityTracker mVelocityTracker;
- private OnClickListener mClickOutsideListener;
+ private OnDismissedListener mOnDismissedListener;
+ private RunOnDismissedListener mRunOnDismissedListener;
+
private float mInitialTouchX;
private float mInitialTouchY;
private float mLastTouchY;
@@ -143,8 +147,8 @@ public class ResolverDrawerLayout extends ViewGroup {
return isSmallCollapsed() ? mMaxCollapsedHeightSmall : mMaxCollapsedHeight;
}
- public void setOnClickOutsideListener(OnClickListener listener) {
- mClickOutsideListener = listener;
+ public void setOnDismissedListener(OnDismissedListener listener) {
+ mOnDismissedListener = listener;
}
@Override
@@ -194,7 +198,7 @@ public class ResolverDrawerLayout extends ViewGroup {
}
if (mIsDragging) {
- mScroller.abortAnimation();
+ abortAnimation();
}
return mIsDragging || mOpenOnClick;
}
@@ -213,12 +217,9 @@ public class ResolverDrawerLayout extends ViewGroup {
mInitialTouchX = x;
mInitialTouchY = mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
- if (findChildUnder(mInitialTouchX, mInitialTouchY) == null &&
- mClickOutsideListener != null) {
- mIsDragging = handled = true;
- }
- handled |= mCollapsibleHeight > 0;
- mScroller.abortAnimation();
+ mIsDragging = findChildUnder(mInitialTouchX, mInitialTouchY) != null;
+ handled = (!mIsDragging && mOnDismissedListener != null) || mCollapsibleHeight > 0;
+ abortAnimation();
}
break;
@@ -264,11 +265,12 @@ public class ResolverDrawerLayout extends ViewGroup {
break;
case MotionEvent.ACTION_UP: {
+ final boolean wasDragging = mIsDragging;
mIsDragging = false;
- if (!mIsDragging && findChildUnder(mInitialTouchX, mInitialTouchY) == null &&
+ if (!wasDragging && findChildUnder(mInitialTouchX, mInitialTouchY) == null &&
findChildUnder(ev.getX(), ev.getY()) == null) {
- if (mClickOutsideListener != null) {
- mClickOutsideListener.onClick(this);
+ if (mOnDismissedListener != null) {
+ dispatchOnDismissed();
resetTouch();
return true;
}
@@ -281,7 +283,13 @@ public class ResolverDrawerLayout extends ViewGroup {
mVelocityTracker.computeCurrentVelocity(1000);
final float yvel = mVelocityTracker.getYVelocity(mActivePointerId);
if (Math.abs(yvel) > mMinFlingVelocity) {
- smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel);
+ if (mOnDismissedListener != null
+ && yvel > 0 && mCollapseOffset > mCollapsibleHeight) {
+ smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, yvel);
+ mDismissOnScrollerFinished = true;
+ } else {
+ smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel);
+ }
} else {
smoothScrollTo(
mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0);
@@ -327,17 +335,27 @@ public class ResolverDrawerLayout extends ViewGroup {
@Override
public void computeScroll() {
super.computeScroll();
- if (!mScroller.isFinished()) {
- final boolean keepGoing = mScroller.computeScrollOffset();
+ if (mScroller.computeScrollOffset()) {
+ final boolean keepGoing = !mScroller.isFinished();
performDrag(mScroller.getCurrY() - mCollapseOffset);
if (keepGoing) {
postInvalidateOnAnimation();
+ } else if (mDismissOnScrollerFinished && mOnDismissedListener != null) {
+ mRunOnDismissedListener = new RunOnDismissedListener();
+ post(mRunOnDismissedListener);
}
}
}
+ private void abortAnimation() {
+ mScroller.abortAnimation();
+ mRunOnDismissedListener = null;
+ mDismissOnScrollerFinished = false;
+ }
+
private float performDrag(float dy) {
- final float newPos = Math.max(0, Math.min(mCollapseOffset + dy, mCollapsibleHeight));
+ final float newPos = Math.max(0, Math.min(mCollapseOffset + dy,
+ mCollapsibleHeight + mUncollapsibleHeight));
if (newPos != mCollapseOffset) {
dy = newPos - mCollapseOffset;
final int childCount = getChildCount();
@@ -356,11 +374,18 @@ public class ResolverDrawerLayout extends ViewGroup {
return 0;
}
- private void smoothScrollTo(int yOffset, float velocity) {
- if (getMaxCollapsedHeight() == 0) {
- return;
+ void dispatchOnDismissed() {
+ if (mOnDismissedListener != null) {
+ mOnDismissedListener.onDismissed();
}
- mScroller.abortAnimation();
+ if (mRunOnDismissedListener != null) {
+ removeCallbacks(mRunOnDismissedListener);
+ mRunOnDismissedListener = null;
+ }
+ }
+
+ private void smoothScrollTo(int yOffset, float velocity) {
+ abortAnimation();
final int sy = (int) mCollapseOffset;
int dy = yOffset - sy;
if (dy == 0) {
@@ -490,6 +515,7 @@ public class ResolverDrawerLayout extends ViewGroup {
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getViewTreeObserver().removeOnTouchModeChangeListener(mTouchModeChangeListener);
+ abortAnimation();
}
@Override
@@ -585,6 +611,7 @@ public class ResolverDrawerLayout extends ViewGroup {
mCollapsibleHeight = Math.max(0,
heightUsed - alwaysShowHeight - getMaxCollapsedHeight());
+ mUncollapsibleHeight = heightUsed - mCollapsibleHeight;
if (isLaidOut()) {
mCollapseOffset = Math.min(mCollapseOffset, mCollapsibleHeight);
@@ -734,4 +761,15 @@ public class ResolverDrawerLayout extends ViewGroup {
}
};
}
+
+ public interface OnDismissedListener {
+ public void onDismissed();
+ }
+
+ private class RunOnDismissedListener implements Runnable {
+ @Override
+ public void run() {
+ dispatchOnDismissed();
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
index 324a6c998683..054ca30c71f4 100644
--- a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
+++ b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
@@ -657,4 +657,36 @@ public class ToolbarWidgetWrapper implements DecorToolbar {
mToolbar.restoreHierarchyState(toolbarStates);
}
+ @Override
+ public void setBackgroundDrawable(Drawable d) {
+ //noinspection deprecation
+ mToolbar.setBackgroundDrawable(d);
+ }
+
+ @Override
+ public int getHeight() {
+ return mToolbar.getHeight();
+ }
+
+ @Override
+ public void setVisibility(int visible) {
+ mToolbar.setVisibility(visible);
+ }
+
+ @Override
+ public int getVisibility() {
+ return mToolbar.getVisibility();
+ }
+
+ @Override
+ public void setMenuCallbacks(MenuPresenter.Callback presenterCallback,
+ MenuBuilder.Callback menuBuilderCallback) {
+ mToolbar.setMenuCallbacks(presenterCallback, menuBuilderCallback);
+ }
+
+ @Override
+ public Menu getMenu() {
+ return mToolbar.getMenu();
+ }
+
}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 4159792c9864..4d178779e32d 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -929,8 +929,8 @@ jstring AndroidRuntime::NewStringLatin1(JNIEnv* env, const char* bytes) {
*/
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{
- ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
- className != NULL ? className : "(unknown)");
+ ALOGD(">>>>>> START %s uid %d <<<<<<\n",
+ className != NULL ? className : "(unknown)", getuid());
static const String8 startSystemServer("start-system-server");
diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp
index 5f60c9e3bfc8..ed6f1d69fc18 100644
--- a/core/jni/android/graphics/pdf/PdfEditor.cpp
+++ b/core/jni/android/graphics/pdf/PdfEditor.cpp
@@ -19,6 +19,9 @@
#include "fpdfview.h"
#include "fpdfedit.h"
#include "fpdfsave.h"
+#include "fsdk_rendercontext.h"
+#include "fpdf_transformpage.h"
+#include "SkMatrix.h"
#include <android_runtime/AndroidRuntime.h>
#include <vector>
@@ -29,6 +32,20 @@
namespace android {
+enum PageBox {PAGE_BOX_MEDIA, PAGE_BOX_CROP};
+
+static struct {
+ jfieldID x;
+ jfieldID y;
+} gPointClassInfo;
+
+static struct {
+ jfieldID left;
+ jfieldID top;
+ jfieldID right;
+ jfieldID bottom;
+} gRectClassInfo;
+
static Mutex sLock;
static int sUnmatchedInitRequestCount = 0;
@@ -72,8 +89,17 @@ static jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) {
if (!document) {
const long error = FPDF_GetLastError();
- jniThrowException(env, "java/io/IOException",
- "cannot create document. Error:" + error);
+ switch (error) {
+ case FPDF_ERR_PASSWORD:
+ case FPDF_ERR_SECURITY: {
+ jniThrowException(env, "java/lang/SecurityException",
+ "cannot create document. Error:" + error);
+ } break;
+ default: {
+ jniThrowException(env, "java/io/IOException",
+ "cannot create document. Error:" + error);
+ } break;
+ }
destroyLibraryIfNeeded();
return -1;
}
@@ -144,18 +170,201 @@ static void nativeWrite(JNIEnv* env, jclass thiz, jlong documentPtr, jint fd) {
}
}
+static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex,
+ jlong transformPtr, jint clipLeft, jint clipTop, jint clipRight, jint clipBottom) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+
+ CPDF_Page* page = (CPDF_Page*) FPDF_LoadPage(document, pageIndex);
+ if (!page) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "cannot open page");
+ return;
+ }
+
+ double width = 0;
+ double height = 0;
+
+ const int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height);
+ if (!result) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "cannot get page size");
+ return;
+ }
+
+ CFX_AffineMatrix matrix;
+
+ SkMatrix* skTransform = reinterpret_cast<SkMatrix*>(transformPtr);
+
+ SkScalar transformValues[6];
+ skTransform->asAffine(transformValues);
+
+ // PDF's coordinate system origin is left-bottom while in graphics it
+ // is the top-left. So, translate the PDF coordinates to ours.
+ matrix.Set(1, 0, 0, -1, 0, page->GetPageHeight());
+
+ // Apply the transformation what was created in our coordinates.
+ matrix.Concat(transformValues[SkMatrix::kAScaleX], transformValues[SkMatrix::kASkewY],
+ transformValues[SkMatrix::kASkewX], transformValues[SkMatrix::kAScaleY],
+ transformValues[SkMatrix::kATransX], transformValues[SkMatrix::kATransY]);
+
+ // Translate the result back to PDF coordinates.
+ matrix.Concat(1, 0, 0, -1, 0, page->GetPageHeight());
+
+ FS_MATRIX transform = {matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f};
+ FS_RECTF clip = {(float) clipLeft, (float) clipTop, (float) clipRight, (float) clipBottom};
+
+ FPDFPage_TransFormWithClip(page, &transform, &clip);
+
+ FPDF_ClosePage(page);
+}
+
+static void nativeGetPageSize(JNIEnv* env, jclass thiz, jlong documentPtr,
+ jint pageIndex, jobject outSize) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+
+ FPDF_PAGE page = FPDF_LoadPage(document, pageIndex);
+ if (!page) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "cannot open page");
+ return;
+ }
+
+ double width = 0;
+ double height = 0;
+
+ const int result = FPDF_GetPageSizeByIndex(document, pageIndex, &width, &height);
+ if (!result) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "cannot get page size");
+ return;
+ }
+
+ env->SetIntField(outSize, gPointClassInfo.x, width);
+ env->SetIntField(outSize, gPointClassInfo.y, height);
+
+ FPDF_ClosePage(page);
+}
+
+static jboolean nativeScaleForPrinting(JNIEnv* env, jclass thiz, jlong documentPtr) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+ FPDF_BOOL success = FPDF_VIEWERREF_GetPrintScaling(document);
+ return success ? JNI_TRUE : JNI_FALSE;
+}
+
+static bool nativeGetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex,
+ PageBox pageBox, jobject outBox) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+
+ FPDF_PAGE page = FPDF_LoadPage(document, pageIndex);
+ if (!page) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "cannot open page");
+ return false;
+ }
+
+ float left;
+ float top;
+ float right;
+ float bottom;
+
+ const FPDF_BOOL success = (pageBox == PAGE_BOX_MEDIA)
+ ? FPDFPage_GetMediaBox(page, &left, &top, &right, &bottom)
+ : FPDFPage_GetCropBox(page, &left, &top, &right, &bottom);
+
+ FPDF_ClosePage(page);
+
+ if (!success) {
+ return false;
+ }
+
+ env->SetIntField(outBox, gRectClassInfo.left, (int) left);
+ env->SetIntField(outBox, gRectClassInfo.top, (int) top);
+ env->SetIntField(outBox, gRectClassInfo.right, (int) right);
+ env->SetIntField(outBox, gRectClassInfo.bottom, (int) bottom);
+
+ return true;
+}
+
+static jboolean nativeGetPageMediaBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex,
+ jobject outMediaBox) {
+ const bool success = nativeGetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_MEDIA,
+ outMediaBox);
+ return success ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean nativeGetPageCropBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex,
+ jobject outMediaBox) {
+ const bool success = nativeGetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_CROP,
+ outMediaBox);
+ return success ? JNI_TRUE : JNI_FALSE;
+}
+
+static void nativeSetPageBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex,
+ PageBox pageBox, jobject box) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+
+ FPDF_PAGE page = FPDF_LoadPage(document, pageIndex);
+ if (!page) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "cannot open page");
+ return;
+ }
+
+ const int left = env->GetIntField(box, gRectClassInfo.left);
+ const int top = env->GetIntField(box, gRectClassInfo.top);
+ const int right = env->GetIntField(box, gRectClassInfo.right);
+ const int bottom = env->GetIntField(box, gRectClassInfo.bottom);
+
+ if (pageBox == PAGE_BOX_MEDIA) {
+ FPDFPage_SetMediaBox(page, left, top, right, bottom);
+ } else {
+ FPDFPage_SetCropBox(page, left, top, right, bottom);
+ }
+
+ FPDF_ClosePage(page);
+}
+
+static void nativeSetPageMediaBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex,
+ jobject mediaBox) {
+ nativeSetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_MEDIA, mediaBox);
+}
+
+static void nativeSetPageCropBox(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex,
+ jobject mediaBox) {
+ nativeSetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_CROP, mediaBox);
+}
+
static JNINativeMethod gPdfEditor_Methods[] = {
{"nativeOpen", "(IJ)J", (void*) nativeOpen},
{"nativeClose", "(J)V", (void*) nativeClose},
{"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount},
{"nativeRemovePage", "(JI)I", (void*) nativeRemovePage},
- {"nativeWrite", "(JI)V", (void*) nativeWrite}
+ {"nativeWrite", "(JI)V", (void*) nativeWrite},
+ {"nativeSetTransformAndClip", "(JIJIIII)V", (void*) nativeSetTransformAndClip},
+ {"nativeGetPageSize", "(JILandroid/graphics/Point;)V", (void*) nativeGetPageSize},
+ {"nativeScaleForPrinting", "(J)Z", (void*) nativeScaleForPrinting},
+ {"nativeGetPageMediaBox", "(JILandroid/graphics/Rect;)Z", (void*) nativeGetPageMediaBox},
+ {"nativeSetPageMediaBox", "(JILandroid/graphics/Rect;)V", (void*) nativeSetPageMediaBox},
+ {"nativeGetPageCropBox", "(JILandroid/graphics/Rect;)Z", (void*) nativeGetPageCropBox},
+ {"nativeSetPageCropBox", "(JILandroid/graphics/Rect;)V", (void*) nativeSetPageCropBox}
};
int register_android_graphics_pdf_PdfEditor(JNIEnv* env) {
- return android::AndroidRuntime::registerNativeMethods(
+ const int result = android::AndroidRuntime::registerNativeMethods(
env, "android/graphics/pdf/PdfEditor", gPdfEditor_Methods,
NELEM(gPdfEditor_Methods));
+
+ jclass pointClass = env->FindClass("android/graphics/Point");
+ gPointClassInfo.x = env->GetFieldID(pointClass, "x", "I");
+ gPointClassInfo.y = env->GetFieldID(pointClass, "y", "I");
+
+ jclass rectClass = env->FindClass("android/graphics/Rect");
+ gRectClassInfo.left = env->GetFieldID(rectClass, "left", "I");
+ gRectClassInfo.top = env->GetFieldID(rectClass, "top", "I");
+ gRectClassInfo.right = env->GetFieldID(rectClass, "right", "I");
+ gRectClassInfo.bottom = env->GetFieldID(rectClass, "bottom", "I");
+
+ return result;
};
};
diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp
index 303ddea9d1ab..357d3c00ae84 100644
--- a/core/jni/android/graphics/pdf/PdfRenderer.cpp
+++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp
@@ -82,8 +82,17 @@ static jlong nativeCreate(JNIEnv* env, jclass thiz, jint fd, jlong size) {
if (!document) {
const long error = FPDF_GetLastError();
- jniThrowException(env, "java/io/IOException",
- "cannot create document. Error:" + error);
+ switch (error) {
+ case FPDF_ERR_PASSWORD:
+ case FPDF_ERR_SECURITY: {
+ jniThrowException(env, "java/lang/SecurityException",
+ "cannot create document. Error:" + error);
+ } break;
+ default: {
+ jniThrowException(env, "java/io/IOException",
+ "cannot create document. Error:" + error);
+ } break;
+ }
destroyLibraryIfNeeded();
return -1;
}
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index 7b33bc28d24e..2a8e6d6b5b3d 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -265,19 +265,22 @@ void JNISoundTriggerCallback::onRecognitionEvent(struct sound_trigger_recognitio
event->capture_session, event->capture_delay_ms,
event->capture_preamble_ms, event->trigger_in_data,
jAudioFormat, jData, jExtras);
- env->DeleteLocalRef(jAudioFormat);
- env->DeleteLocalRef(jData);
+ env->DeleteLocalRef(jExtras);
} else {
jEvent = env->NewObject(gRecognitionEventClass, gRecognitionEventCstor,
event->status, event->model, event->capture_available,
event->capture_session, event->capture_delay_ms,
event->capture_preamble_ms, event->trigger_in_data,
jAudioFormat, jData);
+ }
+
+ if (jAudioFormat != NULL) {
env->DeleteLocalRef(jAudioFormat);
+ }
+ if (jData != NULL) {
env->DeleteLocalRef(jData);
}
-
env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
SOUNDTRIGGER_EVENT_RECOGNITION, 0, 0, jEvent);
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 33bb90bcdb70..f09928979be4 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -390,7 +390,7 @@ android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute
return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
}
-static jfloat
+static jboolean
android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
{
bool mute;
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 4859ee6fb796..94098c91880c 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1095,7 +1095,7 @@ static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject c
// coming from, first XML attributes, then XML style, then default
// style, and finally the theme.
value.dataType = Res_value::TYPE_NULL;
- value.data = 0;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
typeSetFlags = 0;
config.density = 0;
@@ -1157,6 +1157,7 @@ static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject c
if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
DEBUG_STYLES(ALOGI("-> Setting to @null!"));
value.dataType = Res_value::TYPE_NULL;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
block = -1;
}
@@ -1319,7 +1320,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
// coming from, first XML attributes, then XML style, then default
// style, and finally the theme.
value.dataType = Res_value::TYPE_NULL;
- value.data = 0;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
typeSetFlags = 0;
config.density = 0;
@@ -1403,6 +1404,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
DEBUG_STYLES(ALOGI("-> Setting to @null!"));
value.dataType = Res_value::TYPE_NULL;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
block = kXmlBlock;
}
@@ -1512,7 +1514,7 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
// Try to find a value for this attribute...
value.dataType = Res_value::TYPE_NULL;
- value.data = 0;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
typeSetFlags = 0;
config.density = 0;
@@ -1548,6 +1550,7 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
// Deal with the special @null value -- it turns back to TYPE_NULL.
if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
value.dataType = Res_value::TYPE_NULL;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
}
//printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
@@ -1661,6 +1664,7 @@ static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject claz
// Deal with the special @null value -- it turns back to TYPE_NULL.
if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
value.dataType = Res_value::TYPE_NULL;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
}
//printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 2e2b23f25d3d..9bdc6b5c99c9 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -43,6 +43,7 @@
#include <RenderNode.h>
#include <CanvasProperty.h>
#include <Paint.h>
+#include <renderthread/RenderProxy.h>
#include "MinikinUtils.h"
@@ -861,7 +862,7 @@ static void
android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
#ifdef USE_OPENGL_RENDERER
int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
- android::uirenderer::RenderNode::outputLogBuffer(fd);
+ android::uirenderer::renderthread::RenderProxy::outputLogBuffer(fd);
#endif // USE_OPENGL_RENDERER
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 7ca9374631ae..4f5e08b6efa2 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -452,14 +452,23 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
DropCapabilitiesBoundingSet(env);
- bool need_native_bridge = false;
- if (instructionSet != NULL) {
+ bool use_native_bridge = !is_system_server && (instructionSet != NULL)
+ && android::NativeBridgeAvailable();
+ if (use_native_bridge) {
ScopedUtfChars isa_string(env, instructionSet);
- need_native_bridge = android::NeedsNativeBridge(isa_string.c_str());
+ use_native_bridge = android::NeedsNativeBridge(isa_string.c_str());
+ }
+ if (use_native_bridge && dataDir == NULL) {
+ // dataDir should never be null if we need to use a native bridge.
+ // In general, dataDir will never be null for normal applications. It can only happen in
+ // special cases (for isolated processes which are not associated with any app). These are
+ // launched by the framework and should not be emulated anyway.
+ use_native_bridge = false;
+ ALOGW("Native bridge will not be used because dataDir == NULL.");
}
- if (!MountEmulatedStorage(uid, mount_external, need_native_bridge)) {
- ALOGW("Failed to mount emulated storage: %d", errno);
+ if (!MountEmulatedStorage(uid, mount_external, use_native_bridge)) {
+ ALOGW("Failed to mount emulated storage: %s", strerror(errno));
if (errno == ENOTCONN || errno == EROFS) {
// When device is actively encrypting, we get ENOTCONN here
// since FUSE was mounted before the framework restarted.
@@ -487,15 +496,10 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
SetRLimits(env, javaRlimits);
- if (!is_system_server && need_native_bridge) {
- // Set the environment for the apps running with native bridge.
- ScopedUtfChars isa_string(env, instructionSet); // Known non-null because of need_native_...
- if (dataDir == NULL) {
- android::PreInitializeNativeBridge(NULL, isa_string.c_str());
- } else {
- ScopedUtfChars data_dir(env, dataDir);
- android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str());
- }
+ if (use_native_bridge) {
+ ScopedUtfChars isa_string(env, instructionSet);
+ ScopedUtfChars data_dir(env, dataDir);
+ android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str());
}
int rc = setresgid(gid, gid, gid);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8e0cd5266090..6f2a06bb05b6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1269,13 +1269,24 @@
android:description="@string/permdesc_use_sip"
android:label="@string/permlab_use_sip" />
- <!-- Protects the ability to register any PhoneAccount with a capability flags of either
- PhoneAccount#CAPABILITY_CALL_PROVIDER or PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. -->
- <permission android:name="android.permission.REGISTER_PROVIDER_OR_SUBSCRIPTION"
+ <!-- Protects the ability to register any PhoneAccount with
+ PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
+ corresponds to a device SIM. -->
+ <permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION"
android:permissionGroup="android.permission-group.PHONE_CALLS"
- android:description="@string/permdesc_register_provider"
- android:label="@string/permlab_register_provider" />
+ android:protectionLevel="system|signature"
+ android:description="@string/permdesc_register_sim_subscription"
+ android:label="@string/permlab_register_sim_subscription" />
+
+ <!-- Protects the ability to register any PhoneAccount with
+ PhoneAccount#CAPABILITY_CALL_PROVIDER. -->
+ <permission android:name="android.permission.REGISTER_CALL_PROVIDER"
+ android:permissionGroup="android.permission-group.PHONE_CALLS"
+ android:description="@string/permdesc_register_call_provider"
+ android:label="@string/permlab_register_call_provider" />
+ <!-- Protects the ability to register any PhoneAccount with
+ PhoneAccount#CAPABILITY_CONNECTION_MANAGER -->
<permission android:name="android.permission.REGISTER_CONNECTION_MANAGER"
android:permissionGroup="android.permission-group.PHONE_CALLS"
android:description="@string/permdesc_connection_manager"
diff --git a/core/res/res/drawable/view_accessibility_focused.xml b/core/res/res/drawable/view_accessibility_focused.xml
index 68e3f1ecb97f..025916b35f40 100644
--- a/core/res/res/drawable/view_accessibility_focused.xml
+++ b/core/res/res/drawable/view_accessibility_focused.xml
@@ -18,9 +18,7 @@
<stroke
android:width="4dp"
- android:color="@color/accessibility_focus_highlight"
- android:dashWidth="4dp"
- android:dashGap="2dp" />
+ android:color="@color/accessibility_focus_highlight" />
<corners android:radius="2dp" />
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index c96182853a16..5627a2c9c0a3 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -51,12 +51,17 @@
<!-- If the client uses a customTitle, it will be added here. -->
</LinearLayout>
- <LinearLayout android:id="@+id/contentPanel"
+ <FrameLayout android:id="@+id/contentPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:orientation="vertical"
android:minHeight="48dp">
+ <View android:id="@+id/scrollIndicatorUp"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_gravity="top"
+ android:background="@drawable/list_divider_material"/>
<ScrollView android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -78,7 +83,13 @@
android:layout_height="@dimen/alert_dialog_padding_top_material" />
</LinearLayout>
</ScrollView>
- </LinearLayout>
+ <View android:id="@+id/scrollIndicatorDown"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_gravity="bottom"
+ android:background="@drawable/list_divider_material"/>
+ </FrameLayout>
<FrameLayout android:id="@+id/customPanel"
android:layout_width="match_parent"
@@ -99,7 +110,8 @@
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="8dp"
- android:paddingBottom="8dp">
+ android:paddingBottom="8dp"
+ android:gravity="bottom">
<Button android:id="@+id/button3"
style="?attr/buttonBarNeutralButtonStyle"
android:layout_width="wrap_content"
diff --git a/core/res/res/layout/select_dialog_item_material.xml b/core/res/res/layout/select_dialog_item_material.xml
index fe326f35554a..b45edc6218ec 100644
--- a/core/res/res/layout/select_dialog_item_material.xml
+++ b/core/res/res/layout/select_dialog_item_material.xml
@@ -28,6 +28,6 @@
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textColor="?android:attr/textColorAlertDialogListItem"
android:gravity="center_vertical"
- android:paddingStart="@dimen/alert_dialog_padding_material"
- android:paddingEnd="@dimen/alert_dialog_padding_material"
+ android:paddingStart="?attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?attr/listPreferredItemPaddingEnd"
android:ellipsize="marquee" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index a0c93b9398f1..ec4bd5027b3e 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Laat die program toe om die kaslêerstelsel te lees en skryf."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"maak en/of ontvang SIP-oproepe"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Laat die program toe om SIP-oproepe te maak en te ontvang."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registreer nuwe telekom-verbinding"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Laat die program toe om nuwe telekom-verbindings te registreer."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"bestuur telekom-verbindings"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Laat die program toe om telekom-verbindings te bestuur."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"beleef interaksie met inoproep-skerm"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Laat die program beheer wanneer en hoe die gebruiker die inoproep-skerm sien."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"werk met telefoniedienste saam"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vra wagwoord voordat jy ontspeld"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Om batteryleeftyd te help verbeter, verminder batterybespaarder jou toestel se werkverrigting en beperk vibrasie en die meeste agtergronddata. E-pos, boodskappe en ander programme wat op sinkronisering staatmaak, sal dalk nie opdateer nie tensy jy hulle oopmaak.\n\nBatterybespaarder skakel outomaties af wanneer jou toestel laai."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Totdat jou ontspantyd om <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> eindig"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Een minuut lank"</item>
<item quantity="other" msgid="6924190729213550991">"%d minute lank"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Een uur lank"</item>
<item quantity="other" msgid="5408537517529822157">"%d uur lank"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Onbepaalde tyd"</string>
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 16d4c380e8ac..2ba358dfb784 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"መሸጎጫ ስርዓተ ፋይል ለማንበብ እና ለመፃፍ ለመተግበሪያው ይፈቅዳሉ።"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"የSIP ጥሪዎችን ያድርጉ/ይቀበሉ"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"መተግበሪያው የSIP ጥሪዎችን እንዲያደር እና እንዲቀበል ያስችላል።"</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"አዲስ የቴሌኮም ግንኙነት ይመዘግባል"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"መተግበሪያው አዲስ የቴሌክኮም ግንኙነቶችን እንዲመዘግብ ያስችለዋል"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"የቴሌኮም ግንኙነቶችን ያቀናብራል"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"መተግበሪያው የቴሌኮም ግንኙነቶችን እንዲያቀናብር ያስችለዋል።"</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"ከውስጠ-ጥሪ ማያ ገጽ ጋር መስተጋብር ይፈጥራል"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"መተግበሪያው ተጠቃሚው በጥሪ ውስጥ ያለውን ማያ ገጽ መቼ እና እንዴት ማየት እንደሚችል እንዲቆጣጠር ይፈቅድለታል።"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"ከስልክ አገልግሎቶች ጋር መስተጋብር ይፈጥራል"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ከመንቀል በፊት የይለፍ ቃል ጠይቅ"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"የባትሪ ህይወትን ለማሻሻል ሲባል ባትሪ ቆጣቢ የመሣሪያዎ የስራ አፈጻጸምን እና ንዝረትንና አብዛኛውን የጀርባ ውሂብ ይቀንሳል። ኢሜይል፣ መልዕክት መላላኪያ እና ሌሎች በማመሳሰል ላይ የሚወሰኑ መተግበሪያዎች እስኪከፍቷቸው ድረስ ላይዘምኑ ይችላሉ።\n\nመሣሪያዎ ባትሪ እየሞላ ሲሆን ባትሪ ቆጣቢ በራስ-ሰር ይጠፋል።"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"የጥገና ጊዜዎ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ላይ እስኪያበቃ ድረስ"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ለአንድ ደቂቃ"</item>
<item quantity="other" msgid="6924190729213550991">"ለ%d ደቂቃዎች"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"ለአንድ ሰዓት"</item>
<item quantity="other" msgid="5408537517529822157">"ለ%d ሰዓቶች"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"ያለገደብ"</string>
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 891c9404a5b4..d1320d86d545 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"للسماح للتطبيق بقراءة نظام ملفات ذاكرة التخزين المؤقت والكتابة به."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"‏إجراء/تلقي مكالمات SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"‏للسماح للتطبيق بإجراء مكالمات SIP وتلقيها."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"تسجيل الاتصال اللاسلكي الجديد"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"للسماح للتطبيق بتسجيل الاتصالات اللاسلكية الجديدة."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"إدارة الاتصالات اللاسلكية"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"للسماح للتطبيق بإدارة الاتصالات اللاسلكية."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"التفاعل مع الشاشة أثناء الاتصال"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"للسماح للتطبيق بالتحكم في وقت وكيفية مشاهدة المستخدم للشاشة أثناء الاتصال."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"التفاعل مع الخدمات الهاتفية"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"المطالبة بكلمة المرور قبل إزالة التثبيت"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"للمساعدة في تحسين مدة تشغيل البطارية، يقلل وضع توفير طاقة البطارية أداء جهازك ويقلل من الاهتزاز ومعظم بيانات الخلفية. وقد لا يتم تحديث البريد الإلكتروني والمراسلة والتطبيقات الأخرى التي تعتمد على المزامنة ما لم تفتحها.\n\nيتم إيقاف وضع توفير طاقة البطارية تلقائيًا عندما يكون الجهاز قيد الشحن."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"إلى أن ينتهي وقت التوقف عن العمل في <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"لمدة دقيقة واحدة"</item>
<item quantity="other" msgid="6924190729213550991">"‏لمدة %d من الدقائق"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"لمدة ساعة واحدة"</item>
<item quantity="other" msgid="5408537517529822157">"‏لمدة %d من الساعات"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"إلى أجل غير مسمى"</string>
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 7671cb1018df..e202127d35a4 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Разрешава на приложението да чете и записва във файловата система на кеша."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"извършване/получаване на обаждания чрез SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Разрешава на приложението да извършва и получава обаждания чрез SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"регистриране на новите телекомуникационни връзки"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Разрешава на приложението да регистрира новите телекомуникационни връзки."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"управление на телекомуникационните връзки"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Разрешава на приложението да управлява телекомуникационните връзки."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"взаимодействие с екрана за обаждане"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Разрешава на приложението да контролира кога и как потребителят вижда екрана за обаждане."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"взаимодействие с телефонни услуги"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитване за парола преди освобождаване"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"С цел удължаване на живота на батерията режимът за запазването й намалява ефективността на устройството ви и ограничава вибрирането и повечето данни на заден план. Имейл, Съобщения и другите приложения, които разчитат на синхронизиране, може да не се актуализират, освен ако не ги отворите.\n\nТози режим автоматично се изключва, когато устройството ви се зарежда."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"До приключване на неактивността в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"За една минута"</item>
<item quantity="other" msgid="6924190729213550991">"За %d минути"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"За един час"</item>
<item quantity="other" msgid="5408537517529822157">"За %d часа"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"За неопределено време"</string>
</resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 401bd7f4cd73..43a758d26312 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ক্যাশে ফাইল সিস্টেম পড়তে ও লিখতে অ্যাপ্লিকেশানকে অনুমতি দেয়৷"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP কল করুন/গ্রহণ করুন"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"অ্যাপ্লিকেশানকে SIP কল করতে ও গ্রহণ করতে অনুমতি দেয়।"</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"নতুন টেলিকম সংযোগ নিবন্ধিত করুন"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"নতুন টেলিকম সংযোগ নিবন্ধিত করতে অ্যাপ্লিকেশানটিকে অনুমোদিত করে৷"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"টেলিকম সংযোগগুলি পরিচালনা করুন"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"টেলিকম সংযোগগুলি পরিচালনা করতে  অ্যাপ্লিকেশানটিকে অনুমোদিত করে৷"</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"কলে-থাকা স্ক্রীণের সাথে ইন্টারঅ্যাক্ট করে"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ব্যবহারকারী কখন এবং কীভাবে কলে-থাকা স্ক্রীণটিকে দেখতে পাবেন, অ্যাপ্লিকেশানটিকে তা নিয়ন্ত্রণ করতে দেয়৷"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"টেলিফোন পরিষেবার সাথে ইন্টারঅ্যাক্ট করুন"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"আনপিন করার আগে পাসওয়ার্ড চান"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"ব্যাটারির আয়ু বাড়াতে সহায়তার জন্য, ব্যাটারি সঞ্চয়কারী আপনার ডিভাইসের কার্য-সম্পাদনা কমিয়ে আনবে এবং কম্পন ও পশ্চাদভূমি ডেটাকে সীমিত করবে। ইমেল, বার্তাপ্রেরণ ও অন্যান্য অ্যাপ্লিকেশান, যেগুলি সিঙ্ক হওয়ার উপর নির্ভরশীল সেগুলিকে আপনি না খোলা পর্যন্ত সেগুলি আপডেট নাও হতে পারে।\n\nআপনার ডিভাইস চার্জ হওয়ার সময় ব্যাটারি সঞ্চয়কারী স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যাবে।"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>টার সময়ে আপনার ডাউনটাইম শেষ হওয়া পর্যন্ত"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"এক মিনিটের জন্য"</item>
<item quantity="other" msgid="6924190729213550991">"%d মিনিটের জন্য"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"এক ঘন্টার জন্য"</item>
<item quantity="other" msgid="5408537517529822157">"%d ঘন্টার জন্য"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"অনির্দিষ্টভাবে"</string>
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index ef5103f553d2..5aeb5d9bb9bb 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permet que l\'aplicació llegeixi el sistema de fitxers de la memòria cau i que hi escrigui."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"Fer i rebre trucades de SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Permet que l\'aplicació pugui fer i rebre trucades de SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registrar connexions de telecomunicacions noves"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Permet que l\'aplicació registri connexions de telecomunicacions noves."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"gestionar les connexions de telecomunicacions"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permet que l\'aplicació gestioni les connexions de telecomunicacions."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interaccionar amb la pantalla de la trucada"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permet que l\'aplicació controli quan i com l\'usuari veu la pantalla de la trucada."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interacciona amb els serveis de telefonia"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demana la contrasenya abans d\'anul·lar la fixació"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Per tal d\'augmentar la durada de la bateria, la funció d\'estalvi de bateria redueix el rendiment del dispositiu i en limita la vibració i la majoria de dades en segon pla. És possible que el correu electrònic, la missatgeria i la resta d\'aplicacions que se sincronitzen amb freqüència no s\'actualitzin llevat que les obris.\n\nL\'estalvi de bateria es desactiva automàticament mentre el dispositiu s\'està carregant."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Fins que no finalitzi la inactivitat a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>."</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Durant un minut"</item>
<item quantity="other" msgid="6924190729213550991">"Durant %d minuts"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Durant una hora"</item>
<item quantity="other" msgid="5408537517529822157">"Durant %d hores"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidament"</string>
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 771222fea1f1..ffb80dac46a5 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Umožňuje aplikaci číst a zapisovat do souborového systému mezipaměti."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"uskutečňování/příjem volání SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Povolí aplikaci uskutečňovat a přijímat volání SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registrace nového telekomunikačního připojení"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Umožňuje aplikaci registrovat nová telekomunikační připojení."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"správa telekomunikačních připojení"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Umožňuje aplikaci spravovat telekomunikační připojení."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakce s obrazovkou příchozího hovoru"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Umožňuje aplikaci řídit, kdy a jak se uživateli zobrazí obrazovka příchozího hovoru."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"komunikace s telefonními službami"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Před uvolněním požádat o heslo"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Za účelem zvýšení životnosti baterie spořič baterie sníží výkon vašeho zařízení a omezí vibrace a většinu dat na pozadí. E-mail, zprávy a další aplikace, které používají synchronizaci, nemusejí být aktualizovány, dokud je nespustíte.\n\nPři nabíjení zařízení se spořič baterie automaticky vypne."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Dokud v <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> neskončí pozastavení"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Na jednu minutu"</item>
<item quantity="other" msgid="6924190729213550991">"Na %d min"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Na 1 h"</item>
<item quantity="other" msgid="5408537517529822157">"Na %d h"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Na dobu neurčitou"</string>
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 1543eeeff99e..0a81979b61c4 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Tillader, at appen kan læse og skrive i cachefilsystemet."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"foretage/modtage SIP-opkald"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Tillader, at appen foretager og modtager SIP-opkald."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registrere nye telefonforbindelser"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Tillader, at appen registrerer nye telefonforbindelser."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"administrere telefonforbindelser"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Tillader, at appen administrerer telefonforbindelser."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interager med skærmen under opkald"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Tillader, at appen styrer, hvornår og hvordan brugeren ser skærmen for indgående opkald."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagere med telefonitjenester"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bed om adgangskode inden frigørelse"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"For at forbedre batteriets levetid reducerer batterisparefunktionen enhedens ydeevne og begrænser vibrationer og de fleste baggrundsdata. E-mail, beskeder og andre apps, der benytter synkronisering, opdateres ikke, medmindre du åbner dem.\n\nBatterisparefunktionen deaktiveres automatisk, når enheden oplades."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Indtil din nedetid slutter kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"I ét minut"</item>
<item quantity="other" msgid="6924190729213550991">"I %d minutter"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"I én time"</item>
<item quantity="other" msgid="5408537517529822157">"I %d timer"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Uendeligt"</string>
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 6aad2893903c..74bd5f93fa02 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ermöglicht der App Lese- und Schreibzugriff auf das Cache-Dateisystem"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP-Anrufe tätigen/empfangen"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Ermöglicht der App das Tätigen und Empfangen von SIP-Anrufen"</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"Neue Telekommunikationsverbindungen registrieren"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Gestattet der App die Registrierung neuer Telekommunikationsverbindungen"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"Telekommunikationsverbindungen verwalten"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Gestattet der App die Verwaltung der Telekommunikationsverbindungen"</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"Mit Anrufbildschirm interagieren"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Die App kann steuern, wann und wie der Nutzer den Anrufbildschirm sieht."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"Mit Telefondiensten interagieren"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vor dem Beenden nach Passwort fragen"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Der Energiesparmodus hilft, den Akku zu schonen, indem er die Leistung des Geräts reduziert und die Vibrationsfunktion und die meisten Hintergrunddatenaktivitäten einschränkt. E-Mail-, SMS/MMS- und andere Apps, die die Synchronisierungsfunktion benötigen, werden möglicherweise nicht aktualisiert, bis Sie sie öffnen.\n\nDer Energiesparmodus endet automatisch, wenn Ihr Gerät aufgeladen wird."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Bis zum Ende der Downtime um <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Für eine Minute"</item>
<item quantity="other" msgid="6924190729213550991">"Für %d Minuten"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Für eine Stunde"</item>
<item quantity="other" msgid="5408537517529822157">"Für %d Stunden"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Unbegrenzt"</string>
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index c86d4a328093..edffefc5ff6a 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Επιτρέπει στην εφαρμογή την ανάγνωση και την εγγραφή του συστήματος αρχείων προσωρινής μνήμης."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"πραγματοποίηση/λήψη κλήσεων SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Επιτρέπει στην εφαρμογή να πραγματοποιεί και να λαμβάνει κλήσεις SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"εγγραφή νέας σύνδεσης τηλεπικοινωνιών"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Επιτρέπει στην εφαρμογή να εγγράφει νέες συνδέσεις τηλεπικοινωνιών."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"διαχείριση των συνδέσεων τηλεπικοινωνιών"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Επιτρέπει στην εφαρμογή να διαχειρίζεται τις συνδέσεις τηλεπικοινωνιών."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"αλληλεπίδραση με την οθόνη κατά τη διάρκεια κλήσης"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Επιτρέπει στην εφαρμογή να ελέγχει πότε και πώς βλέπει ο χρήστης την οθόνη κατά τη διάρκεια κλήσης."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"αλληλεπίδραση με υπηρεσίες τηλεφωνίας"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Να γίνεται ερώτηση για τον κωδικό πρόσβασης, πριν από το ξεκαρφίτσωμα"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Για τη βελτίωση της διάρκειας ζωής της μπαταρίας, η λειτουργία εξοικονόμησης μπαταρίας μειώνει την απόδοση της συσκευής σας και περιορίζει τη δόνηση και την πλειονότητα των δεδομένων παρασκηνίου. Το ηλεκτρονικό ταχυδρομείου, η ανταλλαγή μηνυμάτων και άλλες εφαρμογές που βασίζονται στο συγχρονισμό ενδέχεται να μην ενημερώνονται, παρά μόνο εάν τις ανοίξετε.\n\nΗ λειτουργία εξοικονόμησης μπαταρίας απενεργοποιείται αυτόματα κατά τη φόρτιση της συσκευής σας."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Έως τη λήξη του νεκρού χρόνου σας στις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Για ένα λεπτό"</item>
<item quantity="other" msgid="6924190729213550991">"Για %d λεπτά"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Για μία ώρα"</item>
<item quantity="other" msgid="5408537517529822157">"Για %d ώρες"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Επ\' αόριστον"</string>
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index fa1d952b8618..e3569034302c 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Allows the app to read and write the cache file system."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"make/receive SIP calls"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Allows the app to make and receive SIP calls."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"register new telecom connection"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Allows the app to register new telecom connections."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"manage telecom connections"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Allows the app to manage telecom connections."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interact with in-call screen"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Allows the app to control when and how the user sees the in-call screen."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interact with telephony services"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"To help improve battery life, battery saver reduces your device’s performance and limits vibration and most background data. Email, messaging and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Until your downtime ends at <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"For one minute"</item>
<item quantity="other" msgid="6924190729213550991">"For %d minutes"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"For one hour"</item>
<item quantity="other" msgid="5408537517529822157">"For %d hours"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinitely"</string>
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index fa1d952b8618..e3569034302c 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Allows the app to read and write the cache file system."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"make/receive SIP calls"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Allows the app to make and receive SIP calls."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"register new telecom connection"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Allows the app to register new telecom connections."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"manage telecom connections"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Allows the app to manage telecom connections."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interact with in-call screen"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Allows the app to control when and how the user sees the in-call screen."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interact with telephony services"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ask for password before unpinning"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"To help improve battery life, battery saver reduces your device’s performance and limits vibration and most background data. Email, messaging and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Until your downtime ends at <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"For one minute"</item>
<item quantity="other" msgid="6924190729213550991">"For %d minutes"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"For one hour"</item>
<item quantity="other" msgid="5408537517529822157">"For %d hours"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinitely"</string>
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 9e0d284f6c54..816436b2aea7 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite que la aplicación lea y escriba el sistema de archivos almacenado en caché."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"realizar/recibir llamadas SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que la aplicación realice y reciba llamadas SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registrar conexiones de telecomunicaciones nuevas"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Permite que la aplicación registre las conexiones de telecomunicaciones nuevas."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"administrar conexiones de telecomunicaciones"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que la aplicación administre las conexiones de telecomunicaciones."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interactuar con la pantalla de llamada"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite que la aplicación controle cuándo y cómo el usuario ve la pantalla de llamada."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interaccionar con servicios de telefonía"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para quitar fijación"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Para ayudar a mejorar la duración de la batería, la función de ahorro de batería reduce el rendimiento del dispositivo y limita la vibración y la mayor parte de la transmisión de datos en segundo plano. Es posible que las aplicaciones que se sincronizan, como las de correo electrónico y mensajería, no se actualicen a menos que las abras.\n\nEl ahorro de batería se desactiva automáticamente cuando el dispositivo se está cargando."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Hasta que termine el tiempo de inactividad a la(s) <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Durante una hora"</item>
<item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 26fa2996efd4..10c8716661a5 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite que la aplicación lea y escriba el sistema de archivos almacenado en caché."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"hacer/recibir llamadas SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que la aplicación haga y reciba llamadas SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registrar conexiones de telecomunicaciones nuevas"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Permite que la aplicación registre conexiones de telecomunicaciones nuevas."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"administrar conexiones de telecomunicaciones"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que la aplicación administre las conexiones de telecomunicaciones."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interactuar con la pantalla de llamada"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite que la aplicación controle cómo y cuándo aparece la pantalla de llamada."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interactuar con servicios de telefonía"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar contraseña para desactivar"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Para ayudar a mejorar la duración de la batería, la función de ahorro de energía reduce el rendimiento del dispositivo y limita la vibración y la mayor parte de la transmisión de datos en segundo plano. Es posible que las aplicaciones que se sincronizan, como las de correo y mensajes, no se actualicen a menos que las abras.\n\nLa función de ahorro de energía se desactiva automáticamente cuando el dispositivo se carga."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Hasta que el tiempo de inactividad finalice el <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Durante 1 hora"</item>
<item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
</resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 31346a64578c..379aef5bd143 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Võimaldab rakendusel vahemälu failisüsteemi lugeda ja kirjutada."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP-kõnede tegemine/vastuvõtmine"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Lubab rakendusel teha ja vastu võtta SIP-kõnesid."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"uute telekommunikatsiooni ühenduste registreerimine"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Lubab rakendusel registreerida uusi telekommunikatsiooni ühendusi."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"telekommunikatsiooni ühenduste haldamine"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Lubab rakendusel hallata telekommunikatsiooni ühendusi."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"ekraani Kõne pooleli kasutamine"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Lubab rakendusel juhtida, millal ja kuidas kasutajale kuvatakse ekraan Kõne pooleli."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"telefoniteenustega suhtlemine"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Enne vabastamist küsi parooli"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Aku kestuse parandamiseks vähendab akusäästja teie seadme jõudlust ja piirab vibratsiooni ning suuremat osa taustaandmetest. E-posti, sõnumsidet ja muid sünkroonimisele tuginevaid rakendusi võidakse värskendada ainult siis, kui te need avate.\n\nAkusäästja lülitatakse seadme laadimise ajal automaatselt välja."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Kuni seisakuaja lõppemiseni kell <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Üheks minutiks"</item>
<item quantity="other" msgid="6924190729213550991">"%d minutiks"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Üheks tunniks"</item>
<item quantity="other" msgid="5408537517529822157">"%d tunniks"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Määramata ajaks"</string>
</resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index a05e9c616573..c19b209fcc37 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -494,7 +494,7 @@
<string name="permlab_writeProfile" msgid="907793628777397643">"zeure kontaktu-txartela aldatzea"</string>
<string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Gailuan gordetako profil pertsonalaren informazioa aldatzeko baimena ematen dio; esaterako, zure izena eta harremanetan jartzeko informazioa. Horrek esan nahi du aplikazioak identifikatu egin zaitzakeela eta zure profil-informazioa besteei bidal diezaiekeela."</string>
<string name="permlab_bodySensors" msgid="4871091374767171066">"Gorputzaren sentsoreak (adibidez, bihotz-erritmoaren monitoreak)"</string>
- <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Zure egoera fisikoa kontrolatzen duten sentsoreetako datuak (adibidez, maiztasun kardiakoa) atzitzea baimentzen die aplikazioei."</string>
+ <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Zure egoera fisikoa kontrolatzen duten sentsoreetako datuak (adibidez, bihotz-maiztasuna) atzitzea baimentzen die aplikazioei."</string>
<string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"irakurri sare sozialetako korronteak"</string>
<string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Zure eta zure lagunen sare sozialetako eguneratzeak atzitzeko baimena ematen die aplikazioei. Kontuz partekatu informazioa; baimen honekin aplikazioak zure eta zure lagunen arteko sare sozialetako komunikazioak irakur ditzake, isilpekotasuna kontuan izan gabe. Oharra: baliteke baimen hori sare sozial guztiek ez aplikatzea."</string>
<string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"idatzi sare sozialetako korronteetan"</string>
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Cachearen fitxategi-sistema irakurtzea eta bertan idaztea baimentzen die aplikazioei."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"Egin/Jaso SIP deiak"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP deiak egitea eta jasotzea baimentzen die aplikazioei."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"erregistratu telekomunikabideekiko konexioak"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Telekomunikabideekiko konexioak erregistratzea baimentzen die aplikazioei."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"kudeatu telekomunikabideekiko konexioak"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Telekomunikabideekiko konexioak kudeatzea baimentzen die aplikazioei."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"Deiak abian direnean pantaila erabiltzea"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Erabiltzaileak deiaren pantaila noiz eta nola ikusten duen kontrolatzea baimentzen die aplikazioei."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"Elkarreragin telefono-zerbitzuekin"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Eskatu pasahitza aingura kendu aurretik"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Bateriak gehiago iraun dezan, bateria aurrezteko aukerak gailuaren errendimendua murrizten du, eta dardara eta atzeko planoko datu gehienak mugatzen ditu. Baliteke posta elektronikoa, mezuak eta sinkronizatzen diren beste aplikazio batzuk ez eguneratzea, ireki ezean.\n\nBateria aurrezteko aukera automatikoki desaktibatzen da gailua kargatzen ari denean."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> arte iraungo du jarduerarik gabeko aldiak"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Minutu batez"</item>
<item quantity="other" msgid="6924190729213550991">"%d minutuz"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Ordubetez"</item>
<item quantity="other" msgid="5408537517529822157">"%d orduz"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Mugagabea"</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 615d1e41efc5..543171661d1e 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"‏به برنامه اجازه می‎دهد تا سیستم فایل حافظهٔ پنهان را بخواند و بنویسد."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"‏تماس گرفتن/دریافت تماس از طریق SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"‏به برنامه اجازه می‌دهد تماس‌های SIP بگیرد یا دریافت کند."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"ثبت ارتباط مخابراتی جدید"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"به برنامه امکان می‌دهد ارتباط مخابراتی جدید ثبت کند."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"مدیریت ارتباطات مخابراتی"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"به برنامه امکان می‌دهد ارتباطات مخابراتی را مدیریت کند."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"تعامل با صفحه‌نمایش هنگام تماس"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"به برنامه امکان می‌دهد کنترل کند که کاربر چه زمانی و چگونه صفحه‌نمایش هنگام تماس را مشاهده کند."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"تعامل با سرویس‌های تلفنی"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"درخواست گذرواژه قبل از برداشتن پین"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"برای کمک به بهبود عمر باتری، ذخیره‌کننده باتری عملکرد دستگاه‌تان را کاهش می‌دهد و اغلب اطلاعات پس‌زمینه و لرزش را محدود می‌کند. ایمیل، پیام‌رسانی و سایر برنامه‌هایی که به همگام‌سازی وابسته هستند ممکن است به‌روز نشوند مگر اینکه آنها را باز کنید.\n\nوقتی دستگاه‌تان شارژ می‌شود، ذخیره‌کننده باتری به صورت خودکار خاموش می‌شود."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"تا زمانی که زمان استراحت در <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> به پایان برسد"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"برای یک دقیقه"</item>
<item quantity="other" msgid="6924190729213550991">"‏برای %d دقیقه"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"برای یک ساعت"</item>
<item quantity="other" msgid="5408537517529822157">"‏برای %d ساعت"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"نامحدود"</string>
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 7566ec68a228..fdec59ae3fc2 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Antaa sovelluksen lukea välimuistin tiedostojärjestelmää ja kirjoittaa siihen."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"soita/vastaanota SIP-puheluja"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Sallii sovelluksen soittaa ja vastaanottaa SIP-puheluja."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"Vuorovaikutteinen puhelunäyttö"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Antaa sovelluksen määrätä, milloin ja millaisena käyttäjä näkee puhelunäytön."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"Puhelinpalveluiden yhteyslupa"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pyydä salasana ennen irrotusta"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Akunsäästötoiminto heikentää laitteen suorituskykyä ja rajoittaa värinää ja useimpia taustatietoja akun iän pidentämiseksi. Sähköposti, viestitys ja muut synkronointia edellyttävät sovellukset eivät ehkä päivity, ellet käynnistä niitä.\n\nAkunsäästö kytkeytyy automaattisesti pois laitteen akun latauksen ajaksi."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Käyttökatkos päättyy klo <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Minuutiksi"</item>
<item quantity="other" msgid="6924190729213550991">"%d minuutiksi"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"Tunniksi"</item>
<item quantity="other" msgid="5408537517529822157">"%d tunniksi"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Toistaiseksi"</string>
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 45ceddee3dec..ed7386c0c292 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permet à l\'application d\'obtenir des droits en lecture et en écriture pour le système de fichiers du cache."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"faire et recevoir des appels SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Autorise l\'application à effectuer et à recevoir des appels SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"enregistrer des nouvelles connexions de télécommunication"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Permettre à l\'application d\'enregistrer de nouvelles connexions de télécommunication"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"gérer les connexions de télécommunication"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permettre à l\'application de gérer les connexions de télécommunication"</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interagir avec l\'écran d\'appel"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permet à l\'application de contrôler quand et comment l\'écran d\'appel s\'affiche."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagir avec les services de téléphonie"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Pour optimiser l\'autonomie de la pile, l\'économiseur d\'énergie réduit les performances de votre appareil et limite les données en arrière-plan. Vous devrez peut-être ouvrir manuellement les applications de courriel, de messagerie et les autres applications synchronisées pour les mettre à jour.\n\nL\'économiseur d\'énergie se désactive automatiquement lorsque votre appareil est en charge."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Jusqu\'à ce que le temps d\'arrêt se termine à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item>
<item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Pendant une heure"</item>
<item quantity="other" msgid="5408537517529822157">"Pendant %d heures"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Indéfiniment"</string>
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 627d2dbe7f63..4f67038d9236 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permet à l\'application d\'obtenir des droits en lecture/écriture concernant le système de fichiers du cache."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"effectuer/recevoir des appels SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Autorise l\'application à effectuer et à recevoir des appels SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"enregistrer des nouvelles connexions de télécommunication"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Permettre à l\'application d\'enregistrer de nouvelles connexions de télécommunication"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"gérer les connexions de télécommunication"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permettre à l\'application de gérer les connexions de télécommunication"</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"contrôler l\'écran d\'appel"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permet à l\'application de contrôler quand et comment l\'écran d\'appel s\'affiche."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagir avec des services de téléphonie"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demander le mot de passe avant d\'annuler l\'épinglage"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Pour optimiser l\'autonomie de la batterie, l\'économiseur de batterie réduit les performances de votre appareil et limite les données en arrière-plan. Vous devrez peut-être ouvrir manuellement vos applications d\'e-mail, de messagerie instantanée et autres applications synchronisées pour les mettre à jour.\n\nL\'économiseur de batterie s\'éteint automatiquement lorsque votre appareil est en charge."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Jusqu\'à ce que le temps d\'arrêt se termine à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item>
<item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Pendant une heure"</item>
<item quantity="other" msgid="5408537517529822157">"Pendant %d heures"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Indéfiniment"</string>
</resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 6e910d8a740e..08de833cd6ed 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite á aplicación ler e escribir no sistema de ficheiros da caché."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"facer/recibir chamadas SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que a aplicación faga e reciba chamadas SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"rexistrar nova conexión de telecomunicacións"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Permite que a aplicación rexistre novas conexións de telecomunicacións."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"xestionar conexións de telecomunicacións"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que a aplicación xestione conexións de telecomunicacións."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interactuar cunha pantalla de chamada"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite á aplicación controlar cando e como ve o usuario a pantalla de chamada."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interactuar cos servizos de telefonía"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicitar un contrasinal antes de soltar a pantalla"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Para axudar a mellorar a duración da batería, o aforro de batería reduce o rendemento do dispositivo e restrinxe a vibración e a maioría dos datos en segundo plano. É posible que o correo, as mensaxes e outras aplicacións que se sincronizan con frecuencia, non se actualicen a menos que as abras.\n\nO aforro de batería desactívase automaticamente durante a carga do dispositivo."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Ata que remate o tempo de inactividade ás <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Durante un minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Durante unha hora"</item>
<item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 66670f2676e9..51586ffb64a6 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ऐप्स को संचय फ़ाइल सिस्‍टम पढ़ने और लिखने देता है."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP कॉल करें/प्राप्‍त करें"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"ऐप्स को SIP कॉल करने और प्राप्‍त करने देती है."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"इन-कॉल स्क्रीन से सहभागिता करें"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ऐप्स को यह नियंत्रित करने देती है कि उपयोगकर्ता को इन-कॉल स्क्रीन कब और कैसी दिखाई देती है."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"टेलीफ़ोनी सेवाओं के साथ सहभागिता करें"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करने से पहले पासवर्ड के लिए पूछें"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"बैटरी के जीवन काल को बेहतर बनाने में सहायता के लिए, बैटरी सेवर आपके डिवाइस के प्रदर्शन को घटा देता है तथा कंपन और अधिकांश पृष्ठभूमि डेटा को सीमित कर देता है. ईमेल, संदेश सेवा और अन्य ऐप्स जो समन्वयन पर निर्भर करते हैं वे तब तक अपडेट नहीं हो सकते जब तक कि आप उन्हें नहीं खोलते.\n\nजब आपका डिवाइस चार्ज हो रहा होता है तो बैटरी सेवर अपने आप बंद हो जाता है."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"जब तक कि <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> बजे आपका डाउनटाइम समाप्‍त न हो"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"एक मिनट के लिए"</item>
<item quantity="other" msgid="6924190729213550991">"%d मिनट के लिए"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"एक घंटे के लिए"</item>
<item quantity="other" msgid="5408537517529822157">"%d घंटे के लिए"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"अनिश्चित समय तक"</string>
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index fcdef47dc584..1a4af08e2355 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Aplikaciji omogućuje čitanje i pisanje u datotečnom sustavu privremene memorije."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"upućivanje/primanje SIP poziva"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Aplikacija može upućivati i primati SIP pozive."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registriranje novih telekomunikacijskih veza"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Aplikaciji omogućuje registriranje novih telekomunikacijskih veza."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"upravljanje telekomunikacijskim vezama"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Aplikaciji omogućuje upravljanje telekomunikacijskim vezama."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakcija sa zaslonom tijekom poziva"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Omogućuje aplikaciji upravljanje vremenom i načinom na koji se korisniku prikazuje zaslon tijekom poziva."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interakcija s telefonskim uslugama"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Traži zaporku radi otkvačivanja"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Da bi se produljilo trajanje baterije, ušteda baterije smanjuje rad uređaja i ograničava vibraciju i većinu pozadinskih podataka. Aplikacije za e-poštu, slanje poruka i ostalo koje se oslanjaju na sinkronizaciju možda se neće ažurirati ako ih ne otvorite.\n\nUšteda baterije isključuje se automatski dok se uređaj puni."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Dok razdoblje zastoja ne završi u <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Jednu minutu"</item>
<item quantity="other" msgid="6924190729213550991">"%d min"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Jedan sat"</item>
<item quantity="other" msgid="5408537517529822157">"%d h"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Neodređeno"</string>
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index f676da459271..87be17493a22 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Lehetővé teszi az alkalmazás számára a gyorsítótár-fájlrendszer olvasását és írását."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP-hívások indítása/fogadása"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP-hívások indításának és fogadásának engedélyezése az alkalmazás számára."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"új telekommunikációs kapcsolatok regisztrálása"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Engedélyezi az alkalmazásnak új telekommunikációs kapcsolatok regisztrálását."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"telekommunikációs kapcsolatok kezelése"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Engedélyezi az alkalmazásnak a telekommunikációs kapcsolatok kezelését."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakció a hívás közbeni képernyővel"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Lehetővé teszi, hogy az alkalmazás felügyelje, a felhasználók mikor és hogyan láthatják a hívás közbeni képernyőt."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"együttműködés a telefonos szolgáltatásokkal"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Jelszó kérése a rögzítés feloldásához"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Az akkumulátor üzemidejének növeléséhez az akkumulátorkímélő mód csökkenti az eszköz teljesítményét, valamint korlátozza a rezgést és a legtöbb háttéradatot. Előfordulhat, hogy az e-mailek, az üzenetküldő programok és más alkalmazások, amelyek a szinkronizálás funkciót használják, nem frissülnek addig, amíg meg nem nyitja őket.\n\nAz akkumulátorkímélő mód automatikusan kikapcsol, amikor az eszköz töltődik."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Amíg az állásidő véget nem ér ekkor: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Egy percen át"</item>
<item quantity="other" msgid="6924190729213550991">"%d percen át"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Egy órán át"</item>
<item quantity="other" msgid="5408537517529822157">"%d órán át"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Határozatlan ideig"</string>
</resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index a53ea2850321..1ab805edcd2b 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Թույլ է տալիս հավելվածին գրել և կարդալ քեշ ֆայլային համակարգը:"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"կատարել կամ ստանալ SIP զանգեր"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Ծրագրին թույլ է տալիս կատարել և ստանալ SIP զանգեր:"</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"փոխազդել մուտքային զանգի էկրանին"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Թույլ է տալիս ծրագրին վերահսկել՝ երբ և ինչպես է օգտվողը տեսնում մուտքային զանգը էկրանին:"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"համագործակցել հեռախոսակապի ծառայությունների հետ"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Ապաամրացնելուց առաջ հարցնել գաղտնաբառը"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Մարտկոցի աշխատաժամանակը շատացնելու համար մարտկոցի տնտեսումը կնվազեցնի ձեր սարքի կատարողականը և կսահմանափակի թրթռոցն ու ֆոնային տվյալներից շատերը: Էլփոստը, հաղորդագրությունները և այլ ծրագրերը, որոնք օգտագործում են համաժամեցումը, կթարմանան միայն դրանք աշխատեցնելիս:\n\nՄարկտոցի տնտեսումը ավտոմատ կանջատվի, հենց սարքը միացվի լիցքավորման:"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Մինչև ձեր ժամանակն ավարտվի ժամը <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Մեկ րոպե"</item>
<item quantity="other" msgid="6924190729213550991">"%d րոպե"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"Մեկ ժամ"</item>
<item quantity="other" msgid="5408537517529822157">"%d ժամ"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Անորոշ ժամանակով"</string>
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index ab5ff0d19568..d80c2bdf2e72 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Mengizinkan apl membaca dan menulis pada sistem file cache."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"lakukan/terima panggilan SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Izinkan aplikasi melakukan dan menerima panggilan SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"daftarkan sambungan telekomunikasi baru"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Mengizinkan aplikasi untuk mendaftarkan sambungan telekomunikasi baru."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"kelola sambungan telekomunikasi"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Mengizinkan aplikasi untuk mengelola sambungan telekomunikasi."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"berinteraksi dengan layar dalam panggilan"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Memungkinkan aplikasi mengontrol kapan dan bagaimana pengguna melihat layar dalam panggilan."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"berinteraksi dengan layanan telepon"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Meminta sandi sebelum melepas sematan"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Guna membantu meningkatkan masa pakai baterai, penghemat baterai mengurangi kinerja perangkat dan membatasi getaran serta sebagian besar data latar belakang. Email, perpesanan, dan aplikasi lain yang bergantung pada sinkronisasi mungkin tidak akan diperbarui kecuali Anda membukanya.\n\nPenghemat baterai dinonaktifkan secara otomatis saat perangkat diisi daya."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Hingga waktu perbaikan Anda berakhir pukul <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Selama satu menit"</item>
<item quantity="other" msgid="6924190729213550991">"Selama %d menit"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Selama satu jam"</item>
<item quantity="other" msgid="5408537517529822157">"Selama %d jam"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Tidak ditentukan"</string>
</resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 1735136f5fe2..2b2415446d7e 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Leyfir forriti að lesa og skrifa í skráakerfi skyndiminnis."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"hringja/svara SIP-símtölum"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Leyfir forritinu að hringja og svara SIP-símtölum."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"skrá nýjar símatengingar"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Leyfir forritinu að skrá nýjar símatengingar."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"stjórna símatengingum"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Leyfir forritinu að stjórna símatengingum."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"eiga samskipti við símtalsskjá"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Leyfir forriti að stjórna því hvenær og hvernig notandi sér símtalsskjá."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"hafa samskipti við símafyrirtæki"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Biðja um aðgangsorð til að losa"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Til að auka endingu rafhlöðunnar dregur rafhlöðusparnaður úr afköstum tækisins og takmarkar titring og flest bakgrunnsgögn. Ekki er víst að tölvupóstur, skilaboð og önnur forrit sem reiða sig á samstillingu verði uppfærð fyrr en þú opnar þau.\n\nSjálfkrafa er slökkt á rafhlöðusparnaði þegar tækið er í hleðslu."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Þangað til niðritíma lýkur, <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Í eina mínútu"</item>
<item quantity="other" msgid="6924190729213550991">"Í %d mínútur"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Í eina klukkustund"</item>
<item quantity="other" msgid="5408537517529822157">"Í %d klukkustundir"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Án tímatakmarkana"</string>
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index df6980942f07..69b76048e605 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Consente all\'applicazione di leggere e scrivere il filesystem nella cache."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"fare/ricevere chiamate SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Consente all\'app di effettuare e ricevere chiamate SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registra nuova connessione di telecomunicazione"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Consente all\'app di registrare nuove connessioni di telecomunicazione."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"gestisci connessioni di telecomunicazione"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Consente all\'app di gestire connessioni di telecomunicazione."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interazione con lo schermo durante una chiamata"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Consente all\'app di stabilire quando e come l\'utente vede lo schermo durante una chiamata."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagire con i servizi di telefonia"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Richiedi password prima di sbloccare"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Per aumentare la durata della batteria, la funzione Risparmio energetico riduce le prestazioni del dispositivo e limita vibrazione e gran parte dei dati in background. App di email, messaggi e altre app basate sulla sincronizzazione potrebbero non essere aggiornate se non le apri.\n\nIl risparmio energetico si disattiva automaticamente quando il dispositivo è in carica."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Fino al termine del periodo di inattività previsto per le <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Per un minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Per %d minuti"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Per un\'ora"</item>
<item quantity="other" msgid="5408537517529822157">"Per %d ore"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Sempre"</string>
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 8e4e2abc4f6a..6a41a47da87f 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"מאפשר לאפליקציה לקרוא ולכתוב במערכת הקבצים של הקבצים השמורים."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"‏ביצוע/קבלה של שיחות SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"‏אפשר לאפליקציה לבצע ולקבל שיחות SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"רישום של חיבור תקשורת חדש"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"מאפשר לאפליקציה לרשום חיבורי תקשורת חדשים."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"ניהול חיבורי תקשורת"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"מאפשר לאפליקציה לנהל חיבורי תקשורת."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"צור אינטראקציה עם מסך שיחה נכנסת"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"מאפשר לאפליקציה לקבוע מתי ואיך המשתמש יראה את מסך השיחה הנכנסת."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"צור אינטראקציה עם שירותי טלפוניה"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"בקש סיסמה לפני ביטול הצמדה"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"כדי לעזור בהארכת חיי הסוללה, תכונת \'חיסכון בסוללה\' מצמצמת את פעילות המכשיר ומגבילה את השימוש ברטט וברוב נתוני הרקע. ייתכן שאימייל, שליחת הודעות ואפליקציות אחרות המסתמכות על סנכרון לא יתעדכנו, אלא אם תפתח אותן.\n\nתכונת \'חיסכון בסוללה\' מופסקת אוטומטית כשהמכשיר מחובר לחשמל."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"עד לסיום ההשבתה בשעה <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"למשך דקה אחת"</item>
<item quantity="other" msgid="6924190729213550991">"‏למשך %d דקות"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"למשך שעה אחת"</item>
<item quantity="other" msgid="5408537517529822157">"‏למשך %d שעות"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"ללא הגבלה"</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index e20947d8f70d..254c7f357071 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"キャッシュファイルシステムの読み書きをアプリに許可します。"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP通話の発着信"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP通話の発着信をアプリに許可します。"</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"新しい通信接続の登録"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"新しい通信接続の登録をアプリに許可します。"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"通信接続の管理"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"通信接続の管理をアプリに許可します。"</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"通話画面とのインタラクション"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"通話画面をユーザーに表示するタイミングと方法の制御をアプリに許可します。"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"電話サービスとの通信"</string>
@@ -1768,10 +1772,14 @@
<string name="lock_to_app_start" msgid="6643342070839862795">"画面を固定しました"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"画面固定を解除しました"</string>
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"オフライン再生を解除する前にPINの入力を求める"</string>
- <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"オフライン再生を解除する前にロック解除パターンの入力を求める"</string>
+ <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"画面固定を解除する前にロック解除パターンの入力を求める"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"オフライン再生を解除する前にパスワードの入力を求める"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンス、バイブレーション、ほとんどのバックグラウンドデータを制限します。同期を使用するメールやメッセージなどのアプリは起動しないと更新されない場合があります。\n\nバッテリーセーバーは、端末の充電中は自動的にOFFになります。"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>にダウンロードが終わるまで"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1分"</item>
<item quantity="other" msgid="6924190729213550991">"%d分"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"1時間"</item>
<item quantity="other" msgid="5408537517529822157">"%d時間"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"制限なし"</string>
</resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 6765fd24b456..d45fb04799a7 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -494,7 +494,7 @@
<string name="permlab_writeProfile" msgid="907793628777397643">"თქვენი საკონტაქტო ინფორმაციის შეცვლა"</string>
<string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"აპს შეეძლება მოწყობილობაზე შენახული პირადი პროფილის ინფორმაციის შეცვლა ან დამატება, მაგალითად, თქვენი სახელისა და საკონტაქტო ინფორმაციის. ეს ნიშნავს, რომ აპს შეუძლია თქვენი იდენტიფიცირება და თქვენი პირადი ინფორმაციის სხვებისთვის გაგზავნა."</string>
<string name="permlab_bodySensors" msgid="4871091374767171066">"სხეულის სენსორები (მაგ. გულისცემის მონიტორები)"</string>
- <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"აპისთვის ნების დართვა იქონიოს წვდომა თქვენი ფიზიკური მდგომარეობის მონიტორინგის სენსორების მონაცემებზე."</string>
+ <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"აპისთვის ნების დართვა, რათა მას ჰქონდეს წვდომა თქვენი ფიზიკური მდგომარეობის მონიტორინგის სენსორების მონაცემებზე."</string>
<string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"სოციალური ნაკადის წაკითხვა"</string>
<string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"აპს შეეძლება თქვენი და თქვენი მეგობრების სოციალური განახლებებთან წვდომა და სინქრონიზაცია. ინფორმაციის გაზიარებისას იყავით ფრთხიად - აპს ექნება შესაძლებლობა, რომ წაიკითხოს სოციალურ ქსელებში კომუნიკაცია თქვენსა და თქვენს მეგობრებს შორის კონფიდენციალურობის მიუხედავად. შენიშვნა: ეს უფლება შესაძლოა ვერ იყოს გამოყენებული ყველა სოციალურ ქსელში."</string>
<string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"თქვენს სოციალურ მაუწყებლობაზე დაწერა"</string>
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"აპებს აძლევს ქეშირებული სისტემური ფაილების წაკითხვისა და მათში ჩანაწერების გაკეთების საშუალებას."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP ზარების წამოწყება/მიღება"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"ნებას რთავს აპს განახორციელოს და მიიღოს SIP ზარები."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"ინტერაქცია საუბრის რეჟიმის ეკრანთან"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"აპს შეეძლება გაკონტროლება, როდის და როგორ დაინახავს მომხმარებელი საუბრის რეჟიმის ეკრანს."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"ტელეფონიის სერვისებთან ინტერაქცია"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ფიქსაციის მოხსნამდე პაროლის მოთხოვნა"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"ბატარეის გამძლეობის გასახანგრძლივებლად, ბატარეის დამზოგი ამცირებს თქვენი მოწყობილობის წარმადობას და ზღუდავს ვიბრაციასა და უმეტეს ფონურ მონაცემს. თუ არ განაახლებთ, შეიძლება არ გაიხსნას ელფოსტა, შეტყობინებები და სხვა აპები, რომლებიც სინქრონიზაციაზეა დამოკიდებული.\n\nბატარეის დამზოგი ავტომატურად გამოირთვება, როდესაც თქვენი მოწყობილობა იტენება."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"დანამ თქვენი კავშირგარეშე დრო დასრულდებოდეს <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-ზე"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ერთი წუთით"</item>
<item quantity="other" msgid="6924190729213550991">"%d წუთით"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"ერთი საათით"</item>
<item quantity="other" msgid="5408537517529822157">"%d საათით"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"სამუდამოდ"</string>
</resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index d698acda4b17..7402cc1908d5 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Қолданбаға кэш файлдық жүйесін оқуға және оған жазуға рұқсат береді."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP қоңырауларын шалу/қабылдау"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Қолданбаға SIP қоңырауларын шалуға және қабылдауға рұқсат етеді."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"қоңыраудағы экранмен өзара әрекеттесу"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Қолданбаға пайдаланушының қоңырау кезінде экранды қашан және қалай көретінін басқару мүмкіндігін береді."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"телефония қызметтерімен өзара әрекеттесу"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Босату алдында құпия сөзді сұрау"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Батареяның қызмет мерзімін жақсарту үшін батарея үнемдегіш құрылғының өнімділігін азайтады және діріл мен фондық деректердің көпшілігін шектейді. Синхрондауды қажет ететін электрондық пошта, хабар алмасу және басқа қолданбалар ашқанша жаңартылмауы мүмкін.\n\nБатарея үнемдегіш құрылғы зарядталып жатқанда автоматты түрде өшеді."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> уақытында әрекетсіздік аяқталғанша"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Бір минут бойы"</item>
<item quantity="other" msgid="6924190729213550991">"%d минут бойы"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"Бір сағат бойы"</item>
<item quantity="other" msgid="5408537517529822157">"%d сағат бойы"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Белгісіз уақыт бойы"</string>
</resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index a0fd3e7c1dca..b6e5c287dce1 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ឲ្យ​កម្មវិធី​អាន និង​សរសេរ​ប្រព័ន្ធ​ឯកសារ​ឃ្លាំង​សម្ងាត់។"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"បង្កើត/ទទួល ការ​ហៅ SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"​ឲ្យ​​កម្មវិធី បង្កើត និង​ទទួល​ការ​ហៅ SIP ។"</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"ចុះ​ឈ្មោះ​ភ្ជាប់​ទូរគមនាគមន៍​ថ្មី"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"ឲ្យ​កម្មវិធី​ចុះ​ឈ្មោះ​ការ​ភ្ជាប់​ទូរគមនាគមន៍​ថ្មី។"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"គ្រប់គ្រង​ការ​ភ្ជាប់​ទូរគមនាគមន៍"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"ឲ្យ​កម្មវិធី​គ្រប់គ្រង​ការ​ភ្ជាប់​ទូរគមនាគមន៍។"</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"ទាក់ទង​ជា​មួយ​អេក្រង់​ហៅ​ចូល"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ឲ្យ​កម្មវិធី​ពិនិត្យ​ពេលវេលា និង​វិធី​ដែល​អ្នកប្រើ​មើល​ឃើញ​អេក្រង់​ហៅ​ចូល។"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"ទាក់ទង​ជា​មួយ​សេវាកម្ម​ទូរស័ព្ទ"</string>
@@ -1774,6 +1778,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"សួរ​រក​ពាក្យ​សម្ងាត់​មុន​ពេល​ផ្ដាច់"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"ដើម្បី​បង្កើន​អាយុ​ថ្ម កម្មវិធី​សន្សំ​ថ្ម​កាត់​បន្ថយ​ការអនុវត្ត​ឧបករណ៍​របស់​អ្នក​ ហើយ​​កម្រិត​ការ​ញ័រ និង​ទិន្នន័យ​ផ្ទៃ​ខាង​ក្រោយ។ អ៊ីមែល, ការ​ផ្ញើ​សារ និង​កម្មវិធី​ផ្សេងៗ​ទៀត​ដែល​ផ្អែក​លើ​ការ​ធ្វើ​សម​កាល​កម្ម​​​មិន​អាច​ធ្វើ​បច្ចុប្បន្នភាព​លុះ​ត្រា​តែ​អ្នក​បើក​ពួកវា។\n\nកម្មវិធី​សន្សំ​ថ្ម​បិទ​ដោយ​ស្វ័យ​ប្រវត្តិ​ពេល​ឧបករណ៍​របស់​អ្នក​កំពុង​បញ្ចូល​ថ្ម។"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"រហូត​ដល់ម៉ោង​សម្រាក ឬរវល់​របស់​អ្នក​បញ្ចប់​នៅ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"សម្រាប់​មួយ​នាទី"</item>
<item quantity="other" msgid="6924190729213550991">"សម្រាប់ %d នាទី"</item>
@@ -1782,5 +1790,7 @@
<item quantity="one" msgid="3480040795582254384">"សម្រាប់​មួយ​ម៉ោង"</item>
<item quantity="other" msgid="5408537517529822157">"សម្រាប់ %d ម៉ោង"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"គ្មាន​​កំណត់"</string>
</resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 8692a4f6a7c7..b23f82f2f61c 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -494,7 +494,7 @@
<string name="permlab_writeProfile" msgid="907793628777397643">"ನಿಮ್ಮದೇ ಸಂಪರ್ಕದ ಕಾರ್ಡ್ ಮಾರ್ಪಡಿಸಿ"</string>
<string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗಿರುವ ನಿಮ್ಮ ಹೆಸರು ಹಾಗೂ ಸಂಪರ್ಕ ಮಾಹಿತಿಯಂತಹ, ವೈಯಕ್ತಿಕ ಪ್ರೊಫೈಲ್ ಮಾಹಿತಿಯನ್ನು ಬದಲಿಸಲು ಅಥವಾ ಸೇರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಅಂದರೆ, ಅಪ್ಲಿಕೇಶನ್‍ ನಿಮ್ಮನ್ನು ಗುರುತಿಸಬಹುದು ಮತ್ತು ನಿಮ್ಮ ಪ್ರೊಫೈಲ್ ಮಾಹಿತಿಯನ್ನು ಇತರರಿಗೆ ಕಳುಹಿಸಬಹುದು ಎಂದರ್ಥ."</string>
<string name="permlab_bodySensors" msgid="4871091374767171066">"ದೇಹದ ಸಂವೇದಗಳು (ಹೃದಯದ ರೇಟ್‌ ಮಾನಿಟರ್‌ಗಳಂತಹ)"</string>
- <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ನಿಮ್ಮ ಹೃದಯ ಬಡಿತದಂತಹ ನಿಮ್ಮ ದೈಹಿಕ ಸ್ಥಿತಿಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುವ ಸೆನ್ಸಾರ್ಸ್‌ಗಳಿಂದ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಅನುಮತಿಸುತ್ತದೆ."</string>
+ <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ನಿಮ್ಮ ಹೃದಯ ಬಡಿತದಂತಹ ನಿಮ್ಮ ದೈಹಿಕ ಸ್ಥಿತಿಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುವ ಸೆನ್ಸರ್‌‌ಗಳಿಂದ ಡೇಟಾ ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string>
<string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ನಿಮ್ಮ ಸಾಮಾಜಿಕ ಸ್ಟ್ರೀಮ್ ಓದಿರಿ"</string>
<string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"ನೀವು ಮತ್ತು ನಿಮ್ಮ ಸ್ನೇಹಿತರ ಸಾಮಾಜಿಕ ನವೀಕರಣಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಮತ್ತು ಸಿಂಕ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಮಾಹಿತಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳುವಾಗ ಜಾಗರೂಕರಾಗಿರಿ -- ಇದು ಗೌಪ್ಯತೆಯನ್ನು ಲೆಕ್ಕಿಸದೆಯೇ, ಸಾಮಾಜಿಕ ನೆಟ್‍‍ವರ್ಕ್‌ಗಳಲ್ಲಿ ನೀವು ಮತ್ತು ನಿಮ್ಮ ಸ್ನೇಹಿತರ ನಡುವೆ ನಡೆದಿರುವ ಸಂವಹನವನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಗಮನಿಸಿ: ಈ ಅನುಮತಿಯನ್ನು ಎಲ್ಲಾ ಸಾಮಾಜಿಕ ನೆಟ್‍‍ವರ್ಕ್‌ಗಳಲ್ಲಿ ಜಾರಿಗೊಳಿಸದೇ ಇರಬಹುದು."</string>
<string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ನಿಮ್ಮ ಸಾಮಾಜಿಕ ಸ್ಟ್ರೀಮ್‌ನಲ್ಲಿ ಬರೆಯಿರಿ"</string>
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ಕ್ಯಾಷ್‌ ಫೈಲ್‌ ವ್ಯವಸ್ಥೆಯನ್ನು ಓದಲು ಮತ್ತು ಬರೆಯಲು ಅಪ್ಲಿಕೇಶನ್‌‌ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP ಕರೆಗಳನ್ನು ಮಾಡಿ/ಸ್ವೀಕರಿಸಿ"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP ಕರೆಗಳನ್ನು ಮಾಡಲು ಮತ್ತು ಸ್ವೀಕರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"ಹೊಸ ಟೆಲಿಕಾಂ ಸಂಪರ್ಕವನ್ನು ನೋಂದಣಿ ಮಾಡಿ"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"ಹೊಸ ಟೆಲಿಕಾಂ ಸಂಪರ್ಕಗಳನ್ನು ನೋಂದಣಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"ಟೆಲಿಕಾಂ ಸಂಪರ್ಕಗಳನ್ನು ನಿರ್ವಹಿಸಿ"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"ಟೆಲಿಕಾಂ ಸಂಪರ್ಕಗಳನ್ನು ನಿರ್ವಹಿಸಲು ಅಪ್ಲಿಕೇಶನ್ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"ಒಳ-ಕರೆ ಪರದೆಯ ಮೂಲಕ ಸಂವಹನ ನಡೆಸಿ"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ಬಳಕೆದಾರರು ಒಳ-ಕರೆಯ ಪರದೆಯನ್ನು ಯಾವಾಗ ಮತ್ತು ಹೇಗೆ ನೋಡುತ್ತಾರೆ ಎಂಬುದನ್ನು ನಿಯಂತ್ರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"ಟೆಲಿಫೋನಿ ಸೇವೆಗಳೊಂದಿಗೆ ಸಂವಾದ ನಡೆಸಿ"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ಅನ್‌ಪಿನ್ ಮಾಡುವುದಕ್ಕೂ ಮೊದಲು ಪಾಸ್‌ವರ್ಡ್ ಕೇಳಿ"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"ಬ್ಯಾಟರಿ ಬಾಳಿಕೆಯನ್ನು ಹೆಚ್ಚಿಸುವ ನಿಟ್ಟಿನಲ್ಲಿ ಸಹಾಯ ಮಾಡಲು, ಬ್ಯಾಟರಿ ಉಳಿತಾಯವು ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಕುಂಠಿತಗೊಳಿಸುತ್ತದೆ ಮತ್ತು ವೈಬ್ರೇಷನ್‌‌ ಹಾಗೂ ಹೆಚ್ಚಿನ ಹಿನ್ನೆಲೆ ಡೇಟಾವನ್ನು ಸೀಮಿತಗೊಳಿಸುತ್ತದೆ. ಇಮೇಲ್, ಸಂದೇಶ ಕಳುಹಿಸುವಿಕೆ, ಮತ್ತು ಸಿಂಕ್ ಮಾಡುವುದನ್ನು ಅವಲಂಬಿಸಿರುವ ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ನೀವು ತೆರೆಯುವವರೆಗೆ ಅವುಗಳನ್ನು ನವೀಕರಿಸಲಾಗುವುದಿಲ್ಲ.\n\nನಿಮ್ಮ ಸಾಧನವು ಚಾರ್ಜ್ ಆಗುತ್ತಿರುವಾಗ ಬ್ಯಾಟರಿ ಉಳಿತಾಯವು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆಫ್ ಆಗುತ್ತದೆ."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"ನಿಮ್ಮ ಅಲಭ್ಯತೆ ಕೊನೆಗೊಳ್ಳುವವರೆಗೆ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ಒಂದು ನಿಮಿಷದವರೆಗೆ"</item>
<item quantity="other" msgid="6924190729213550991">"%d ನಿಮಿಷಗಳವರೆಗೆ"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"ಒಂದು ಗಂಟೆಯವರೆಗೆ"</item>
<item quantity="other" msgid="5408537517529822157">"%d ಗಂಟೆಗಳವರೆಗೆ"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"ಅನಿರ್ದಿಷ್ಟವಾಗಿ"</string>
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 0a89714525a1..241159316dcf 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"앱이 캐시 파일 시스템을 읽고 쓸 수 있도록 허용합니다."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP 통화 발신/수신"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"앱에서 SIP 통화를 발신 및 수신하도록 허용"</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"통화 화면과 상호작용"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"앱에서 사용자가 통화 화면을 보는 시기와 방법을 제어하도록 허용합니다."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"전화 서비스와 상호 작용"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"고정 해제 이전에 비밀번호 요청"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"배터리 수명을 개선하기 위해 배터리 세이버에서는 기기의 성능을 줄이고 진동과 대부분의 백그라운드 데이터를 제한합니다. 동기화가 필요한 이메일, 메시지, 기타 앱은 열어야 업데이트됩니다.\n\n기기를 충전하는 중에는 배터리 세이버가 자동으로 사용 중지됩니다."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>에 정지가 종료될 때까지"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1분 동안"</item>
<item quantity="other" msgid="6924190729213550991">"%d분 동안"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"1시간 동안"</item>
<item quantity="other" msgid="5408537517529822157">"%d시간 동안"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"무제한"</string>
</resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index d240c7a0850a..5f34b9de0fb1 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -926,6 +926,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Колдонмого кэш файл тутумун окуу жана жазуу мүмкүнчүлүгүн берет."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP чалууларын жасоо/кабыл алуу"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Колдонмонун SIP чалууларын жасап жана кабыл алуусуна жол ачат."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"чалуу экраны менен байланыштыруу"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Колдонмого чалуу экраны качан жана кандай көрүнө тургандыгын башкаруу мүмкүнчүлүгүн берет."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"телефония кызматтары"</string>
@@ -2252,6 +2260,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Бошотуудан мурун сырсөз суралсын"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Батарея өмүрүн узартууга жардамдашуу үчүн, батарея үнөмдөгүч түзмөгүңүздүн өндүрүмдүүлүгүн азайтып, дирилдөөнү жана көпчүлүк фон дайындарын чектейт. Email, билдирүү жазуу жана башка шайкештирүүгө көз каранды колдонмолор, аларды ачмайыңызча жаңыртылбашы мүмкүн.\n\nТүзмөгүңүз кубатталып жатканда батарея үнөмдөгүч автоматтык түрдө өчөт."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Иштебей турган абал <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> аяктамайынча"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Бир мүнөткө"</item>
<item quantity="other" msgid="6924190729213550991">"%d мүнөткө"</item>
@@ -2260,5 +2272,7 @@
<item quantity="one" msgid="3480040795582254384">"Бир саатка"</item>
<item quantity="other" msgid="5408537517529822157">"%d саатка"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Белгисиз"</string>
</resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 34ecf92a4704..719717bbfac4 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານ ແລະຂຽນ ລະບົບໄຟລ໌ແຄດ."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"ຮັບສາຍ/ໂທອອກ ຜ່ານ SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"ອະນຸຍາດ​ໃຫ້ແອັບຯ​ສາມາດ​ຮັບສາຍ ແລະໂທອອກ​ຜ່ານ SIP ໄດ້"</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"ໂຕ້​ຕອບ​ກັບ​ໜ້າ​ຈໍ​ການ​ໂທ"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ອະນຸຍາດ​ໃຫ້​ແອັບຯ​ຄວບຄຸມ​ເວລາ ແລະ​ວິທີ​ການ​ທີ່​ຜູ່ໃຊ້​ເຫັນ​ໜ້າ​ຈໍ​ການ​ໂທ​ໄດ້."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"ສັ່ງ​ບໍ​ລິ​ການ​ໂທ​ລະ​ສັບ"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"​ຖາມ​ຫາ​ລະ​ຫັດ​ຜ່ານ​ກ່ອນ​ຍົກ​ເລີກ​ການ​ປັກ​ໝຸດ"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"ເພື່ອ​ຊ່ວຍ​ປັບ​ປຸງ​ອາ​ຍຸ​ແບັດ​ເຕ​ີ​ຣີ, ໂຕ​ປະ​ຢັດ​ແບັດ​ເຕີ​ຣີ​ຈະຫຼຸດ​ປະ​ສິດ​ທິ​ພາບ​​ຂອງ​ອຸ​ປະ​ກອນ​ທ່ານ​ລົງ ແລະ​ຈຳ​ກັດ​ການ​ສັ່ນເຕືອນ ຮວມ​ເຖິງຂໍ້​ມູນ​ພື້ນຫຼັງ​ສ່ວນ​ໃຫຍ່​ນຳ. ອີ​ເມວ, ການ​ສົ່ງ​ຂໍ້​ຄວາມ ແລະ​ແອັບຯ​ອື່ນໆ​ທີ່​ອີງ​ອາ​ໃສ​ການ​ຊິ້ງ​ຂໍ້​ມູນ​ອາດບໍ່​ມີ​ການ​ອັບ​ເດດ​ຈົນ​ກວ່າ​ທ່ານ​ຈະ​ເປີດ​ພວກ​ມັນ​ຂຶ້ນ​ມາ.\n\n​ໂຕ​ປະ​ຢັດ​ແບັດ​ເຕີ​ຣີ​ຈະ​ປິດ​ໂດຍ​ອັດ​ຕະ​ໂນ​ມັດ​ເມື່ອ​ມີ​ອຸ​ປະ​ກອນ​ຖືກ​ສາກ​ໄຟ."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"ຈົນ​ກວ່າ​ດາວ​ທາມ​ຂອງ​ທ່ານ​ຈະ​ສິ້ນ​ສຸດ​ທີ່ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ເປັນ​ເວລາ​ນຶ່ງ​ນາ​ທີ"</item>
<item quantity="other" msgid="6924190729213550991">"ເປັນ​ເວລາ %d ນາ​ທີ"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"ເປັນ​ເວລາ​ນຶ່ງ​ຊົ່ວ​ໂມງ"</item>
<item quantity="other" msgid="5408537517529822157">"ເປັນ​ເວລາ %d ຊົ່ວ​ໂມງ"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"ຢ່າງ​ບໍ່​ມີ​ກຳນົດ"</string>
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 35fbe0c2ebf7..f6e05dc2d94a 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Leidžiama programai skaityti talpyklos failų sistemą ir į ją rašyti."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"skambinti / priimti SIP skambučius"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Leidžiama programai skambinti ir priimti SIP skambučius."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registruoti naujus telekomunikacijų ryšius"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Programai leidžiama registruoti naujus telekomunikacijų ryšius."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"tvarkyti telekomunikacijų ryšius"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Programai leidžiama tvarkyti telekomunikacijų ryšius."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"sąveika su gaunamojo skambučio ekranu"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Programai leidžiama valdyti, kada ir kaip naudotojai matys gaunamojo skambučio ekraną."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"sąveikauti su telefonijos paslaugomis"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Prašyti slaptažodžio prieš atsegant"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Siekiant pailginti akumuliatoriaus veikimo laiką, Akumuliatoriaus tausojimo priemonė sumažina įrenginio našumą ir apriboja vibravimą bei daugumą foninių duomenų. El. paštas, pranešimų siuntimas ir kitos programos, kurios veikia sinchronizavimo pagrindu, gali nebūti atnaujintos, nebent jas atidarysite.\n\nKraunant įrenginį Akumuliatoriaus tausojimo priemonė automatiškai išjungiama."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Kol jūsų prastova baigsis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 min."</item>
<item quantity="other" msgid="6924190729213550991">"%d min."</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"1 val."</item>
<item quantity="other" msgid="5408537517529822157">"%d val."</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Neapibrėžta"</string>
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index de2d8a66ac75..72ecf591e033 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ļauj lietotnei lasīt un rakstīt kešatmiņas failu sistēmā."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP zvanu veikšana/saņemšana"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Ļauj lietotnei veikt un saņemt SIP zvanus."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"jauna telekomunikācijas savienojuma reģistrēšana"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Ļauj lietotnei reģistrēt jaunus telekomunikācijas savienojumus."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"telekomunikācijas savienojumu pārvaldība"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Ļauj lietotnei pārvaldīt telekomunikācijas savienojumus."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"Mijiedarboties ar zvana laikā rādītu ekrānu"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Ļauj lietotnei kontrolēt, kad un kā lietotājam ir redzams zvana laikā redzamais ekrāns."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"mijiedarbība ar tālruņu komunikācijas pakalpojumiem"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pirms atspraušanas pieprasīt paroli"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Lai paildzinātu akumulatora darbības laiku, akumulatora enerģijas taupīšanas režīmā tiks pazemināta ierīces veiktspēja, samazināta vibrācija un ierobežota liela daļa fona datu. E-pasta, ziņojumapmaiņas un citas lietotnes, kas regulāri tiek sinhronizētas, tiks atjauninātas tikai tad, ja tās atvērsiet.\n\nIerīces uzlādes laikā akumulatora jaudas taupīšana tiek izslēgta automātiski."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Līdz beigsies dīkstāve (<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Vienu minūti"</item>
<item quantity="other" msgid="6924190729213550991">"%d min"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Vienu stundu"</item>
<item quantity="other" msgid="5408537517529822157">"%d h"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Uz nenoteiktu laiku"</string>
</resources>
diff --git a/core/res/res/values-mcc204-mnc04/config.xml b/core/res/res/values-mcc204-mnc04/config.xml
index 3c0381427b8a..d7484e164576 100644
--- a/core/res/res/values-mcc204-mnc04/config.xml
+++ b/core/res/res/values-mcc204-mnc04/config.xml
@@ -31,4 +31,11 @@
<item>"*611:+19085594899,BAE0000000000000"</item>
<item>"*86:+1MDN,BAE0000000000000"</item>
</string-array>
+
+ <!-- Flag indicating whether strict threshold is used, or lenient threshold is used,
+ when evaluating RSRP for LTE antenna bar display
+ 0. Strict threshold
+ 1. Lenient threshold
+ -->
+ <integer name="config_LTE_RSRP_threshold_type">0</integer>
</resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index d0a57b37ee10..8cb2928e83e2 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -49,4 +49,11 @@
<item>"*611:+19085594899,"</item>
<item>"*86:+1MDN,"</item>
</string-array>
+
+ <!-- Flag indicating whether strict threshold is used, or lenient threshold is used,
+ when evaluating RSRP for LTE antenna bar display
+ 0. Strict threshold
+ 1. Lenient threshold
+ -->
+ <integer name="config_LTE_RSRP_threshold_type">0</integer>
</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index a2049f4607d5..58ee5ec96d9c 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Дозволува апликацијата да чита и да пишува кеш систем на датотеки."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"остварувај/примај повици преку СИП"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Дозволува апликацијата да остварува и прима повици преку СИП."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"регистрира нови телекомуникациски врски"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Дозволува апликацијата да регистрира нови телекомуникациски врски."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"управува со телекомуникациски врски"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Дозволува апликацијата да управува со телекомуникациски врски."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"комуницирај со екран на дојдовен повик"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Овозможува апликацијата да контролира кога и како корисникот го гледа екранот на дојдовен повик."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"комуницира со телефонски услуги"</string>
@@ -1774,6 +1778,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Прашај за лозинка пред откачување"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"За да помогне во подобрување на трајноста на батеријата, штедачот на батерија го намалува учинокот на уредот и ги ограничува вибрациите и повеќето податоци во заднина. Е-поштата, испраќањето пораки и другите апликации кои се потпираат на синхронизирање може да не се ажурираат освен ако не ги отворите.\n\nШтедачот на батерија автоматски се исклучува кога уредот се полни."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Додека не заврши паузата во <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"За една минута"</item>
<item quantity="other" msgid="6924190729213550991">"За %d минути"</item>
@@ -1782,5 +1790,7 @@
<item quantity="one" msgid="3480040795582254384">"За еден час"</item>
<item quantity="other" msgid="5408537517529822157">"За %d часа"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Неодредено време"</string>
</resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 44399cc0dc6f..c303fa23759b 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"കാഷെ ഫയൽ സിസ്‌റ്റം റീഡുചെയ്യുന്നതിനും റൈറ്റുചെയ്യുന്നതിനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP കോളുകൾ വിളിക്കുക/സ്വീകരിക്കുക"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP കോളുകൾ വിളിക്കാനും സ്വീകരിക്കാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"പുതിയ ടെലികോം കണക്ഷൻ രജിസ്‌റ്റർ ചെയ്യുക"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"പുതിയ ടെലികോം കണക്ഷനുകൾ രജിസ്‌റ്റർ ചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"ടെലികോം കണക്ഷനുകൾ നിയന്ത്രിക്കുക"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"ടെലികോം കണക്ഷനുകൾ നിയന്ത്രിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"ഇൻ-കോൾ സ്‌ക്രീനുമായി സംവദിക്കുക"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ഉപയോക്താവ് ഇൻ-കോൾ സ്‌ക്രീൻ എപ്പോൾ, എങ്ങനെ കാണുന്നുവെന്നത് നിയന്ത്രിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"ടെലിഫോണി സേവനങ്ങൾ ഉപയോഗിച്ച് സംവദിക്കുക"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"അൺപിൻ ചെയ്യുന്നതിനുമുമ്പ് പാസ്‌വേഡ് ആവശ്യപ്പെടുക"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"ബാറ്ററി ആയുസ്സ് മെച്ചപ്പെടുത്താൻ സഹായിക്കുന്നതിന്, ബാറ്ററി സേവർ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനത്തെ കുറയ്‌ക്കുകയും വൈബ്രേഷനെയും മിക്ക പശ്ചാത്തല ഡാറ്റയെയും പരിമിതപ്പെടുത്തുകയും ചെയ്യുന്നു. ഇമെയിൽ, സന്ദേശമയയ്‌ക്കൽ, സമന്വയിപ്പിക്കലിനെ ആശ്രയിച്ചുള്ള മറ്റ് അപ്ലിക്കേഷനുകൾ എന്നിവ നിങ്ങൾ തുറക്കുന്നതുവരെ അപ്‌ഡേറ്റുചെയ്യാനിടയില്ല.\n\nനിങ്ങളുടെ ഉപകരണം ചാർജ്ജുചെയ്യുമ്പോൾ ബാറ്ററി സേവർ യാന്ത്രികമായി ഓഫാകും."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-ന് നിങ്ങളുടെ കാലാവധി അവസാനിക്കുന്നതുവരെ"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ഒരു മിനിറ്റ് ദൈർഘ്യം"</item>
<item quantity="other" msgid="6924190729213550991">"%d മിനിറ്റ് ദൈർഘ്യം"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"ഒരു മണിക്കൂർ ദൈർഘ്യം"</item>
<item quantity="other" msgid="5408537517529822157">"%d മണിക്കൂർ ദൈർഘ്യം"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"അവ്യക്തം"</string>
</resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 0368a980038d..38e395ce39be 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Апп нь кеш файлсистемийг унших бичих боломжтой."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP дуудлага хийх/хүлээн авах"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Апп-д SIP дуудлага хийх болон хүлээн авахыг зөвшөөрөх."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"шинэ телеком холболтуудыг бүртгэх"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Апп-д шинэ телеком холболтуудыг бүртгэхийг зөвшөөрнө."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"телеком холболтуудыг удирдах."</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Апп-д телеком холболтуудыг удирдахыг зөвшөөрнө."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"дуудлагын дэлгэцтэй харьцах"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Апп-д дуудлагын дэлгэцийг хэрэглэгчид хэзээ хэрхэн харуулахыг удирдахыг зөвшөөрнө."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"телефоны үйлчилгээтэй харилцах"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Батерейны ашиглалтыг уртасгахын тулд батерей хэмнэгч нь таны төхөөрөмжийн ажиллагааг бууруулж, чичрэлт болон далд датаны ихэнх хувийг хязгаарлана. Имэйл, зурвас гэх мэт синк хийгддэг бусад апп-ууд таныг нээхээс нааш шинэчлэгдэхгүй байж болно.\n\nТаныг төхөөрөмжөө цэнэглэх үед батерей хэмнэгч автоматаар унтарна."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Таны уйтгартай байдал <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-д дуусах хүртэл"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Нэг минутын турш"</item>
<item quantity="other" msgid="6924190729213550991">"%d минутын турш"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Нэг цагийн турш"</item>
<item quantity="other" msgid="5408537517529822157">"%d цагийн турш"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Тодорхойгүй"</string>
</resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 90f23945d940..b7401c774f62 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"कॅशे filesystem वाचण्यासाठी आणि लिहिण्यासाठी अॅप ला अनुमती देते."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP कॉल करा/प्राप्त करा"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"अॅपला SIP कॉल करण्‍याची आणि प्राप्त करण्‍याची अनुमती देते."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"नवीन टेलिकॉम कनेक्शनची नोंदणी करा"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"नवीन टेलिकॉम कनेक्शनची नोंदणी करण्यासाठी अॅपला अनुमती देते."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"टेलिकॉम कनेक्शन व्यवस्थापित करा"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"टेलिकॉम कनेक्शन व्यवस्थापित करण्यासाठी अॅप ला अनुमती देते."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"कॉल-मधील स्‍क्रीनशी परस्‍परसंवाद करा"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"वापरकर्ता कॉल-मधील स्‍क्रीन केव्‍हा आणि कशी पाहतो ते नियंत्रित करण्‍याची अ‍ॅपला अनुमती देते."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"टेलिफोनी सेवांशी परस्परसंवाद साधा"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"अनपिन करण्‍यापूर्वी संकेतशब्दासाठी विचारा"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"बॅटरीचे आयुष्य सुधारण्यात मदत होण्यासाठी, बॅटरी बचतकर्ता आपल्या डिव्हाइसचे कार्यप्रदर्शन कमी करतो आणि कंपन आणि बराच पार्श्वभूमी डेटा मर्यादित करतो. संकालनावर अवलंबून असणारे ईमेल, संदेशन आणि अन्य अॅप्स आपण ते उघडल्याशिवाय अद्यतनित होऊ शकत नाहीत.\n\nआपले डिव्हाइस चार्ज होत असते तेव्हा बॅटरी बचतकर्ता स्वयंचलितपणे बंद होतो."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"आपला कार्य न करण्याचा कालावधी <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> वाजता समाप्त होईपर्यंत"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"एक मिनिटासाठी"</item>
<item quantity="other" msgid="6924190729213550991">"%d मिनिटांसाठी"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"एका तासासाठी"</item>
<item quantity="other" msgid="5408537517529822157">"%d तासांसाठी"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"अनिश्‍चितपणे"</string>
</resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index bebee52e090d..95d7cef62ec1 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Membenarkan apl membaca dan menulis cache sistem fail."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"buat/terima panggilan SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Membenarkan apl membuat dan menerima panggilan SIP."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"berinteraksi dengan skrin dalam panggilan"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Membenarkan apl mengawal masa dan cara pengguna melihat skrin dalam panggilan."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"berinteraksi dengan perkhidmatan telefoni"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Minta kata laluan sebelum menyahsemat"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Untuk membantu memperbaik hayat bateri, penjimat bateri mengurangkan prestasi peranti anda dan menghadkan getaran serta kebanyakan data latar belakang. E-mel, pemesejan dan apl lain yang bergantung pada penyegerakan mungkin tidak dikemas kini melainkan anda membuka apl tersebut.\n\nPenjimat bateri dimatikan secara automatik semasa peranti anda mengecas."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Sehingga waktu gendala anda berakhir pada <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Selama satu minit"</item>
<item quantity="other" msgid="6924190729213550991">"Selama %d minit"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"Selama satu jam"</item>
<item quantity="other" msgid="5408537517529822157">"Selama %d jam"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Selama-lamanya"</string>
</resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 2a8bd765be75..999fb48f5456 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"appအား ဖိုင်စနစ်၏ကက်ရှကို ဖတ် နှင့် ရေး ခွင့်ပြုသည်။"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP ခေါ်ဆိုမှုများ ခေါ်ရန်/လက်ခံရန်"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP ခေါ်ဆိုမှုများ ခေါ်ရန်နှင့် လက်ခံနိုင်ရန် app ကို ခွင့်ပြုပါ။"</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"တယ်လီကွမ် ဆက်သွယ်မှု အသစ်ကို မှတ်ပုံတင်ရန်"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"appအား တယ်လီကွမ် ဆက်သွယ်မှု အသစ်ကို မှတ်ပုံတင်ခွင့် ပြုပါ။"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"တယ်လီကွမ် ဆက်သွယ်မှုများကို စီမံရန်"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"appအား တယ်လီကွမ် ဆက်သွယ်မှုများကို စီမံခွင့် ပြုပါ။"</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"ခေါ်ဆိုမှု-အဝင် မျက်နှာပြင်နဲ့ တုံ့ပြန်လုပ်ကိုင်ရန်"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"appအား အသုံးပြုသူက ခေါ်ဆိုမှုအဝင် မျက်နှာပြင် ဘယ်အချိန်မှာ ဘယ်လို မြင်ရမှာကို ထိန်းချုပ်ခွင့်ပေးရန်"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"တယ်လီဖုန်း ဝန်ဆောင်မှုများနှင့် အပြန်အလှန် တုံ့ပြန်မှု"</string>
@@ -1772,11 +1776,17 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ပင်မဖြုတ်မီမှာ စကားဝှက်ကို မေးကြည့်ရန်"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"ဘက်ထရီသက်တမ်း ကြာရှည်ခံရန်အတွက်၊ ဘက်ထရီချွေတာရေးအပိုင်းမှ သင့် စက်ပစ္စည်း၏ဆောင်ရွက်ချက်များကို လျော့ချပေးပြီး တုန်ခါမှုနှင့် နောက်ခံအချက်အလက်အများစုကို ကန့်သတ်ပေးသည်။ အီးမေး၊ စာပို့ခြင်း နှင့် တခြားapp များကို သင်ဖွင့်မထားပါက အချိန်နှင့်တပြေးညီ ညှိမပေးပါ။ \n\n စက်ပစ္စည်း အားသွင်းနေစဉ် ဘက်ထရီချွေတာရေးအပိုင်းသည် အလိုအလျောက်ပင် အလုပ်မလုပ်ပါ။"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"သင်၏ စက်ရပ်ချိန် <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> မှာ ပြီးဆုံးသည့် အထိ။"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"တစ်မိနစ် အတွင်း"</item>
<item quantity="other" msgid="6924190729213550991">"%d မိနစ် အတွင်း"</item>
</plurals>
<!-- String.format failed for translation -->
<!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"အကန့်အသတ်မရှိစွာ"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index a9d8b118b67d..f9e44e7106e7 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Lar appen lese og skrive til det bufrede filsystemet."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"foreta/motta SIP-anrop"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Tillater at appen utfører og mottar SIP-anrop."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registrere nye telekom-tilkoblinger"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Lar appen registrere nye telekom-tilkoblinger."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"administrere telekom-tilkoblinger"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Lar appen administrere telekom-tilkoblinger."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"samhandle med skjermen for innkommende anrop"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Lar appen styre når og hvordan brukeren ser skjermen for innkommende anrop."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"samhandle med telefonitjenester"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Krev passord for å løsne apper"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Batterisparing reduserer enhetens ytelse og begrenser vibrering og de fleste bakgrunnsdata for å forbedre batterilevetiden. Det kan hende E-post, Meldinger og andre apper som er avhengige av synkronisering, ikke oppdateres med mindre du åpner dem.\n\nBatterisparing slås automatisk av når enheten lades."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Til hviletiden din ender kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"I ett minutt"</item>
<item quantity="other" msgid="6924190729213550991">"I %d minutter"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"I én time"</item>
<item quantity="other" msgid="5408537517529822157">"I %d timer"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"På ubestemt tid"</string>
</resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index fd1173c1af29..e93bee10d744 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"केस फाइल प्रणालीलाई पढ्न र लेख्‍नको लागि अनुप्रयोगलाई अनुमति दिन्छ।"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP कलहरू प्राप्त/बनाउन"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP कलहरू बनाउन र प्राप्त गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"नयाँ दूरसंचार जडान दर्ता गर्नुहोस्"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"अनुप्रयोग लाई नयाँ दूरसंचार सम्पर्क दर्ता गर्न अनुमति दिन्छ।"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"दूरसंचार जडान व्यवस्थापन गर्नुहोस्"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"अनुप्रयोग लाई टेलिकम जडान व्यवस्थापन गर्न अनुमति दिन्छ।"</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"आगमन कल स्क्रिन संग अन्तर्क्रिया गर्नुहोस्"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"कहिले र कसरी प्रयोगकर्ताले आगमन कल स्क्रीन हेर्न सक्दछ भनेर नियन्त्रण गर्न अनुप्रयोगलाई अनुमति दिनुहोस्।"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"टेलिफोनी सेवा अन्तरक्रिया"</string>
@@ -1780,6 +1784,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"पिन निकाल्नुअघि पासवर्ड सोध्नुहोस्"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"ब्याट्री जीवन सुधार्न, ब्याट्री बचतले आफ्नो उपकरणको प्रदर्शन र कम्पनको सीमा र सबैभन्दा पृष्ठभूमि डेटा कम गर्छ। इमेल, सन्देश, र अन्य अनुप्रयोगहरू जसले तपाईं तिनीहरूलाई नखोले सम्म समिकरण अद्यावधिक नगर्न सक्छ भनि भर पर्छ।\n\nब्याट्री बचतले तपाईँको उपकरण चार्ज हुँदै बेला तपाईँको उपकरण स्वचालित बन्द गर्छ।"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"तपाईँको <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> डाउनटाइम समाप्त हुँदा सम्म"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"एक मिनेटको लागि"</item>
<item quantity="other" msgid="6924190729213550991">"%d मिनेटको लागि"</item>
@@ -1788,5 +1796,7 @@
<item quantity="one" msgid="3480040795582254384">"एक घण्टाको लागि"</item>
<item quantity="other" msgid="5408537517529822157">"%d घण्टाको लागि"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"अनिश्चित"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 97744bbd58aa..f2564d889ff4 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Hiermee kan de app het cachebestandssysteem lezen en schrijven."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP-oproepen plaatsen/ontvangen"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Toestaan dat de app SIP-oproepen plaatst en ontvangt."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"nieuwe telecomverbinding registreren"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Hiermee kan de app nieuwe telecomverbindingen registreren."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"telecomverbindingen beheren"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Hiermee kan de app telecomverbindingen beheren."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interactie met scherm in actieve oproep"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Hiermee kan de app bepalen wanneer en hoe de gebruiker het scherm in een actieve oproep te zien krijgt."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"communicatie met telefonische diensten"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Vragen om wachtwoord voordat items worden losgemaakt"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Accubesparing beperkt de prestaties van uw apparaat, de trilfunctie en de meeste achtergrondgegevens om de accuduur te verlengen.\n\nAccubesparing wordt automatisch uitgeschakeld wanneer uw apparaat wordt opgeladen."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Totdat uw downtime eindigt om <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Eén minuut"</item>
<item quantity="other" msgid="6924190729213550991">"%d minuten"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Eén uur"</item>
<item quantity="other" msgid="5408537517529822157">"%d uur"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Voor onbepaalde tijd"</string>
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index f52f4059de67..69ddf8391a9d 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Pozwala aplikacji na odczyt i zapis w systemie plików pamięci podręcznej."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"wykonywanie/odbieranie połączeń SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Pozwala aplikacji na wykonywanie i odbieranie połączeń SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"rejestrowanie nowych połączeń telekomunikacyjnych"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Zezwala aplikacji na rejestrowanie nowych połączeń telekomunikacyjnych."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"zarządzanie połączeniami telekomunikacyjnymi"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Zezwala aplikacji na zarządzanie połączeniami telekomunikacyjnymi."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakcje z ekranem połączenia"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Zezwala aplikacji na kontrolowanie, kiedy i w jaki sposób użytkownik widzi ekran połączenia."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"korzystanie z usług telefonii"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Aby odpiąć, poproś o hasło"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Aby wydłużyć czas pracy baterii, Oszczędzanie baterii ogranicza aktywność urządzenia, w tym wibracje i przetwarzanie większości danych w tle. Poczta, SMS i inne synchronizowane aplikacje mogą nie aktualizować swojej zawartości, dopóki ich nie otworzysz.\n\nOszczędzanie baterii wyłącza się automatycznie podczas ładowania urządzenia."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Do zakończenia przestoju o <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Przez minutę"</item>
<item quantity="other" msgid="6924190729213550991">"Przez %d min"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Przez 1 godz."</item>
<item quantity="other" msgid="5408537517529822157">"Przez %d godz."</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Na czas nieokreślony"</string>
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 48a8f2fa1c43..84100f075aee 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite à aplicação ler e escrever no sistema de ficheiros da cache."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"efetuar/receber chamadas SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que a aplicação efetue e receba chamadas SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registar novas ligações de telecomunicação"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Permite que a aplicação registe novas ligações de telecomunicação."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"gerir ligações de telecomunicação"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que a aplicação faça a gestão das ligações de telecomunicação."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interagir com o ecrã durante uma chamada"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite que a aplicação controle quando e como o utilizador vê o ecrã durante uma chamada."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"Interagir com serviços telefónicos"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir palavra-passe antes de soltar"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Para ajudar a melhorar a duração da bateria, a poupança de bateria reduz o desempenho do dispositivo e limita a vibração e a maior parte dos dados de segundo plano. O email, as mensagens e outras aplicações que dependem da sincronização não podem ser atualizados, exceto se os abrir.\n\nA poupança de bateria desliga-se automaticamente quando o dispositivo estiver a carregar."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Até o período de inatividade terminar às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Durante um minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Durante %d minutos"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Durante uma hora"</item>
<item quantity="other" msgid="5408537517529822157">"Durante %d horas"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 708f5260a1a5..3c0ab1ea6fa2 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite que o app leia e grave o sistema de arquivos cache."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"fazer/receber chamadas SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que o app faça e receba chamadas SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registrar nova conexão de telecomunicações"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Permite que o app registre novas conexões de telecomunicações."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"gerenciar conexões de telecomunicações"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que o app gerencie conexões de telecomunicações."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interagir com chamada na tela"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite que o app controle quando e como o usuário visualiza a chamada na tela."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagir com os serviços de telefonia"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Para ajudar a melhorar a vida útil da bateria, a economia de bateria reduz o desempenho do dispositivo e restringe a vibração e a maioria dos dados em segundo plano. É possível que apps de e-mail, mensagens, entre outros que dependem de sincronização não sejam atualizados a menos que sejam abertos.\n\nA economia de bateria é desativada automaticamente quando o dispositivo estiver carregando."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Até o período de inatividade terminar às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Por 1 minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Por %d minutos"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Por 1 hora"</item>
<item quantity="other" msgid="5408537517529822157">"Por %d horas"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 6413218c85b1..6ae7f52bba49 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite aplicaţiei să scrie şi să citească sistemul de fişiere cache."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"efectuarea/primirea apelurilor SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Permite aplicației să efectueze și să primească apeluri SIP."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interacțiune cu ecranul în timpul unui apel"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Permite aplicației să controleze când și cum vede utilizatorul ecranul în timpul unui apel."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"să interacționeze cu servicii de telefonie"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Solicită parola înainte de a anula fixarea"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Pentru a ajuta la îmbunătățirea duratei bateriei, modul Economisirea bateriei reduce performanțele dispozitivului și limitează vibrațiile și majoritatea datelor de fundal. Mesajele prin e-mail și alte aplicații care se bazează pe sincronizare nu se vor actualiza dacă nu le deschideți.\n\nEconomisirea baterie se dezactivează automat când dispozitivul se încarcă."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Până când inactivitatea dvs. se încheie la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Timp de un minut"</item>
<item quantity="other" msgid="6924190729213550991">"Timp de %d (de) minute"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"Timp de o oră"</item>
<item quantity="other" msgid="5408537517529822157">"Timp de %d (de) ore"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Nedefinit"</string>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 344e40832246..c12a0c8f6638 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Приложение сможет выполнять чтение и запись в файловую систему кеша."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"Входящие и исходящие вызовы SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Разрешить вызовы по протоколу SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"регистрация подключений"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Регистрация новых сетевых подключений."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"управление подключениями"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Управление сетевыми подключениями."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"Управление экраном во время разговора"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Управление экраном во время разговора."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"доступ к службам телефонии"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запрашивать пароль для отключения блокировки"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Чтобы продлить время работы устройства от батареи, в режиме энергосбережения снижается производительность, а также ограничивается использование вибросигнала и фоновой передачи данных. Данные, требующие синхронизации, могут обновляться только когда вы откроете приложение.\n\nРежим энергосбережения автоматически отключается во время зарядки устройства."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"До отключения режима (в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 мин."</item>
<item quantity="other" msgid="6924190729213550991">"%d мин."</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"1 ч."</item>
<item quantity="other" msgid="5408537517529822157">"%d ч."</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Бессрочно"</string>
</resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 5b54939115ae..b8042f7e7d12 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"හැඹිලි ගොනු පද්ධති කියවීමට සහ ලිවීමට යෙදුමට අවසර දෙන්න."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP ඇමතුම් සිදුකිරීමට/ලබාගැනීමට"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP ඇමතුම් සිදුකිරීමට සහ ලබාගැනීමට යෙදුමට ඉඩ දෙන්න."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"ලැබෙන ඇමතුම් තිරය සමග අන්තර් ක්‍රියාකාරී වන්න"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ලැබෙන ඇමතුම් තිරය පරිශීලකයාට පෙනෙන්නේ කෙදිනද සහ කෙසේද යැයි පාලනය කිරීමට යෙදුමට අවසර දෙන්න."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"දුරකථන සේවාවන් සමඟ සම්බන්ධ වීම"</string>
@@ -1774,6 +1782,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ගැලවීමට පෙර මුරපදය විමසන්න"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"බැටරියේ ජීව කාලය දියුණු කිරීමට උදව් කිරීමට, ඔබගේ උපාංගයේ ක්‍රියාකාරිත්වය සහ සීමා කළ කම්පනයන් සහ බොහොමයක් පසුබිම් දත්ත බැටරි සුරැකීමෙන් අඩු කරයි. සමමුහුර්ත කිරීම බලාපොරොත්තු වෙන ඊ-තැපෑල, පණිවිඩ යැවීම සහ වෙනත් යෙදුම් යාවත්කාලීන වන්නේ ඔබ ඒවා විවෘත කළ විට පමණි.\n\nඔබගේ උපාංගය ආරෝපණය වන විට බැටරි සුරැකීම ස්වයංක්‍රීයව අක්‍රිය වේ."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"ඔබගේ බිඳවැටුම් වේලාව <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> දී අවසන්වන තුරු"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"විනාඩි එකක් සඳහා"</item>
<item quantity="other" msgid="6924190729213550991">"විනාඩි %d සඳහා"</item>
@@ -1782,5 +1794,7 @@
<item quantity="one" msgid="3480040795582254384">"පැයක් සඳහා"</item>
<item quantity="other" msgid="5408537517529822157">"පැය %d ක් සඳහා"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"අනියත ආකාරයට"</string>
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 53d6aeaf96fc..2ac1c56632e3 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Umožňuje aplikácii čítať a zapisovať do súborového systému vyrovnávacej pamäte."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"uskutočňovanie/príjem hovorov SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Umožňuje aplikácii uskutočňovať a prijímať hovory SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registrácia nových pripojení telefonických sietí"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Povoľuje aplikácii registrovať nové pripojenia telekomunikačnej siete."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"správa pripojení telefonických sietí"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Povoľuje aplikácii spravovať pripojenia telekomunikačnej siete."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakcia s obrazovkou hovoru"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Umožňuje aplikácii ovládať, kedy a ako sa používateľovi zobrazí obrazovka hovoru."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"komunikovať s telefonickými službami"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred uvoľnením požiadať o heslo"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Na predĺženie výdrže batérie šetrič batérie znižuje výkonnosť zariadenia a obmedzuje vibrácie a prenos údajov na pozadí. E-mail, správy a ďalšie aplikácie, ktoré používajú synchronizáciu, sa možno nebudú aktualizovať, dokiaľ ich neotvoríte.\n\nPri nabíjaní zariadenia sa šetrič batérie automaticky vypne."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Dokým o <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> neskončí výpadok"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Na jednu minútu"</item>
<item quantity="other" msgid="6924190729213550991">"Na %d min"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Na 1 h"</item>
<item quantity="other" msgid="5408537517529822157">"Na %d h"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Natrvalo"</string>
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index b76757fdbcf3..fc7d93e045ee 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Aplikaciji omogoča branje in pisanje v datotečni sistem predpomnilnika."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"opravljanje/sprejemanje klicev SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Aplikaciji omogoča opravljanje in sprejemanje klicev SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registriranje nove telekomunikacijske povezave"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Aplikaciji omogoča registriranje novih telekomunikacijskih povezav."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"upravljanje telekomunikacijskih povezav"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Aplikaciji omogoča upravljanje telekomunikacijskih povezav."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interakcija z zaslonom pri klicu"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Aplikaciji omogoča nadzor nad tem, kdaj in kako uporabnik vidi zaslon pri klicu."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"uporaba telefonskih storitev"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pred odpenjanjem vprašaj za geslo"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Varčevanje z energijo akumulatorja poveča čas delovanja akumulatorja, tako da zmanjša zmogljivost delovanja naprave in omeji vibriranje ter prenos večine podatkov v ozadju. Aplikacije za e-pošto, sporočanje in drugo, ki uporabljajo sinhroniziranje, se morda ne posodabljajo, razen če jih odprete.\n\nVarčevanje z energijo se samodejno izklopi med polnjenjem akumulatorja naprave."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Do konca prekinitve delovanja ob <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Za eno minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Za %d min"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Za eno uro"</item>
<item quantity="other" msgid="5408537517529822157">"Za %d h"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Za nedoločen čas"</string>
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index de0f5b1dcbb3..4b44223fb0a2 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Дозвољава апликацији да чита систем датотека кеша и уписује податке у њега."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"упућивање/пријем SIP позива"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Омогућава апликацији да упућује и прима SIP позиве."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"регистровање нових веза са телекомуникационим мрежама"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Дозвољава апликацији да региструје нове везе са телекомуникационим мрежама."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"управљање везама са телекомуникационим мрежама"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Дозвољава апликацији да управља везама са телекомуникационим мрежама."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"комуницирај са екраном током позива"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Дозвољава апликацији да контролише када и како се кориснику приказује екран током позива."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"да ступа у интеракцију са телефонским услугама"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Тражи лозинку пре откачињања"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Да би смањила потрошњу батерије, Штедња батерије снижава перформансе уређаја, ограничава вибрацију и већину позадинских података. Имејл, размена порука и друге апликације које се ослањају на синхронизацију се можда неће ажурирати ако их не отворите.\n\nШтедња батерије се аутоматски искључује када се уређај пуни."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Док се прекид рада не заврши у <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Један минут"</item>
<item quantity="other" msgid="6924190729213550991">"%d мин"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Један сат"</item>
<item quantity="other" msgid="5408537517529822157">"%d с"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Бесконачно"</string>
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index d39a72275c63..90085291c8e3 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Tillåter att appen läser och skriver till cachefilsystemet."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"gör/ta emot SIP-anrop"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Tillåter att appen gör och tar emot SIP-anrop."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"registrera ny telekommunikationsanslutning"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Tillåter att appen registrerar nya telekommunikationsanslutningar."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"hantera telekommunikationsanslutningar"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Tillåter att appen hanterar telekommunikationsanslutningar."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"interagera med skärmen för inkommande samtal"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Tillåter att appen kontrollerar hur och när användaren ser skärmen för inkommande samtal."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"samverka med telefonitjänster"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Be om lösenord innan skärmen slutar fästas"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"I batterisparläget reduceras enhetens prestanda så att batteriet ska räcka längre, och vibration samt den mesta användningen av bakgrundsdata begränsas. Det kan hända att appar för e-post, sms och annat som kräver synkronisering inte uppdateras förrän du öppnar dem.\n\nBatterisparläget inaktiveras automatiskt när enheten laddas."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Tills avbrottstiden är slut <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"I en minut"</item>
<item quantity="other" msgid="6924190729213550991">"I %d minuter"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"I en timme"</item>
<item quantity="other" msgid="5408537517529822157">"I %d timmar"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"För alltid"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 00a45b457370..785f2ff1be52 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Huruhusu programu kusoma na kuandika mfumo wa faili wa akiba."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"piga/pokea simu za SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Ruhusu programu ipige na kupokea simu za SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"sajili muunganisho mpya wa mawasiliano ya simu"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Huruhusu programu kuandikisha miunganisho mipya ya mawasiliano ya simu."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"dhibiti miunganisho ya mawasiliano ya simu"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Huruhusu programu kudhibiti miunganisho ya mawasiliano ya simu."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"wezesha mwingiliano na skrini ya simu inayoingia"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Huruhusu programu kudhibiti wakati na jinsi mtumiaji anavyoona skrini ya simu inayoingia."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"shirikiana na huduma za simu"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Omba nenosiri kabla hujabandua"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Ili kusaidia kuokoa muda wa matumizi wa betri, kiokoa betri hupunguza utendaji wa kifaa chako na kuzuia kutetema na data nyingi ya chinichini. Barua pepe, kutuma ujumbe na programu zingine zinazotegemea usawazishaji huenda hazitasasisha usipozifungua.\n\nKiokoa betri hujizima kiotomatiki kifaa chako kikianza kuchajiwa."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Hadi <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> wakati wa kutotenda kazi kwa kifaa chako unapoisha"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Kwa dakika moja"</item>
<item quantity="other" msgid="6924190729213550991">"Kwa dakika %d"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Kwa saa moja"</item>
<item quantity="other" msgid="5408537517529822157">"Kwa saa %d"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Bila kikomo"</string>
</resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 821de0c79782..8bec63ad05ba 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"தற்காலிகச் சேமிப்பு கோப்பு அமைப்பைப் படிக்க மற்றும் எழுத, பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP அழைப்புகளைச் செய்தல்/பெறுதல்"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP அழைப்புகளைச் செய்ய/பெற, பயன்பாட்டை அனுமதிக்கிறது."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"புதிய தொலைத்தொடர்பு இணைப்பைப் பதிவுசெய்"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"புதிய தொலைத்தொடர்பு இணைப்புகளைப் பதிவுசெய்ய, பயன்பாட்டை அனுமதிக்கும்."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"தொலைத்தொடர்பு இணைப்புகளை நிர்வகி"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"தொலைத்தொடர்பு இணைப்புகளை நிர்வகிக்க, பயன்பாட்டை அனுமதிக்கும்."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"உள்வரும் அழைப்பிற்கான திரையுடன் ஊடாடுதல்"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"உள்வரும் அழைப்பிற்கான திரையைப் பயனர் எப்போது மற்றும் எப்படிக் காணவேண்டும் என்பதைக் கட்டுப்படுத்துவதற்குப் பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"டெலிஃபோனி சேவைகளுடனான ஊடாடல்"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"அகற்றும் முன் கடவுச்சொல்லைக் கேள்"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"பேட்டரியின் ஆயுட்காலத்தை அதிகரிக்க, பேட்டரி சேமிப்பான் சாதனத்தின் செயல்திறனைக் குறைத்து, அதிர்வுறுவதையும் பெரும்பாலான பின்புலத் தரவையும் வரம்பிடுகிறது. ஒத்திசைவைச் சார்ந்திருக்கும் மின்னஞ்சல், மெசேஜ், மேலும் பிற பயன்பாடுகளைத் திறக்கும் வரை, அவை புதுப்பிக்கப்படாமல் இருக்கலாம்.\n\nசாதனம் சார்ஜ் ஆகும் போது, பேட்டரி சேமிப்பான் தானாகவே முடக்கப்படும்."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> முடியும் வரை"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ஒரு நிமிடம்"</item>
<item quantity="other" msgid="6924190729213550991">"%d நிமிடங்கள்"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"ஒரு மணி நேரம்"</item>
<item quantity="other" msgid="5408537517529822157">"%d மணிநேரம்"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"வரையறையற்றது"</string>
</resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index ea1260f90a33..0219a9623b9b 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"కాష్ ఫైల్‌సిస్టమ్‌ను చదవడానికి మరియు వ్రాయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP కాల్‌లను చేయడానికి/స్వీకరించడానికి"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"SIP కాల్‌లను చేయడానికి మరియు స్వీకరించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"కొత్త టెలికామ్ కనెక్షన్‌లను నమోదు చేయడం"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"కొత్త టెలికామ్ కనెక్షన్‌లను నమోదు చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"టెలికామ్ కనెక్షన్‌లను నిర్వహించడం"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"టెలికామ్ కనెక్షన్‌లను నిర్వహించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"ఇన్-కాల్ స్క్రీన్‌తో పరస్పర చర్య చేయడం"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"వినియోగదారునికి ఇన్-కాల్ స్క్రీన్ ఎప్పుడు, ఎలా కనిపించాలనే దాన్ని నియంత్రించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"టెలిఫోన్ సేవలతో పరస్పర చర్య చేయడం"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"అన్‌పిన్ చేయడానికి ముందు పాస్‌వర్డ్ కోసం అడుగు"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"బ్యాటరీ సామర్థ్యాన్ని మెరుగుపరచడంలో సహాయపడటానికి, బ్యాటరీ సేవర్ మీ పరికరం పనితీరుని తగ్గిస్తుంది మరియు వైబ్రేషన్‌ను మరియు అత్యధిక నేపథ్య డేటాను పరిమితపరుస్తుంది. అలాగే సమకాలీకరణపై ఆధారపడే ఇమెయిల్, సందేశ సేవ మరియు ఇతర అనువర్తనాలు మీరు వాటిని తెరిస్తే మినహా నవీకరించబడకపోవచ్చు.\n\nమీ పరికరం ఛార్జింగ్‌లో ఉన్నప్పుడు బ్యాటరీ సేవర్ స్వయంచాలకంగా ఆఫ్ చేయబడుతుంది."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"మీ వృథా సమయం <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>కి ముగిసే వరకు"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ఒక నిమిషానికి"</item>
<item quantity="other" msgid="6924190729213550991">"%d నిమిషాలకి"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"ఒక గంటకు"</item>
<item quantity="other" msgid="5408537517529822157">"%d గంటలకు"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"నిరవధికంగా"</string>
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index e5a4e9c1caaa..fa6c0e83f632 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"อนุญาตให้แอปพลิเคชันอ่านและเขียนระบบไฟล์แคช"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"โทร/รับสาย SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"อนุญาตให้แอปโทรและรับสาย SIP"</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"ลงทะเบียนการเชื่อมต่อโทรคมนาคมใหม่"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"อนุญาตให้แอปลงทะเบียนการเชื่อมต่อโทรคมนาคมใหม่"</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"จัดการการเชื่อมต่อโทรคมนาคม"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"อนุญาตให้แอปจัดการการเชื่อมต่อโทรคมนาคม"</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"โต้ตอบกับหน้าจอขณะกำลังใช้สาย"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"อนุญาตให้แอปควบคุมเวลาและลักษณะที่ผู้ใช้เห็นหน้าจอขณะกำลังใช้สาย"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"โต้ตอบกับบริการโทรศัพท์"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ขอรหัสผ่านก่อนเลิกตรึง"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"เพื่อให้สามารถใช้แบตเตอรี่ได้ยาวนานขึ้น โหมดประหยัดแบตเตอรี่จะลดการทำงานของอุปกรณ์ และจำกัดการสั่นรวมถึงข้อมูลแบ็กกราวด์เกือบทั้งหมด อีเมล การรับส่งข้อความ และแอปอื่นๆ ที่ใช้การซิงค์อาจไม่อัปเดตจนกว่าคุณจะเปิดใช้\n\nโหมดประหยัดแบตเตอรี่จะปิดอัตโนมัติเมื่อชาร์จอุปกรณ์"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"จนกว่าจะสิ้นสุดช่วงเวลาที่เครื่องไม่ทำงานในเวลา <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 นาที"</item>
<item quantity="other" msgid="6924190729213550991">"%d นาที"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"1 ชั่วโมง"</item>
<item quantity="other" msgid="5408537517529822157">"%d ชั่วโมง"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"ไม่มีกำหนด"</string>
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 8360eb191849..41e271861eff 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Pinapayagan ang app na basahin at isulat ang cache filesystem."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"magsagawa/tumanggap ng mga tawag sa SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Pinapayagan ang app na magsagawa at makatanggap ng mga tawag sa SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"magrehistro ng bagong koneksyon sa telecom"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Pinapayagan ang app na magrehistro ng mga bagong koneksyon sa telecom."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"papamahalaan ang mga koneksyon sa telecom"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Pinapayagan ang app na mamahala ng mga koneksyon sa telecom."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"makipag-ugnayan sa in-call na screen"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Nagbibigay-daan sa app na kontrolin kung kailan at kung paano makikita ng user ang in-call na screen."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"makipag-ugnayan sa mga serbisyo sa telephony"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Humingi ng password bago mag-unpin"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Upang makatulong na mas mapatagal ang baterya, binabawasan ng battery saver ang pagganap ng iyong device at nililimitahan ang pag-vibrate at ang karamihan ng data ng background. Hindi maaaring ma-update ang email, pagmemensahe at iba pang mga app na umaasa sa pagsi-sync maliban kung bubuksan mo ang mga ito.\n\nAwtomatikong mao-off ang battery saver kapag nagcha-charge ang iyong device."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Hanggang sa matapos ang iyong downtime nang <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Sa loob ng isang minuto"</item>
<item quantity="other" msgid="6924190729213550991">"Sa loob ng %d (na) minuto"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Sa loob ng isang oras"</item>
<item quantity="other" msgid="5408537517529822157">"Sa loob ng %d (na) oras"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Walang tiyak na katapusan"</string>
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e6f78c6970aa..8ddc7f8ea11e 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Uygulamaya, önbellek dosya sisteminde okuma ve yazma yapma izni verir."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP çağrıları yapma/alma"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Uygulamanın SIP çağrıları yapmasına ve almasına izin verir."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"çağrı ekranıyla etkileşimde bulunma"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Uygulamaya, kullanıcının çağrı ekranını ne zaman ve nasıl göreceğini denetleme izni verir."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"telefon hizmetleriyle etkileşimde bulunma"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Sabitlemeyi kaldırmadan önce şifre sor"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Pil tasarrufu, pilin ömrünü uzatmaya yardımcı olmak amacıyla cihazınızın performansını düşürür ve arka plan verilerini sınırlar. E-posta, mesajlaşma ve senkronizasyona dayalı diğer uygulamalar siz açmadığınız müddetçe güncellenemez. \n\nPil tasarrufu, cihaz şarj olurken otomatik olarak kapanır."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Kesinti süreniz <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> saatinde sona erene kadar"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Bir dakika süreyle"</item>
<item quantity="other" msgid="6924190729213550991">"%d dakika süreyle"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"Bir saat süreyle"</item>
<item quantity="other" msgid="5408537517529822157">"%d saat süreyle"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Süresiz"</string>
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 925ec80192ef..ca66cbb9fd9f 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Дозволяє програмі читати з файлової системи кеш-пам’яті та писати в неї."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"здійснювати й отримувати дзвінки через протокол SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Додаток зможе здійснювати й отримувати дзвінки через протокол SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"реєстрація нових телекомунікаційних з’єднань"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Додаток може реєструвати нові телекомунікаційні з’єднання."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"керування телекомунікаційними з’єднаннями"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Додаток може керувати телекомунікаційними з’єднаннями."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"взаємодіяти з екраном вхідного дзвінка"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Додаток може контролювати, коли та як користувач бачить екран вхідного дзвінка."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"взаємодіяти з телефонними службами"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Запитувати пароль перед відкріпленням"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Щоб подовжити час роботи акумулятора, функція заощадження заряду акумулятора знизить продуктивність пристрою й обмежить вібрацію та більшість фонових даних. Електронна пошта, повідомлення й інші додатки, які синхронізуються, можуть не оновлюватися, доки ви їх не відкриєте.\n\nФункція заощадження заряду акумулятора автоматично вимкнеться, коли пристрій заряджатиметься."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Термін простою закінчується о <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Протягом хвилини"</item>
<item quantity="other" msgid="6924190729213550991">"Протягом %d хв"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Протягом години"</item>
<item quantity="other" msgid="5408537517529822157">"Протягом %d год"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Без обмежень"</string>
</resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index ddfd85d6752c..faeab4d54b1b 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"ایپ کو کیش فائل سسٹم پڑھنے اور لکھنے کی اجازت دیتا ہے۔"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"‏SIP کالز کریں/موصول کریں"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"‏ایپ کو SIP کالز کرنے اور موصول کرنے کی اجازت دیتا ہے۔"</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"درون کال اسکرین کے ساتھ تعامل کریں"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"ایپ کو صارف کے درون کال اسکرین دیکھنے کے وقت اور طریقے کو کنٹرول کرنے کی اجازت دیتا ہے۔"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"ٹیلیفونی سروسز کے ساتھ تعامل کریں"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"پن ہٹانے سے پہلے پاس ورڈ طلب کریں"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"بیٹری کی میعاد بہتر بنانے میں مدد کرنے کیلئے، بیٹری سیور آپ کے آلہ کی کارکردگی میں تخفیف کر دیتی ہے اور وائبریشن اور پس منظر کے زیادہ تر ڈیٹا کو محدود کر دیتی ہے۔ ای میل، پیغام رسانی اور مطابقت پذیری پر انحصار کرنے والی دیگر ایپس ممکن ہے اس وقت تک اپ ڈیٹ نہ ہوں جب تک آپ انہیں نہ کھولیں۔\n\nآپ کا آلہ چارج ہوتے وقت بیٹری سیور خود بخود آف ہو جاتی ہے۔"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> پر آپ کا آخری وقت ختم ہونے تک"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"ایک منٹ کیلئے"</item>
<item quantity="other" msgid="6924190729213550991">"‏%d منٹ کیلئے"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"ایک گھنٹے کیلئے"</item>
<item quantity="other" msgid="5408537517529822157">"‏%d گھنٹوں کیلئے"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"غیر متعینہ"</string>
</resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 6d6f36e9d966..cf426e2ed1bd 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ilova kesh fayl tizimini o‘qishi va unga yozishi mumkin."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"SIP qo‘ng‘iroqlarini amalga oshirish/qabul qilish"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Ilovaga SIP qo‘ng‘iroqlarini amalga oshirish va qabul qilish uchun ruxsat beradi."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"suhbat vaqtida ekranni boshqarish"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Ilova suhbat vaqtida ekranni boshqarishi mumkin."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"telefoniya xizmatlarini bilan aloqa qilish"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Bo‘shatishdan oldin parol so‘ralsin"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Batareya quvvatini uzoqroq vaqtga yetkazish uchun quvvat tejash funksiyasi qurilmangiz unumdorligini kamaytiradi hamda uning tebranishi va orqa fonda internetdan foydalanishni cheklaydi. Sinxronlanib turishi lozim bo‘lgan e-pochta, xabar almashinuv va boshqa ilovalar esa ishga tushirilmaguncha yangilanmaydi.\n\nQurilmani quvvat oldirish uchun energiya manbayiga ulashingiz bilanoq, quvvat tejash funksiyasi avtomatik tarzda o‘chadi."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Tanaffus vaqti tugaguncha – <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 daqiqa"</item>
<item quantity="other" msgid="6924190729213550991">"%d daqiqa"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"1 soat"</item>
<item quantity="other" msgid="5408537517529822157">"%d soat"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Uzluksiz ravishda"</string>
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index f56f8e702337..5acd5bbec711 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -494,7 +494,7 @@
<string name="permlab_writeProfile" msgid="907793628777397643">"sửa đổi thẻ liên hệ của riêng bạn"</string>
<string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Cho phép ứng dụng thay đổi hoặc thêm vào thông tin tiểu sử cá nhân được lưu trữ trên thiết bị, chẳng hạn như tên và thông tin liên hệ của bạn. Điều này có nghĩa là ứng dụng có thể xác định danh tính của bạn và gửi thông tin tiểu sử của bạn cho người khác."</string>
<string name="permlab_bodySensors" msgid="4871091374767171066">"cảm biến cơ thể (như máy đo nhịp tim)"</string>
- <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Cho phép ứng dụng truy cập dữ liệu từ bộ cảm biến giám sát tình trạng thể chất của bạn, ví dụ như nhịp tim."</string>
+ <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Cho phép ứng dụng truy cập dữ liệu từ bộ cảm biến giám sát tình trạng sức khỏe của bạn, ví dụ như nhịp tim."</string>
<string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"đọc luồng xã hội của bạn"</string>
<string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Cho phép ứng dụng truy cập và đồng bộ hóa các cập nhật xã hội của bạn và bạn bè bạn. Hãy cẩn trọng khi chia sẻ thông tin -- việc này có thể cho phép ứng dụng đọc thông tin liên lạc giữa bạn và bạn bè bạn trên các mạng xã hội, bất kể tính bí mật là gì. Lưu ý: quyền này có thể không được thực thi trên tất cả các mạng xã hội."</string>
<string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ghi luồng xã hội của bạn"</string>
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Cho phép ứng dụng đọc và ghi hệ thống tệp bộ nhớ cache."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"thực hiện/nhận các cuộc gọi qua SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Cho phép ứng dụng thực hiện và nhận các cuộc gọi qua SIP."</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"tương tác với màn hình trong cuộc gọi"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Cho phép ứng dụng kiểm soát thời gian và cách người dùng nhìn thấy màn hình trong cuộc gọi."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"tương tác với dịch vụ điện thoại"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Hỏi mật khẩu trước khi bỏ ghim"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Để giúp tăng tuổi thọ pin, trình tiết kiệm pin sẽ giảm hiệu suất thiết bị của bạn và hạn chế chế rung và hầu hết dữ liệu nền. Email, nhắn tin và các ứng dụng khác dựa trên đồng bộ hóa không thể cập nhật trừ khi bạn mở chúng.\n\nTrình tiết kiệm pin tự động tắt khi thiết bị của bạn đang sạc."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Cho tới khi thời gian ngừng hoạt động của bạn kết thúc vào <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Trong một phút"</item>
<item quantity="other" msgid="6924190729213550991">"Trong %d phút"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"Trong một giờ"</item>
<item quantity="other" msgid="5408537517529822157">"Trong %d giờ"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Không giới hạn"</string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 82c9fe1c2dd8..f32c8c096761 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允许应用读取和写入缓存文件系统。"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"拨打/接听SIP电话"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"允许该应用拨打和接听SIP电话。"</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"与通话屏幕互动"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"允许应用控制用户看到通话屏幕的时机和方式。"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"与电话服务交互"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消时要求输入密码"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"为了延长电池的续航时间,节电助手会降低设备的性能,并限制振动和大部分后台流量。对于电子邮件、聊天工具等依赖于同步功能的应用,可能要打开这类应用时才能收到新信息。\n\n节电助手会在设备充电时自动关闭。"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"直到休息时间结束(<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1分钟"</item>
<item quantity="other" msgid="6924190729213550991">"%d分钟"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"1小时"</item>
<item quantity="other" msgid="5408537517529822157">"%d小时"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"无限期"</string>
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 880380ad2684..59ff983b3ba2 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允許應用程式讀取及寫入快取檔案系統。"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"撥打/接聽 SIP 電話"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"允許應用程式撥打及接聽 SIP 電話。"</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"與通話畫面互動"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"允許應用程式控制通話畫面的顯示時間和方式。"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"與電話語音服務互動"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"省電模式可延長電池使用時間,但會降低裝置的效能,並限制震動和大部分背景數據傳輸。電郵、短訊及其他需要同步處理的應用程式可能只會在開啟時才會更新。\n\n裝置充電時,省電模式會自動關閉。"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"直到停機時間於 <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> 結束"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 分鐘"</item>
<item quantity="other" msgid="6924190729213550991">"%d 分鐘"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"1 小時"</item>
<item quantity="other" msgid="5408537517529822157">"%d 小時"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"無限期"</string>
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 70cb87e2b859..1848795b73dd 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -716,6 +716,14 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"允許應用程式讀取及寫入快取檔案系統。"</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"撥打/接聽 SIP 通話"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"允許應用程式撥打及接聽 SIP 通話。"</string>
+ <!-- no translation found for permlab_register_provider (2654513709546459553) -->
+ <skip />
+ <!-- no translation found for permdesc_register_provider (7571533832018681544) -->
+ <skip />
+ <!-- no translation found for permlab_connection_manager (1116193254522105375) -->
+ <skip />
+ <!-- no translation found for permdesc_connection_manager (5925480810356483565) -->
+ <skip />
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"與通話螢幕互動"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"允許應用程式控制使用者看到通話螢幕的時機和方式。"</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"與電話語音服務互動"</string>
@@ -1772,6 +1780,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消固定時必須輸入密碼"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"節約耗電量功能會降低裝置的效能,並限制震動和大多數背景資料,藉此延長電池續航力。此外,電子郵件、簡訊和其他需要使用同步功能的應用程式若未開啟,將不會自動更新。\n\n當您為裝置充電時,節約耗電量功能會自動關閉。"</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"直到 <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> 停機時間結束"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 分鐘"</item>
<item quantity="other" msgid="6924190729213550991">"%d 分鐘"</item>
@@ -1780,5 +1792,7 @@
<item quantity="one" msgid="3480040795582254384">"1 小時"</item>
<item quantity="other" msgid="5408537517529822157">"%d 小時"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"無限期"</string>
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 65bd617fa9ab..10d558f4853d 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -716,6 +716,10 @@
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Ivumela uhlelo lokusebenza ukuthi ifunde futhi ibhale isistimu yokufayila amafayela esikhashana."</string>
<string name="permlab_use_sip" msgid="2052499390128979920">"yenza/thola amakholi we-SIP"</string>
<string name="permdesc_use_sip" msgid="2297804849860225257">"Ivumela uhlelo lokusebenza ukwenza nokuthola amakholi we-SIP."</string>
+ <string name="permlab_register_provider" msgid="2654513709546459553">"bhalisa ukuxhumana kwezokuxhumana kwefoni okusha"</string>
+ <string name="permdesc_register_provider" msgid="7571533832018681544">"Ivumela uhlelo lokusebenza ukuthi lubhalise ukuxhumana kwezokuxhumana kwefoni okusha."</string>
+ <string name="permlab_connection_manager" msgid="1116193254522105375">"phatha ukuxhumana kwezokuxhumana kwefoni"</string>
+ <string name="permdesc_connection_manager" msgid="5925480810356483565">"Ivumela uhlelo lokusebenza ukuthi luphathe ukuxhumana kwezokuxhumana kwefoni."</string>
<string name="permlab_bind_incall_service" msgid="6773648341975287125">"hlanganyela neskrini esingaphakathi kwekholi"</string>
<string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Ivumela uhlelo lokusebenza ukuthi lulawule ukuthi umsebenzisi ubona kanjani isikrini esingaphakathi kwekholi."</string>
<string name="permlab_bind_connection_service" msgid="3557341439297014940">"sebenzisana namasevisi wefoni"</string>
@@ -1772,6 +1776,10 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Cela iphasiwedi ngaphambi kokususa ukuphina"</string>
<string name="battery_saver_description" msgid="2510530476513605742">"Ukuze usize ukwenza kangcono impilo yebhethri, isilondolozi sebhethri sehlisa ukusebenza kwedivayisi yakho futhi sikhawulela ukudlidliza nedatha eningi yangasemuva. I-imeyili, imilayezo, nezinye izinhlelo zokusebenza ezincike ekuvumelaniseni kungenzeka zingabuyekezi ngaphandle kokuthi uzivule.\n\nIsilondolozi sebhethri sivaleka ngokuzenzakalelayo uma idivayisi yakho ishaja."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Kuze kuphele isikhathi sakho ngo-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for zen_mode_duration_minutes_summary:one (3177683545388923234) -->
+ <!-- no translation found for zen_mode_duration_minutes_summary:other (2787867221129368935) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:one (597194865053253679) -->
+ <!-- no translation found for zen_mode_duration_hours_summary:other (2827214920627669898) -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"Iminithi elilodwa"</item>
<item quantity="other" msgid="6924190729213550991">"Amaminithi angu-%d"</item>
@@ -1780,5 +1788,7 @@
<item quantity="one" msgid="3480040795582254384">"Ihora elilodwa"</item>
<item quantity="other" msgid="5408537517529822157">"Amahora angu-%d"</item>
</plurals>
+ <!-- no translation found for zen_mode_until (7336308492289875088) -->
+ <skip />
<string name="zen_mode_forever" msgid="4316804956488785559">"Unaphakade"</string>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 7b4df49390e0..91a8598b6cea 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2363,6 +2363,18 @@
representation this attribute can be used for providing such. -->
<attr name="contentDescription" format="string" localization="suggested" />
+ <!-- Sets the id of a view before which this one is visited in accessibility traversal.
+ A screen-reader must visit the content of this view before the content of the one
+ it precedes.
+ @see android.view.View#setAccessibilityTraversalBefore(int)} -->
+ <attr name="accessibilityTraversalBefore" format="integer" />
+
+ <!-- Sets the id of a view after which this one is visited in accessibility traversal.
+ A screen-reader must visit the content of the other view before the content of
+ this one.
+ @see android.view.View#setAccessibilityTraversalAfter(int)} -->
+ <attr name="accessibilityTraversalAfter" format="integer" />
+
<!-- Name of the method in this View's context to invoke when the view is
clicked. This name must correspond to a public method that takes
exactly one parameter of type View. For instance, if you specify
@@ -7460,7 +7472,10 @@
<!-- Push object to the bottom of its container, not changing its size. -->
<flag name="bottom" value="0x50" />
</attr>
+ <!-- Icon drawable to use for the collapse button. -->
<attr name="collapseIcon" format="reference" />
+ <!-- Text to set as the content description for the collapse button. -->
+ <attr name="collapseContentDescription" format="string" />
<!-- Reference to a theme that should be used to inflate popups
shown by widgets in the toolbar. -->
<attr name="popupTheme" format="reference" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9332105d76d7..1534b49b1e51 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -586,6 +586,7 @@
0 - Nothing
1 - Global actions menu
2 - Power off (with confirmation)
+ 3 - Power off (without confirmation)
-->
<integer name="config_longPressOnPowerBehavior">1</integer>
@@ -597,6 +598,20 @@
-->
<integer name="config_shortPressOnPowerBehavior">1</integer>
+ <!-- Control the behavior when the user double presses the power button.
+ 0 - Nothing
+ 1 - Toggle theater mode setting
+ 2 - Brightness boost
+ -->
+ <integer name="config_doublePressOnPowerBehavior">0</integer>
+
+ <!-- Control the behavior when the user triple presses the power button.
+ 0 - Nothing
+ 1 - Toggle theater mode setting
+ 2 - Brightness boost
+ -->
+ <integer name="config_triplePressOnPowerBehavior">0</integer>
+
<!-- Package name for default keyguard appwidget [DO NOT TRANSLATE] -->
<string name="widget_default_package_name"></string>
@@ -1885,4 +1900,11 @@
<bool name="config_switch_phone_on_voice_reg_state_change">true</bool>
<bool name="config_sms_force_7bit_encoding">false</bool>
+
+ <!-- Flag indicating whether strict threshold is used, or lenient threshold is used,
+ when evaluating RSRP for LTE antenna bar display
+ 0. Strict threshold
+ 1. Lenient threshold
+ -->
+ <integer name="config_LTE_RSRP_threshold_type">1</integer>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 45208ab6b4d5..c0a5ab26ad66 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2589,6 +2589,15 @@
<!-- @hide -->
<public-padding type="attr" name="private_resource_pad" end="0x01010500" />
+
+ <!-- ===============================================================
+ Resources added in version 22 of the platform
+ =============================================================== -->
+ <eat-comment />
+
<public type="attr" name="resizeClip"/>
+ <public type="attr" name="collapseContentDescription"/>
+ <public type="attr" name="accessibilityTraversalBefore" />
+ <public type="attr" name="accessibilityTraversalAfter" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 99d15cccf7a9..61fc16188e75 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2115,9 +2115,14 @@
<string name="permdesc_use_sip">Allows the app to make and receive SIP calls.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_register_provider">register new telecom connection</string>
+ <string name="permlab_register_sim_subscription">register new telecom SIM connections</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_register_provider">Allows the app to register new telecom connections.</string>
+ <string name="permdesc_register_sim_subscription">Allows the app to register new telecom SIM connections.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_register_call_provider">register new telecom connections</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_register_call_provider">Allows the app to register new telecom connections.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_connection_manager">manage telecom connections</string>
@@ -3509,6 +3514,9 @@
<!-- [CHAR LIMIT=40] Title of dialog that is shown when performing a system upgrade. -->
<string name="android_upgrading_title">Android is upgrading\u2026</string>
+ <!-- [CHAR LIMIT=40] Title of dialog that is shown when system is starting. -->
+ <string name="android_start_title">Android is starting\u2026</string>
+
<!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog for each .apk that is optimized. -->
<string name="android_upgrading_apk">Optimizing app
<xliff:g id="number" example="123">%1$d</xliff:g> of
@@ -4902,4 +4910,7 @@
<!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
<string name="zen_mode_forever">Indefinitely</string>
+
+ <!-- Content description for the Toolbar icon used to collapse an expanded action mode. [CHAR LIMIT=NONE] -->
+ <string name="toolbar_collapse_description">Collapse</string>
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index ba15e9cc28c0..dd871399b6fc 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1218,6 +1218,7 @@ please see styles_device_defaults.xml.
<item name="buttonGravity">top</item>
<item name="navigationButtonStyle">@style/Widget.Toolbar.Button.Navigation</item>
<item name="collapseIcon">?attr/homeAsUpIndicator</item>
+ <item name="collapseContentDescription">@string/toolbar_collapse_description</item>
<item name="contentInsetStart">16dp</item>
<item name="touchscreenBlocksFocus">true</item>
</style>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 6e03b3d2696c..cc3ded505079 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -1091,16 +1091,16 @@ please see styles_device_defaults.xml.
<!-- Dialog styles -->
<style name="AlertDialog.Material" parent="AlertDialog">
- <item name="fullDark">@null</item>
- <item name="topDark">@null</item>
- <item name="centerDark">@null</item>
- <item name="bottomDark">@null</item>
- <item name="fullBright">@null</item>
- <item name="topBright">@null</item>
- <item name="centerBright">@null</item>
- <item name="bottomBright">@null</item>
- <item name="bottomMedium">@null</item>
- <item name="centerMedium">@null</item>
+ <item name="fullDark">@empty</item>
+ <item name="topDark">@empty</item>
+ <item name="centerDark">@empty</item>
+ <item name="bottomDark">@empty</item>
+ <item name="fullBright">@empty</item>
+ <item name="topBright">@empty</item>
+ <item name="centerBright">@empty</item>
+ <item name="bottomBright">@empty</item>
+ <item name="bottomMedium">@empty</item>
+ <item name="centerMedium">@empty</item>
<item name="layout">@layout/alert_dialog_material</item>
<item name="listLayout">@layout/select_dialog_material</item>
<item name="progressLayout">@layout/progress_dialog_material</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d86413f88877..3835d8bb1025 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -340,6 +340,7 @@
<java-symbol type="integer" name="config_bluetooth_max_advertisers" />
<java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
<java-symbol type="integer" name="config_cursorWindowSize" />
+ <java-symbol type="integer" name="config_doublePressOnPowerBehavior" />
<java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
<java-symbol type="integer" name="config_extraFreeKbytesAbsolute" />
<java-symbol type="integer" name="config_immersive_mode_confirmation_panic" />
@@ -354,6 +355,7 @@
<java-symbol type="integer" name="config_ntpTimeout" />
<java-symbol type="integer" name="config_shortPressOnPowerBehavior" />
<java-symbol type="integer" name="config_toastDefaultGravity" />
+ <java-symbol type="integer" name="config_triplePressOnPowerBehavior" />
<java-symbol type="integer" name="config_wifi_framework_scan_interval" />
<java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
<java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
@@ -1491,6 +1493,7 @@
<java-symbol type="layout" name="screen_title" />
<java-symbol type="layout" name="screen_title_icons" />
<java-symbol type="string" name="system_ui_date_pattern" />
+ <java-symbol type="string" name="android_start_title" />
<java-symbol type="string" name="android_upgrading_title" />
<java-symbol type="string" name="bugreport_title" />
<java-symbol type="string" name="bugreport_message" />
@@ -2090,7 +2093,10 @@
<java-symbol type="bool" name="config_switch_phone_on_voice_reg_state_change" />
<java-symbol type="string" name="whichHomeApplicationNamed" />
<java-symbol type="bool" name="config_sms_force_7bit_encoding" />
-
- <!-- From MSIM Account -->
<java-symbol type="layout" name="simple_account_item" />
+ <java-symbol type="id" name="scrollIndicatorUp" />
+ <java-symbol type="id" name="scrollIndicatorDown" />
+
+ <!-- From SignalStrength -->
+ <java-symbol type="integer" name="config_LTE_RSRP_threshold_type" />
</resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 1864f8962700..5640fc1b7ee1 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1019,10 +1019,10 @@ please see themes_device_defaults.xml.
<item name="textAppearance">@style/TextAppearance.Material</item>
<item name="textAppearanceInverse">@style/TextAppearance.Material.Inverse</item>
- <item name="listPreferredItemPaddingLeft">16dip</item>
- <item name="listPreferredItemPaddingRight">16dip</item>
- <item name="listPreferredItemPaddingStart">16dip</item>
- <item name="listPreferredItemPaddingEnd">16dip</item>
+ <item name="listPreferredItemPaddingLeft">24dip</item>
+ <item name="listPreferredItemPaddingRight">24dip</item>
+ <item name="listPreferredItemPaddingStart">24dip</item>
+ <item name="listPreferredItemPaddingEnd">24dip</item>
<item name="listDivider">@null</item>
@@ -1135,10 +1135,10 @@ please see themes_device_defaults.xml.
<item name="textAppearance">@style/TextAppearance.Material</item>
<item name="textAppearanceInverse">@style/TextAppearance.Material.Inverse</item>
- <item name="listPreferredItemPaddingLeft">16dip</item>
- <item name="listPreferredItemPaddingRight">16dip</item>
- <item name="listPreferredItemPaddingStart">16dip</item>
- <item name="listPreferredItemPaddingEnd">16dip</item>
+ <item name="listPreferredItemPaddingLeft">24dip</item>
+ <item name="listPreferredItemPaddingRight">24dip</item>
+ <item name="listPreferredItemPaddingStart">24dip</item>
+ <item name="listPreferredItemPaddingEnd">24dip</item>
<item name="listDivider">@null</item>
diff --git a/docs/html/design/wear/patterns.jd b/docs/html/design/wear/patterns.jd
index 30fdc2443e82..e56ac2db8a72 100644
--- a/docs/html/design/wear/patterns.jd
+++ b/docs/html/design/wear/patterns.jd
@@ -76,6 +76,13 @@ page.title=UI Patterns for Android Wear
<li>The cue card can be invoked to continue specifying the action. For example in a messaging application, tapping a “Reply” action button invokes the Cue Card and prompts for voice input. In this case the prompt label (such as “Speak your message…”) and a set of sample voice suggestions can be specified by developers.</li>
</ol>
+<a class="notice-developers left" href="{@docRoot}training/wearables/ui/confirm.html">
+ <div>
+ <h3>Developer Docs</h3>
+ <p>Showing Confirmations</p>
+ </div>
+</a>
+
<h2 id="Continuing" style="clear:both">Continuing activities on phone</h2>
@@ -100,6 +107,13 @@ page.title=UI Patterns for Android Wear
<p>Good examples of using an action on card include: play and pause music, toggle light switch on and off, navigate to an address, and call a phone number.</p>
+<a class="notice-developers left" href="{@docRoot}training/wearables/ui/cards.html">
+ <div>
+ <h3>Developer Docs</h3>
+ <p>Creating Cards</p>
+ </div>
+</a>
+
<h2 id="Stacks" style="clear:both">Card stacks</h2>
<img src="{@docRoot}design/media/wear/expandable_stacks.png" width="147" height="147" style="float:right;margin:0 0 20px 40px">
@@ -124,6 +138,13 @@ to check-in to.</p>
<p>More information about how to use the 2D Picker pattern is provided in the <a href="{@docRoot}design/wear/structure.html#2DPicker">App Structure</a> guide.</p>
+<a class="notice-developers left" href="{@docRoot}training/wearables/ui/2d-picker.html">
+ <div>
+ <h3>Developer Docs</h3>
+ <p>Creating a 2D Picker</p>
+ </div>
+</a>
+
<h2 id="Voice" style="clear:both">Voice commands</h2>
@@ -148,3 +169,10 @@ href="{@docRoot}training/wearables/apps/layouts.html#UiLibrary"><code>WearableLi
<p>Of course, it is possible for Android Wear apps to extend themselves beyond the familiarities of these patterns. For a deeper look at the options available, see the <a href="{@docRoot}design/wear/structure.html">App Structure</a> guide.</p>
+
+<a class="notice-developers left" href="{@docRoot}training/wearables/ui/lists.html">
+ <div>
+ <h3>Developer Docs</h3>
+ <p>Creating Lists</p>
+ </div>
+</a>
diff --git a/docs/html/design/wear/structure.jd b/docs/html/design/wear/structure.jd
index b77ccc23b69e..95d5c1aeecca 100644
--- a/docs/html/design/wear/structure.jd
+++ b/docs/html/design/wear/structure.jd
@@ -84,12 +84,18 @@ margin: 0 10px 20px 20px;
<img src="{@docRoot}design/media/wear/1D_picker.png" alt="" width="499px" />
<p class="img-caption">This pattern can be used to present a single vertical list, or a “1D Picker”</p>
-<img src="{@docRoot}design/media/wear/2D_picker.png" alt="" width:760px" />
+<img src="{@docRoot}design/media/wear/2D_picker.png" alt="" width="760px" />
<p class="img-caption">It can also be used as a 2D matrix of options, as a way of presenting categorized options.</p>
<h3>Actions</h3>
+<a class="notice-developers" style="clear:none" href="{@docRoot}training/wearables/ui/2d-picker.html">
+ <div>
+ <h3>Developer Docs</h3>
+ <p>Creating a 2D Picker</p>
+ </div>
+</a>
<p>For actions on each card, use the <a href="{@docRoot}design/wear/patterns.html#Actions">Action cards pattern</a>.</p>
<h3>Making it fast</h3>
@@ -155,6 +161,6 @@ href="#2DPicker">2D picker</a> is always available.</p>
<h3>Manually exiting</h3>
<p>Even with logical exit points like these, some cases may exist where the user may want to immediately exit. This may be common in apps that are used for a longer while. In all cases, you should treat long-press as the user's intent to exit, using
-<a href="{@docRoot}training/wearables/apps/layouts.html#UiLibrary"><code>DismissOverlayView</code></a>.</p>
+<a href="{@docRoot}training/wearables/ui/exit.html"><code>DismissOverlayView</code></a>.</p>
diff --git a/docs/html/distribute/tools/promote/badges.jd b/docs/html/distribute/tools/promote/badges.jd
index 4bea8beceecb..eb09333e0582 100644
--- a/docs/html/distribute/tools/promote/badges.jd
+++ b/docs/html/distribute/tools/promote/badges.jd
@@ -66,7 +66,7 @@ div.button-row input {
var APP_LANGS = ['it','pt-br','pt-pt','nl','ko','ja','fr','es','es-419','en','de'];
// variables for creating 'try it out' demo button
-var imagePath = "{@docRoot}images/brand/"
+var imagePath = "https://developer.android.com/images/brand/"
var linkStart = "<a href=\"https://play.google.com/store/";
var imageStart = "\">\n"
+ " <img alt=\"";
@@ -99,7 +99,7 @@ function buildButton(form) {
$("#button-preview").html(linkStart + "apps/details?id=" + packageName
+ imageStart + altText + imageSrc
+ selectedValue + imageEnd);
-
+
// Send the event to Analytics
ga('send', 'event', 'Distribute', 'Create Google Play Badge', 'Package ' + selectedValue);
} else if (form["publisher"].value != "Example, Inc.") {
@@ -111,7 +111,7 @@ function buildButton(form) {
$("#button-preview").html(linkStart + "search?q=pub:" + publisherName
+ imageStart + altText + imageSrc
+ selectedValue + imageEnd);
-
+
// Send the event to Analytics
ga('send', 'event', 'Distribute', 'Create Google Play Badge', 'Publisher ' + selectedValue);
} else {
@@ -159,7 +159,7 @@ function clearLabel(id, example) {
/** Switch the badge urls for selected language */
function changeBadgeLang() {
var lang = $('#locale option:selected').val();
-
+
// check if we have the 'app' badge for this lang and show notice if not
$("div.button-row.error").remove(); // remove any existing instance of error message
if ($.inArray(lang,APP_LANGS) == -1) {
@@ -173,7 +173,7 @@ function changeBadgeLang() {
} else {
$("div.button-row.app").show(); // show the 'app' badge row
}
-
+
$('.button-row img').each(function() {
var id = $(this).parent().attr('for');
var imgName = lang + $('input#'+id).attr('value') + '.png';
@@ -356,7 +356,7 @@ alt="Get it on Google Play (large)" /></label>
style="font-family:monospace;background-color:#efefef;padding:5px;display:none;margin-bottom:1em">
</textarea >
-<p>Try it out:</p>
+<p>Test your badge:</p>
<div id="button-preview" style="margin-top:1em"></div>
</div>
diff --git a/docs/html/google/gcm/adv.jd b/docs/html/google/gcm/adv.jd
index 245467f51f18..95497e3049b5 100644
--- a/docs/html/google/gcm/adv.jd
+++ b/docs/html/google/gcm/adv.jd
@@ -261,7 +261,7 @@ is either a &quot;send-to-sync&quot; (collapsible) message or a &quot;message wi
payload&quot; (non-collapsible message). These concepts are described in more
detail in the following sections.</p>
-<h3 id="s2s"><strong>Send-to-sync messages</strong></h3>
+<h3 id="s2s">Send-to-sync messages</h3>
<p>A send-to-sync (collapsible) message is often a &quot;tickle&quot; that tells
a mobile application to sync data from the server. For example, suppose you have
@@ -288,6 +288,7 @@ and B4, and so on. If you exceed this number GCM will only keep 4 collapse keys,
guarantees about which ones they will be.</p>
<h3 id="payload">Messages with payload</h3>
+
<p>Unlike a send-to-sync message, every &quot;message with payload&quot;
(non-collapsible message) is delivered. The payload the message contains can be
up to 4kb. For example, here is a JSON-formatted message in an IM application in
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index 2faf97f3829d..7db7a74c8abf 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -21,7 +21,7 @@ page.title=GCM Cloud Connection Server (XMPP)
</li>
<li><a href="#upstream">Upstream Messages</a>
<ol>
- <li><a href="#receipts">Receive return receipts</a></li>
+ <li><a href="#receipts">Receive delivery receipts</a></li>
</ol>
</li>
<li><a href="#flow">Flow Control</a> </li>
@@ -45,11 +45,15 @@ page.title=GCM Cloud Connection Server (XMPP)
</div>
</div>
-<p>The GCM Cloud Connection Server (CCS) is an XMPP endpoint that provides a
+<p>The Google Cloud Messaging (GCM) Cloud Connection Server (CCS) is an XMPP endpoint that provides a
persistent, asynchronous, bidirectional connection to Google servers. The
connection can be used to send and receive messages between your server and
your users' GCM-connected devices.</p>
+<p class="note"><strong>Note:</strong> The content in this document
+applies to <a href="http://developer.chrome.com/apps/cloudMessaging">
+GCM with Chrome apps</a> as well as Android.
+
<p>You can continue to use the HTTP request mechanism to send messages to GCM
servers, side-by-side with CCS which uses XMPP. Some of the benefits of CCS include:</p>
@@ -259,22 +263,6 @@ message is &quot;nack&quot;. A NACK message contains:</p>
&lt;/message&gt;
</pre>
-<p>Quota exceeded:</p>
-
-<pre>&lt;message&gt;
- &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
- {
- &quot;message_type&quot;:&quot;nack&quot;,
- &quot;message_id&quot;:&quot;msgId1&quot;,
- &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
- &quot;error&quot;:&quot;QUOTA_EXCEEDED&quot;,
- &quot;error_description&quot;:&quot;Short-term downstream quota exceeded for this registration id&quot;
- }
- &lt;/gcm&gt;
-&lt;/message&gt;
-</pre>
-
-
<p>The following table lists NACK error codes. Unless otherwise
indicated, a NACKed message should not be retried. Unexpected NACK error codes
should be treated the same as {@code INTERNAL_SERVER_ERROR}.</p>
@@ -312,11 +300,11 @@ message should be immediately retried over another connection.</td>
<td>{@code INVALID_JSON}</td>
<td>The JSON message payload is not valid.</td>
</tr>
-<tr>
-<td>{@code QUOTA_EXCEEDED}</td>
-<td>The rate of messages to a particular registration ID (in other words, to a
-sender/device pair) is too high. If you want to retry the message, try using a slower
-rate.</td>
+<td>{@code DEVICE_MESSAGE_RATE_EXCEEDED}</td>
+<td>The rate of messages to a particular device is too high. You should reduce
+the number of messages sent to this device and should not immediately retry
+sending to this device. This error code replaces {@code QUOTA_EXCEEDED},
+which has been deprecated.</td>
</tr>
<tr>
<td>{@code SERVICE_UNAVAILABLE}</td>
@@ -429,15 +417,17 @@ response to the above message:</p>
&lt;/gcm&gt;
&lt;/message&gt;</pre>
-<h3 id="receipts">Receive return receipts</h3>
+<h3 id="receipts">Receive delivery receipts</h3>
-<p>You can use upstream messaging to get receipt notifications, confirming
-that a given message was sent to a device. Your 3rd-party app server receives the receipt
-notification from CCS once the message has been sent to the device.</p>
+<p>You can use upstream messaging to get delivery receipts (sent from CCS to
+your 3rd party app server) when
+a device confirms that it received a message sent by CCS.</p>
<p>To enable this feature, the message your 3rd-party app server sends to CCS must include
a field called <code>&quot;delivery_receipt_requested&quot;</code>. When this field is set to
-<code>true</code>, CCS sends a return receipt. Here is an XMPP stanza containing a JSON
+<code>true</code>, CCS sends a delivery receipt when a device confirms that it received a particular message.</p>
+
+<p>Here is an XMPP stanza containing a JSON
message with <code>&quot;delivery_receipt_requested&quot;</code> set to <code>true</code>:</p>
<pre>&lt;message id=&quot;&quot;&gt;
@@ -457,8 +447,10 @@ message with <code>&quot;delivery_receipt_requested&quot;</code> set to <code>tr
&lt;/message&gt;
</pre>
-<p>Here is an example of a receipt notification message that CCS sends back to your 3rd-party
-app server:</p>
+
+
+<p>Here is an example of the delivery receipt that CCS sends to tell your 3rd-party
+app server that a device received a message that CCS sent it:</p>
</p>
<pre>&lt;message id=&quot;&quot;&gt;
@@ -483,12 +475,12 @@ app server:</p>
<ul>
<li>The {@code &quot;message_type&quot;} is set to {@code &quot;receipt&quot;}.
<li>The {@code &quot;message_status&quot;} is set to {@code &quot;MESSAGE_SENT_TO_DEVICE&quot;},
- indicating that the message was delivered. Notice that in this case,
+ indicating that the device received the message. Notice that in this case,
{@code &quot;message_status&quot;} is not a field but rather part of the data payload.</li>
<li>The receipt message ID consists of the original message ID, but with a
-<code>dr:</code> prefix. Your 3rd-party app server must send an ACK back with this ID,
+<code>dr2:</code> prefix. Your 3rd-party app server must send an ACK back with this ID,
which in this example is {@code dr2:m-1366082849205}.</li>
- <li>The original message ID and status are inside the
+ <li>The original message ID, the device registration ID, and the status are inside the
{@code &quot;data&quot;} field.</li>
</ul>
diff --git a/docs/html/google/gcm/client.jd b/docs/html/google/gcm/client.jd
index 20bff10dd954..70109c6f39db 100644
--- a/docs/html/google/gcm/client.jd
+++ b/docs/html/google/gcm/client.jd
@@ -34,14 +34,14 @@ page.tags=cloud,push,messaging
</div>
</div>
-<p>A GCM client is a GCM-enabled app that runs on an Android device. To write your
-client code, we recommend that you use the
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> APIs.
+<p>A Google Cloud Messaging (GCM) client is a GCM-enabled app that runs on an
+Android device. To write your client code, we recommend that you use the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/package-summary.html">
+GCM APIs</a>.
The client helper library that was offered in previous versions of GCM still works,
but it has been superseded by the more efficient
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> APIs.</p>
+<a href="{@docRoot}reference/com/google/android/gms/gcm/package-summary.html">
+GCM APIs</a>.</p>
<p>A full GCM implementation requires both a client implementation and a server
implementation. For more
@@ -57,8 +57,8 @@ registration ID), and a broadcast receiver to receive messages sent by GCM.
<h2 id="play-services">Step 1: Set Up Google Play Services</h2>
<p>To write your client application, use the
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> API.
+<a href="{@docRoot}reference/com/google/android/gms/gcm/package-summary.html">
+GCM APIs</a>.
To use this API, you must set up your project to use the Google Play services SDK,
as described in <a href="/google/play-services/setup.html">Setup Google Play
Services SDK</a>.</p>
@@ -159,7 +159,7 @@ could not run properly. </li>
<p>Finally, write your application. This section features a sample client
application that illustrates how to use the
<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> APIs. The sample consists of a main activity
+{@code GoogleCloudMessaging}</a> API. The sample consists of a main activity
({@code DemoActivity}), a {@link android.support.v4.content.WakefulBroadcastReceiver}
({@code GcmBroadcastReceiver}), and an {@link android.app.IntentService}
({@code GcmIntentService}). You can find the complete source code for this sample at the
@@ -456,7 +456,7 @@ private void storeRegistrationId(Context context, String regId) {
<p>When the user clicks the app's <strong>Send</strong> button, the app sends an
upstream message using the
<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> APIs. In order to receive the upstream message,
+{@code GoogleCloudMessaging}</a> API. In order to receive the upstream message,
your server should be connected to CCS. You can use one of the demo servers in
<a href="ccs.html#implement">Implementing an XMPP-based App Server</a> to run the sample and connect
to CCS.</p>
@@ -652,7 +652,7 @@ your sender ID and API key.
<p>To view statistics and any error messages for your GCM applications:</p>
<ol>
- <li> Go to the <code><a href="http://play.google.com/apps/publish">Developer Console</a></code>.</li>
+ <li> Go to the <a href="http://play.google.com/apps/publish">Developer Console</a>.</li>
<li>Login with your developer account.
<p>You will see a page that has a list of all of your apps.</p></li>
<li> Click on the &quot;statistics&quot; link next to the app for which you
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index 19151b94e1c0..3d6594da8c9d 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -21,7 +21,7 @@ page.title=Overview
</div>
</div>
-<p>Google Cloud Messaging for Android (GCM) is a free service that helps
+<p>Google Cloud Messaging (GCM) for Android is a free service that helps
developers send data from servers to their Android applications on Android
devices, and upstream messages from the user's device back to the cloud.
This could be a lightweight message telling the Android application
diff --git a/docs/html/google/gcm/gs.jd b/docs/html/google/gcm/gs.jd
index ae57b6d6e372..a88962462cfc 100644
--- a/docs/html/google/gcm/gs.jd
+++ b/docs/html/google/gcm/gs.jd
@@ -25,12 +25,12 @@ page.tags=cloud,push,messaging
</div>
</div>
-<p>This document tells you how to get started setting up a GCM
-implementation.
+<p>This document tells you how to get started setting up a Google Cloud Messaging
+(GCM) implementation.
Before you begin, make sure to <a href="/google/play-services/setup.html">set up
the Google Play Services SDK</a>. You need this SDK to use the
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> methods.</p>
+<a href="{@docRoot}reference/com/google/android/gms/gcm/package-summary.html">
+GCM APIs</a>.</p>
<h2 id="create-proj">Creating a Google API project</h2>
<p>To create a Google API project:</p>
diff --git a/docs/html/google/gcm/http.jd b/docs/html/google/gcm/http.jd
index b8d8659d941e..773acd1690ff 100644
--- a/docs/html/google/gcm/http.jd
+++ b/docs/html/google/gcm/http.jd
@@ -33,13 +33,16 @@ page.title=GCM HTTP Connection Server
</div>
</div>
-<p>This document describes the GCM HTTP connection server. Connection servers
+<p>This document describes the Google Cloud Messaging (GCM) HTTP
+connection server. Connection servers
are the Google-provided servers that take messages from the 3rd-party
application server and sending them to the device.</p>
+<p class="note"><strong>Note:</strong> The content in this document
+applies to <a href="http://developer.chrome.com/apps/cloudMessaging">
+GCM with Chrome apps</a> as well as Android.</p>
-
-<p class="note"><strong>Note:</strong> See
+<p>See
<a href="server.html#params">Implementing GCM Server</a> for a list of all the message
parameters and which connection server(s) supports them.</p>
@@ -163,7 +166,7 @@ before the request can be retried.</td>
</tr>
<tr>
<td>5xx</td>
- <td>Errors in the 500-599 range (such as 500 or 503) indicate that there wa
+ <td>Errors in the 500-599 range (such as 500 or 503) indicate that there was
an internal error in the GCM server while trying to process the request, or that
the server is temporarily unavailable (for example, because of timeouts). Sender
must retry later, honoring any <code>Retry-After</code> header included in the
@@ -416,6 +419,12 @@ A message was addressed to a registration ID whose package name did not match
the value passed in the request. Happens when error code is
<code>InvalidPackageName</code>.
</dd>
+
+<dt id="big_msg"><strong>Device Message Rate Exceeded</strong></dt>
+ <dd>The rate of messages to a particular device is too high. You should reduce the number
+of messages sent to this device and should not retry sending to this device immediately.
+<br/>Happens when error code is <code>DeviceMessageRateExceeded</code>.</dd>
+
</dl>
<h3 id="example-responses">Example responses</h3>
diff --git a/docs/html/google/gcm/index.jd b/docs/html/google/gcm/index.jd
index 56e08655e4be..af5d74104605 100644
--- a/docs/html/google/gcm/index.jd
+++ b/docs/html/google/gcm/index.jd
@@ -13,11 +13,11 @@ header.hide=1
<h1 itemprop="name" style="margin-bottom:0;">Google Cloud Messaging for Android</h1>
<p itemprop="description">
- Google Cloud Messaging for Android (GCM) is a service that allows you to send data
+ Google Cloud Messaging (GCM) for Android is a service that allows you to send data
from your server to your users' Android-powered device, and also to receive messages from
devices on the same connection. The GCM service handles all aspects of queueing of messages
-and delivery to the target Android application running on the target device. GCM is
-completely free no matter how big your messaging needs are, and there are no quotas.
+and delivery to the target Android application running on the target device, and it is
+completely free.
</p>
</div>
diff --git a/docs/html/google/gcm/notifications.jd b/docs/html/google/gcm/notifications.jd
index 2815f3d6cefb..147b69c3b57c 100644
--- a/docs/html/google/gcm/notifications.jd
+++ b/docs/html/google/gcm/notifications.jd
@@ -83,7 +83,7 @@ message body is JSON.</p>
<h2 id="gen-server">Generate a Notification Key on the Server</h2>
<p>To generate a notification key on the server, you create a new
-create a new <code>notification_key</code> and map it to a
+<code>notification_key</code> and map it to a
<code>notification_key_name</code>.</p>
<p>This example shows how to create a new <code>notification_key</code> for a
@@ -268,7 +268,7 @@ notification key operations.</p>
<p>When you make a request to create a {@code notification_key} or to add/remove its
regIDs, a successful response always returns the <code>notification_key</code>.
-his is the {@code notification_key} you will use for sending messages:</p>
+Use the returned {@code notification_key} for sending messages:</p>
<pre>HTTP status: 200
{
diff --git a/docs/html/google/gcm/server.jd b/docs/html/google/gcm/server.jd
index e3a6b2527899..20e2b2e6cf12 100644
--- a/docs/html/google/gcm/server.jd
+++ b/docs/html/google/gcm/server.jd
@@ -37,7 +37,7 @@ page.title=Implementing GCM Server
</div>
-<p>The server side of GCM consists of 2 components:</p>
+<p>The server side of Google Cloud Messaging (GCM) consists of 2 components:</p>
<ul>
<li>Google-provided <strong>GCM Connection Servers</strong>
take messages from a 3rd-party application server and send them to a GCM-enabled
@@ -168,36 +168,37 @@ column for information about which connection servers support that particular
parameter.</p>
<p class="table-caption" id="table1">
- <strong>Table 1.</strong> Message parameters.</p>
+ <strong>Table 1.</strong> Message Parameters JSON (CCS and HTTP).</p>
<table>
<tr>
- <th>Field</th>
+ <th>Parameter</th>
<th>Description</th>
<th>Where Supported</th>
</tr>
<td><code>to</code></td>
-<td>In CCS, used in place of <code>registration_ids</code> to specify the
-recipient of a message. Its value must be a registration ID.
+<td>In CCS, this parameter is used in place of <code>registration_ids</code> to
+specify the recipient of a message. Its value must be a registration ID.
The value is a string. Required.</td>
<td>CCS</td>
</tr>
<tr>
<td><code>message_id</code></td>
-<td>In CCS, uniquely identifies a message in an XMPP connection. The value is a
-string that uniquely identifies the associated message. The value is a string. Required.</td>
+<td>In CCS, this parameter uniquely identifies a message in an XMPP connection.
+The value is a string that uniquely identifies the associated message. Required.</td>
<td>CCS</td>
</tr>
<tr>
<td><code>message_type</code></td>
-<td>In CCS, indicates a special status message, typically sent by the system.
+<td>In CCS, this parameter indicates a special status message, typically sent by the system.
However, your app server also uses this parameter to send an 'ack' or 'nack'
message back to the CCS connection server. For more discussion of this topic, see
<a href="ccs.html">Cloud Connection Server</a>. The value is a string. Optional.</td>
<td>CCS</td>
<tr>
<td><code>registration_ids</code></td>
- <td>A string array with the list of devices (registration IDs) receiving the
+ <td>This parameter specifies a string array containing the list of devices
+(registration IDs) receiving the
message. It must contain at least 1 and at most 1000 registration IDs. To send a
multicast message, you must use JSON. For sending a single message to a single
device, you could use a JSON object with just 1 registration id, or plain text
@@ -208,12 +209,13 @@ Required.</td>
</tr>
<tr>
<td><code>notification_key</code></td>
- <td>A string that maps a single user to multiple registration IDs associated
+ <td>This parameter specifies a string that maps a single user to multiple
+registration IDs associated
with that user. This allows a 3rd-party server to send a single message to
multiple app instances (typically on multiple devices) owned by a single user.
A 3rd-party server can use {@code notification_key} as the target for a message
instead of an individual registration ID (or array of registration IDs). The maximum
-number of members allowed for a {@code notification_key} is 10. For more discussion
+number of members allowed for a {@code notification_key} is 20. For more discussion
of this topic, see <a href="notifications.html">User Notifications</a>. Optional.
</td>
<td style="width:100px">HTTP. This feature is supported in CCS, but you use it by
@@ -221,13 +223,14 @@ specifying a notification key in the &quot;to&quot; field.</td>
</tr>
<tr>
<td><code>collapse_key</code></td>
- <td>An arbitrary string (such as &quot;Updates Available&quot;) that is used
+ <td>This parameter specifies an arbitrary string (such as
+&quot;Updates Available&quot;) that is used
to collapse a group of like messages
when the device is offline, so that only the last message gets sent to the
client. This is intended to avoid sending too many messages to the phone when it
comes back online. Note that since there is no guarantee of the order in which
messages get sent, the &quot;last&quot; message may not actually be the last
-message sent by the application server. Collapse keys are also called
+message sent by the application server. Messages with collapse keys are also called
<a href="#s2s">send-to-sync messages</a>.
<br>
<strong>Note:</strong> GCM allows a maximum of 4 different collapse keys to be
@@ -242,8 +245,9 @@ discussion of this topic. Optional.</td>
</tr>
<tr>
<td><code>data</code></td>
- <td>A JSON object whose fields represents the key-value pairs of the message's
-payload data. If present, the payload data it will be
+ <td>This parameter specifies a JSON object whose fields represents the
+key-value pairs of the message's
+payload data. If present, the payload data will be
included in the Intent as application data, with the key being the extra's name.
For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra
named <code>score</code> whose value is the string <code>3x1</code>.
@@ -253,17 +257,14 @@ recommend using strings, since the values will be converted to strings in the GC
server anyway. If you want to include objects or other non-string data types
(such as integers or booleans), you have to do the conversion to string yourself.
Also note that the key cannot be a reserved word (<code>from</code> or any word
-starting with <code>google.</code>). To complicate things slightly, there are
-some reserved words (such as <code>collapse_key</code>) that are technically
-allowed in payload data. However, if the request also contains the word, the
-value in the request will overwrite the value in the payload data. Hence using
-words that are defined as field names in this table is not recommended, even in
-cases where they are technically allowed. Optional.</td>
+starting with <code>google.</code>). Using words defined in this table as field
+names (such as <code>collapse_key</code>) could yield unpredictable outcomes and
+is not recommended. Optional.</td>
<td>CCS, HTTP</td>
</tr>
<tr>
<td><code>delay_while_idle</code></td>
- <td>If included, indicates that the message should not be sent immediately
+ <td>This parameter indicates that the message should not be sent immediately
if the device is idle. The server will wait for the device to become active, and
then only the last message for each <code>collapse_key</code> value will be
sent. The default value is <code>false</code>, and must be a JSON boolean. Optional.</td>
@@ -271,26 +272,70 @@ sent. The default value is <code>false</code>, and must be a JSON boolean. Optio
</tr>
<tr>
<td><code>time_to_live</code></td>
- <td>How long (in seconds) the message should be kept on GCM storage if the
-device is offline. Optional (default time-to-live is 4 weeks, and must be set as
+ <td>This parameter specifies how long (in seconds) the message should be kept on GCM
+storage if the device is offline. Optional (default time-to-live is 4 weeks, and must be set as
a JSON number).</td>
<td>CCS, HTTP</td>
</tr>
<tr>
<td><code>restricted_package_name</code></td>
- <td>A string containing the package name of your application. When set, messages
-will only be sent to registration IDs that match the package name. Optional.
+ <td>This parameter specifies a string containing the package
+name of your application. When set, messages
+are only sent to registration IDs that match the package name. Optional.
</td>
<td>HTTP</td>
</tr>
<tr>
<td><code>dry_run</code></td>
- <td>If included, allows developers to test their request without actually
+ <td>This parameter allows developers to test a request without actually
sending a message. Optional. The default value is <code>false</code>, and must
be a JSON boolean.
</td>
<td>HTTP</td>
</tr>
+<tr>
+ <td><code>delivery_receipt_requested</code></td>
+ <td>This parameter lets you request confirmation of message delivery. When
+this parameter is set to <code>true</code>, CCS sends a
+delivery receipt when a device confirms that it received a message sent by CCS.
+The default value is <code>false</code>, and must be a JSON boolean. Optional.<br />
+This parameter relates to <a href="{@docRoot}google/gcm/ccs.html#receipts"}>
+delivery receipts</a>.
+</td>
+ <td>CCS</td>
+</tr>
+<tr>
+ <td><code>message_status</code></td>
+ <td>This parameter specifies the status of the receipt message.
+The parameter appears inside the
+<code>&quot;data&quot;</code> field of a
+delivery receipt message. Currently the only possible value
+is <code>MESSAGE_SENT_TO_DEVICE</code>, which indicates that a device acknowledges
+receiving a message sent by CCS.<br />
+This parameter relates to <a href="{@docRoot}google/gcm/ccs.html#receipts"}>
+delivery receipts</a>.</td>
+ <td>CCS</td>
+</tr>
+<tr>
+ <td><code>original_message_id</code></td>
+ <td>The value of this parameter is the ID of the original message that the server sent to
+the device. This parameter appears inside the <code>&quot;data&quot;</code> field of a
+delivery receipt message. <br />
+This parameter relates to <a href="{@docRoot}google/gcm/ccs.html#receipts"}>
+delivery receipts</a>.</td>
+ <td>CCS</td>
+</tr>
+<tr>
+ <td><code>device_registration_id</code></td>
+ <td>For the purpose of tracking the delivery receipt, this parameter lists
+the registration ID of the device to which a given message was sent. This parameter
+appears inside the <code>&quot;data&quot;</code> field of a
+delivery receipt message. <br />
+This parameter relates to <a href="{@docRoot}google/gcm/ccs.html#receipts"}>
+delivery receipts</a>.</td>
+ <td>CCS</td>
+</tr>
+
</table>
<p>If you want to test your request (either JSON or plain text) without delivering
@@ -298,21 +343,23 @@ the message to the devices, you can set an optional HTTP or JSON parameter calle
<code>dry_run</code> with the value <code>true</code>. The result will be almost
identical to running the request without this parameter, except that the message
will not be delivered to the devices. Consequently, the response will contain fake
-IDs for the message and multicast fields.</p>
-
-<h3 id="plain-text">Plain text (HTTP only)</h3>
+IDs for the message and multicast parameters.</p>
-<p>If you are using plain text instead of JSON, the message fields must be set as
+<p>If you are using plain text instead of JSON, the message parameters must be set as
HTTP parameters sent in the body, and their syntax is slightly different, as
-described below:
+described in the following table:
+
+<p class="table-caption" id="table2">
+ <strong>Table 2.</strong> Message Parameters Plain Text (HTTP only).</p>
<table>
<tr>
- <th>Field</th>
+ <th>Parameter</th>
<th>Description</th>
</tr>
<tr>
<td><code>registration_id</code></td>
- <td>Must contain the registration ID of the single device receiving the message.
+ <td>This parameter specifies the registration ID of the single device
+receiving the message.
Required.</td>
</tr>
<tr>
@@ -322,24 +369,23 @@ Required.</td>
<tr>
<td><code>data.&lt;key&gt;</code></td>
- <td>Payload data, expressed as parameters prefixed with <code>data.</code> and
+ <td>This parameter specifies payload data, expressed as parameters
+prefixed with <code>data.</code> and
suffixed as the key. For instance, a parameter of <code>data.score=3x1</code> would
result in an intent extra named <code>score</code> whose value is the string
<code>3x1</code>. There is no limit on the number of key/value parameters, though
there is a limit on the total size of the message. Also note that the key cannot
be a reserved word (<code>from</code> or any word starting with
-<code>google.</code>). To complicate things slightly, there are some reserved words
-(such as <code>collapse_key</code>) that are technically allowed in payload data.
-However, if the request also contains the word, the value in the request will
-overwrite the value in the payload data. Hence using words that are defined as
-field names in this table is not recommended, even in cases where they are
-technically allowed. Optional.</td>
+<code>google.</code>). Using words defined in this table as field
+names (such as <code>collapse_key</code>) could yield unpredictable outcomes and
+is not recommended. Optional.</td>
</tr>
<tr>
<td><code>delay_while_idle</code></td>
- <td>Should be represented as <code>1</code> or <code>true</code> for
-<code>true</code>, anything else for <code>false</code>. Optional. The default
+ <td>This parameter specifies whether messages should be delivered when the device
+is asleep. A value of <code>1</code> or <code>true</code> indicates
+<code>true</code>, and anything else indicates <code>false</code>. Optional. The default
value is <code>false</code>.</td>
</tr>
<tr>
diff --git a/docs/html/guide/topics/text/creating-input-method.jd b/docs/html/guide/topics/text/creating-input-method.jd
index 802b58a75d8f..424a21cf452a 100644
--- a/docs/html/guide/topics/text/creating-input-method.jd
+++ b/docs/html/guide/topics/text/creating-input-method.jd
@@ -41,8 +41,8 @@ page.tags=ime,keyboard,inputmethodservice
<p>
To add an IME to the Android system, you create an Android application
containing a class that extends {@link android.inputmethodservice.InputMethodService}. In
- addition, you usually create a "settings" activity that passes options to the IME
- service. You can also define a settings UI that's displayed as part of the system settings.
+ addition, you usually create a "settings" activity that passes options to the IME service. You
+ can also define a settings UI that's displayed as part of the system settings.
</p>
<p>This guide covers the following:</p>
<ul>
@@ -70,29 +70,22 @@ page.tags=ime,keyboard,inputmethodservice
<strong>Figure 1.</strong> The life cycle of an IME.
</p>
<p>
- The following sections describe how to implement the UI and code associated
-with an IME that
+ The following sections describe how to implement the UI and code associated with an IME that
follows this lifecycle.
</p>
<h2 id="DefiningIME">Declaring IME Components in the Manifest</h2>
<p>
- In the Android system, an IME is an Android application that contains a
-special IME service.
- The application's manifest file must declare the service, request the
-necessary permissions,
- provide an intent filter that matches the action
-<code>action.view.InputMethod</code>, and
- provide metadata that defines characteristics of the IME. In addition, to
-provide a settings
- interface that allows the user to modify the behavior of the IME, you can
-define a "settings"
+ In the Android system, an IME is an Android application that contains a special IME service.
+ The application's manifest file must declare the service, request the necessary permissions,
+ provide an intent filter that matches the action <code>action.view.InputMethod</code>, and
+ provide metadata that defines characteristics of the IME. In addition, to provide a settings
+ interface that allows the user to modify the behavior of the IME, you can define a "settings"
activity that can be launched from System Settings.
</p>
<p>
The following snippet declares an IME service. It requests the permission
-{@link android.Manifest.permission#BIND_INPUT_METHOD} to allow the service to
-connect the IME to
- the system, sets up an intent filter that matches the action
+ {@link android.Manifest.permission#BIND_INPUT_METHOD} to allow the service to connect the IME
+ to the system, sets up an intent filter that matches the action
<code>android.view.InputMethod</code>, and defines metadata for the IME:
</p>
<pre>
@@ -108,10 +101,8 @@ android:resource="&#64;xml/method" /&gt;
&lt;/service&gt;
</pre>
<p>
- This next snippet declares the settings activity for the IME. It has an
-intent filter for
- {@link android.content.Intent#ACTION_MAIN} that indicates this activity is
-the main entry point
+ This next snippet declares the settings activity for the IME. It has an intent filter for
+ {@link android.content.Intent#ACTION_MAIN} that indicates this activity is the main entry point
for the IME application:</p>
<pre>
&lt;!-- Optional: an activity for controlling the IME settings --&gt;
@@ -127,23 +118,18 @@ the main entry point
</p>
<h2 id="IMEAPI">The Input Method API</h2>
<p>
- Classes specific to IMEs are found in the {@link android.inputmethodservice} and {@link android.view.inputmethod}
- packages. The {@link android.view.KeyEvent} class is important for handling keyboard
- characters.
+ Classes specific to IMEs are found in the {@link android.inputmethodservice} and
+ {@link android.view.inputmethod} packages. The {@link android.view.KeyEvent} class is
+ important for handling keyboard characters.
</p>
<p>
The central part of an IME is a service component, a class that extends
- {@link android.inputmethodservice.InputMethodService}. In addition to
-implementing the
- normal service lifecycle, this class has callbacks for providing your IME's
-UI, handling user
- input, and delivering text to the field that currently has focus. By
-default, the
- {@link android.inputmethodservice.InputMethodService} class provides most
-of the implementation
- for managing the state and visibility of the IME and communicating with the
-current
- input field.
+ {@link android.inputmethodservice.InputMethodService}. In addition to implementing the
+ normal service lifecycle, this class has callbacks for providing your IME's UI, handling user
+ input, and delivering text to the field that currently has focus. By default, the
+ {@link android.inputmethodservice.InputMethodService} class provides most of the implementation
+ for managing the state and visibility of the IME and communicating with the current input
+ field.
</p>
<p>
The following classes are also important:
@@ -152,45 +138,32 @@ current
<dt>{@link android.view.inputmethod.BaseInputConnection}</dt>
<dd>
Defines the communication channel from an {@link android.view.inputmethod.InputMethod}
- back to the application that is receiving its input. You use it to read
-text around the
- cursor, commit text to the text box, and send raw key events to the
-application.
- Applications should extend this class rather than implementing the base
-interface
+ back to the application that is receiving its input. You use it to read text around the
+ cursor, commit text to the text box, and send raw key events to the application.
+ Applications should extend this class rather than implementing the base interface
{@link android.view.inputmethod.InputConnection}.
</dd>
<dt>{@link android.inputmethodservice.KeyboardView}</dt>
<dd>
- An extension of {@link android.view.View} that renders a keyboard and
-responds to user
+ An extension of {@link android.view.View} that renders a keyboard and responds to user
input events. The keyboard layout is specified by an instance of
- {@link android.inputmethodservice.Keyboard}, which you can define in an
-XML file.
+ {@link android.inputmethodservice.Keyboard}, which you can define in an XML file.
</dd>
</dl>
<h2 id="IMEUI">Designing the Input Method UI</h2>
<p>
- There are two main visual elements for an IME: the <strong>input</strong>
-view and the
- <strong>candidates</strong> view. You only have to implement the elements
-that are relevant to
+ There are two main visual elements for an IME: the <strong>input</strong> view and the
+ <strong>candidates</strong> view. You only have to implement the elements that are relevant to
the input method you're designing.
</p>
<h3 id="InputView">Input view</h3>
<p>
- The input view is the UI where the user inputs text in the form of
-keyclicks, handwriting or
- gestures. When the IME is displayed for the first time, the system calls
-the
- {@link android.inputmethodservice.InputMethodService#onCreateInputView()}
-callback. In your
- implementation of this method, you create the layout you want to display in
-the IME
- window and return the layout to the system. This snippet is an example of
-implementing the
- {@link android.inputmethodservice.InputMethodService#onCreateInputView()}
-method:
+ The input view is the UI where the user inputs text in the form of keyclicks, handwriting or
+ gestures. When the IME is displayed for the first time, the system calls the
+ {@link android.inputmethodservice.InputMethodService#onCreateInputView()} callback. In your
+ implementation of this method, you create the layout you want to display in the IME
+ window and return the layout to the system. This snippet is an example of implementing the
+ {@link android.inputmethodservice.InputMethodService#onCreateInputView()} method:
<pre>
&#64;Override
public View onCreateInputView() {
@@ -215,17 +188,12 @@ traditional QWERTY keyboard,
</p>
<h3 id="CandidateView">Candidates view</h3>
<p>
- The candidates view is the UI where the IME displays potential word
-corrections or
+ The candidates view is the UI where the IME displays potential word corrections or
suggestions for the user to select. In the IME lifecycle, the system calls
- {@link android.inputmethodservice.InputMethodService#onCreateCandidatesView()} when
-it's ready
- to display the candidates view. In your implementation of this method,
-return a layout that shows
- word suggestions, or return null if you don’t want to show anything. A
-null response is the
- default behavior, so you don’t have to implement this if you don’t
-provide suggestions.</p>
+ {@link android.inputmethodservice.InputMethodService#onCreateCandidatesView()} when it's ready
+ to display the candidates view. In your implementation of this method, return a layout that
+ shows word suggestions, or return null if you don’t want to show anything. A null response is
+ the default behavior, so you don’t have to implement this if you don’t provide suggestions.</p>
<p>
For an example implementation that provides user suggestions, see the
<a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/">
@@ -237,32 +205,22 @@ provide suggestions.</p>
</p>
<h4>Handling multiple screen sizes</h4>
<p>
- The UI for your IME must be able to scale for different screen sizes, and
-it also
- must handle both landscape and portrait orientations. In non-fullscreen IME
-mode, leave
- sufficient space for the application to show the text field and any
-associated context, so that
- no more than half the screen is occupied by the IME. In fullscreen IME mode
-this is not an
+ The UI for your IME must be able to scale for different screen sizes, and it also
+ must handle both landscape and portrait orientations. In non-fullscreen IME mode, leave
+ sufficient space for the application to show the text field and any associated context, so that
+ no more than half the screen is occupied by the IME. In fullscreen IME mode this is not an
issue.
</p>
<h4>Handling different input types</h4>
<p>
- Android text fields allow you to set a specific input type, such as free
-form text, numbers,
- URLs, email addresses, and search strings. When you implement a new IME,
-you need to
- detect the input type of each field and provide the appropriate interface
-for it. However, you
- don't have to set up your IME to check that the user entered text
-valid for the
- input type; that's the responsibility of the application that owns the text
-field.
+ Android text fields allow you to set a specific input type, such as free-form text, numbers,
+ URLs, email addresses, and search strings. When you implement a new IME, you need to detect
+ the input type of each field and provide the appropriate interface for it. However, you
+ don't have to set up your IME to check that the user entered text valid for the input type;
+ that's the responsibility of the application that owns the text field.
</p>
<p>
- For example, here are screenshots of the interfaces that the Latin IME
-provided with the
+ For example, here are screenshots of the interfaces that the Latin IME provided with the
Android platform provides for text and phone number inputs:
</p>
<img src="{@docRoot}resources/articles/images/inputmethod_text_type_screenshot.png" alt="" height="142" id="figure2" />
@@ -273,18 +231,14 @@ provided with the
<p>
When an input field receives focus and your IME starts, the system calls
{@link android.inputmethodservice.InputMethodService#onStartInputView(EditorInfo, boolean) onStartInputView()},
- passing in an {@link android.view.inputmethod.EditorInfo} object that
- contains details about the input type and other attributes of the text
-field. In this object,
- the {@link android.view.inputmethod.EditorInfo#inputType} field contains
-the text field's input
+ passing in an {@link android.view.inputmethod.EditorInfo} object that contains details about
+ the input type and other attributes of the text field. In this object, the
+ {@link android.view.inputmethod.EditorInfo#inputType} field contains the text field's input
type.
</p>
<p>
- The {@link android.view.inputmethod.EditorInfo#inputType} field is an
-<code>int</code>
- that contains bit patterns for various input type settings. To test it for
-the text field's
+ The {@link android.view.inputmethod.EditorInfo#inputType} field is an <code>int</code>
+ that contains bit patterns for various input type settings. To test it for the text field's
input type, mask it with the constant {@link android.text.InputType#TYPE_MASK_CLASS}, like
this:
</p>
@@ -297,8 +251,7 @@ The input type bit pattern can have one of several values, including:
<dl>
<dt>{@link android.text.InputType#TYPE_CLASS_NUMBER}</dt>
<dd>
- A text field for entering numbers. As illustrated in the previous
-screen shot, the
+ A text field for entering numbers. As illustrated in the previous screen shot, the
Latin IME displays a number pad for fields of this type.
</dd>
<dt>{@link android.text.InputType#TYPE_CLASS_DATETIME}</dt>
@@ -315,103 +268,86 @@ screen shot, the
</dd>
</dl>
<p>
- These constants are described in more detail in the reference documentation
-for
+ These constants are described in more detail in the reference documentation for
{@link android.text.InputType}.
</p>
<p>
- The {@link android.view.inputmethod.EditorInfo#inputType} field can contain
-other bits that
+ The {@link android.view.inputmethod.EditorInfo#inputType} field can contain other bits that
indicate a variant of the text field type, such as:
</p>
<dl>
<dt>{@link android.text.InputType#TYPE_TEXT_VARIATION_PASSWORD}</dt>
<dd>
- A variant of {@link android.text.InputType#TYPE_CLASS_TEXT} for
-entering passwords. The
+ A variant of {@link android.text.InputType#TYPE_CLASS_TEXT} for entering passwords. The
input method will display dingbats instead of the actual text.
</dd>
<dt>{@link android.text.InputType#TYPE_TEXT_VARIATION_URI}</dt>
<dd>
- A variant of {@link android.text.InputType#TYPE_CLASS_TEXT} for
-entering web URLs and
+ A variant of {@link android.text.InputType#TYPE_CLASS_TEXT} for entering web URLs and
other Uniform Resource Identifiers (URIs).
</dd>
<dt>{@link android.text.InputType#TYPE_TEXT_FLAG_AUTO_COMPLETE}</dt>
<dd>
- A variant of {@link android.text.InputType#TYPE_CLASS_TEXT} for
-entering text that the
- application "auto-completes" from a dictionary, search, or other
-facility.
+ A variant of {@link android.text.InputType#TYPE_CLASS_TEXT} for entering text that the
+ application "auto-completes" from a dictionary, search, or other facility.
</dd>
</dl>
<p>
- Remember to mask {@link android.view.inputmethod.EditorInfo#inputType} with
-the appropriate
- constant when you test for these variants. The available mask constants are
-listed in the
+ Remember to mask {@link android.view.inputmethod.EditorInfo#inputType} with the appropriate
+ constant when you test for these variants. The available mask constants are listed in the
reference documentation for {@link android.text.InputType}.
</p>
<p class="caution">
- <strong>Caution:</strong> In your own IME, make sure you handle text
-correctly when you send it
- to a password field. Hide the password in your UI both in the input view
-and in the candidates
- view. Also remember that you shouldn't store passwords on a device. To
-learn more, see the <a href="{@docRoot}guide/practices/security.html">Designing for Security</a>
- guide.
+ <strong>Caution:</strong> In your own IME, make sure you handle text correctly when you send it
+ to a password field. Hide the password in your UI both in the input view and in the candidates
+ view. Also remember that you shouldn't store passwords on a device. To learn more, see the
+ <a href="{@docRoot}guide/practices/security.html">Designing for Security</a> guide.
</p>
<h2 id="SendText">Sending Text to the Application</h2>
<p>
- As the user inputs text with your IME, you can send text to the application
-by
- sending individual key events or by editing the text around the cursor in
-the application's text
+ As the user inputs text with your IME, you can send text to the application by sending
+ individual key events or by editing the text around the cursor in the application's text
field. In either case, you use an instance of {@link android.view.inputmethod.InputConnection}
to deliver the text. To get this instance, call
{@link android.inputmethodservice.InputMethodService#getCurrentInputConnection InputMethodService.getCurrentInputConnection()}.
</p>
<h3 id="EditingCursor">Editing the text around the cursor</h3>
<p>
- When you're handling the editing of existing text in a text field, some of
-the more useful
+ When you're handling the editing of existing text in a text field, some of the more useful
methods in {@link android.view.inputmethod.BaseInputConnection} are:
</p>
<dl>
<dt>
{@link android.view.inputmethod.BaseInputConnection#getTextBeforeCursor(int, int) getTextBeforeCursor()}</dt>
<dd>
- Returns a {@link java.lang.CharSequence} containing the number of
-requested characters
+ Returns a {@link java.lang.CharSequence} containing the number of requested characters
before the current cursor position.
</dd>
<dt>
{@link android.view.inputmethod.BaseInputConnection#getTextAfterCursor(int, int) getTextAfterCursor()}
</dt>
<dd>
- Returns a {@link java.lang.CharSequence} containing the number of
-requested characters following the current cursor position.
+ Returns a {@link java.lang.CharSequence} containing the number of requested characters
+ following the current cursor position.
</dd>
<dt>
{@link android.view.inputmethod.BaseInputConnection#deleteSurroundingText(int, int) deleteSurroundingText()}
</dt>
<dd>
- Deletes the specified number of characters before and following the
-current cursor
+ Deletes the specified number of characters before and following the current cursor
position.
</dd>
<dt>
{@link android.view.inputmethod.BaseInputConnection#commitText(CharSequence, int) commitText()}
</dt>
<dd>
- Commit a {@link java.lang.CharSequence} to the text field and set a new
-cursor
+ Commit a {@link java.lang.CharSequence} to the text field and set a new cursor
position.
</dd>
</dl>
<p>
- For example, the following snippet shows how to replace the four characters to
-the left of the cursor with the text "Hello!":
+ For example, the following snippet shows how to replace the four characters to the left of the
+ cursor with the text "Hello!":
</p>
<pre>
InputConnection ic = getCurrentInputConnection();
@@ -424,12 +360,9 @@ the left of the cursor with the text "Hello!":
</pre>
<h3 id="ComposeThenCommit">Composing text before committing</h3>
<p>
- If your IME does text prediction or requires multiple steps to compose a
-glyph or
- word, you can show the progress in the text field until the user commits
-the word, and then you
- can replace the partial composition with the completed text. You may give
-special treatment to
+ If your IME does text prediction or requires multiple steps to compose a glyph or
+ word, you can show the progress in the text field until the user commits the word, and then you
+ can replace the partial composition with the completed text. You may give special treatment to
the text by adding a "span" to it when you pass it to
{@link android.view.inputmethod.InputConnection#setComposingText setComposingText()}.
</p>
@@ -465,14 +398,10 @@ alt="" height="31"
</p>
<h3 id="HardwareKeyEvents">Intercepting hardware key events</h3>
<p>
- Even though the input method window doesn't have explicit focus, it
-receives hardware key
- events first and can choose to consume them or forward them along to the
-application. For
- example, you may want to consume the directional keys to navigate within
-your UI for candidate
- selection during composition. You may also want to trap the back key to
-dismiss any popups
+ Even though the input method window doesn't have explicit focus, it receives hardware key
+ events first and can choose to consume them or forward them along to the application. For
+ example, you may want to consume the directional keys to navigate within your UI for candidate
+ selection during composition. You may also want to trap the back key to dismiss any popups
originating from the input method window.</p>
<p>
To intercept hardware keys, override
@@ -483,45 +412,36 @@ dismiss any popups
SoftKeyboard</a> sample app for an example.
</p>
<p>
- Remember to call the <code>super()</code> method for keys you don't want to
-handle yourself.
+ Remember to call the <code>super()</code> method for keys you don't want to handle yourself.
</p>
<h2 id="IMESubTypes">Creating an IME Subtype</h2>
<p>
- Subtypes allow the IME to expose multiple input modes and languages
-supported by an IME. A subtype can represent:
+ Subtypes allow the IME to expose multiple input modes and languages supported by an IME. A
+ subtype can represent:
</p>
<ul>
<li>A locale such as en_US or fr_FR</li>
<li>An input mode such as voice, keyboard, or handwriting</li>
<li>
- Other input styles, forms, or properties specific to the IME, such as
-10-key or qwerty
+ Other input styles, forms, or properties specific to the IME, such as 10-key or qwerty
keyboard layouts.
</li>
</ul>
<p>
- Basically, the mode can be any text such as "keyboard", "voice", and so
-forth. A subtype can also expose a combination of these.
+ Basically, the mode can be any text such as "keyboard", "voice", and so forth. A subtype can
+ also expose a combination of these.
</p>
<p>
- Subtype information is used for an IME switcher dialog that's available
-from the notification
- bar and also for IME settings. The information also allows the framework to
-bring up a
- specific subtype of an IME directly. When you build an IME, use the subtype
-facility, because
- it helps the user identify and switch between different IME languages and
-modes.
-</p>
-<p>
- You define subtypes in one of the input method's XML resource files, using
-the
- <code>&lt;subtype&gt;</code> element. The following snippet defines an IME
-with two
- subtypes: a keyboard subtype for the US English locale, and another
-keyboard subtype for the
+ Subtype information is used for an IME switcher dialog that's available from the notification
+ bar and also for IME settings. The information also allows the framework to bring up a
+ specific subtype of an IME directly. When you build an IME, use the subtype facility, because
+ it helps the user identify and switch between different IME languages and modes.
+</p>
+<p>
+ You define subtypes in one of the input method's XML resource files, using the
+ <code>&lt;subtype&gt;</code> element. The following snippet defines an IME with two
+ subtypes: a keyboard subtype for the US English locale, and another keyboard subtype for the
French language locale for France:
</p>
<pre>
@@ -546,10 +466,8 @@ keyboard subtype for the
/&gt;
</pre>
<p>
- To ensure that your subtypes are labeled correctly in the UI, use %s to get
-a subtype label
- that is the same as the subtype’s locale label. This is demonstrated in
-the next two snippets.
+ To ensure that your subtypes are labeled correctly in the UI, use %s to get a subtype label
+ that is the same as the subtype’s locale label. This is demonstrated in the next two snippets.
The first snippet shows part of the input method's XML file:
</p>
<pre>
@@ -560,10 +478,8 @@ the next two snippets.
android:imeSubtypeMode="keyboard" /&gt;
</pre>
<p>
- The next snippet is part of the IME's <code>strings.xml</code> file. The
-string
- resource <code>label_subtype_generic</code>, which is used by the input
-method UI definition to
+ The next snippet is part of the IME's <code>strings.xml</code> file. The string
+ resource <code>label_subtype_generic</code>, which is used by the input method UI definition to
set the subtype's label, is defined as:
</p>
<pre>
@@ -575,12 +491,9 @@ method UI definition to
</p>
<h3 id="SubtypeProcessing">Choosing IME subtypes from the notification bar</h3>
<p>
- The Android system manages all subtypes exposed by all IMEs. IME subtypes
-are
- treated as modes of the IME they belong to. In the notification bar, a user
-can select an
- available subtype for the currently-set IME, as shown in the following
-screenshot:
+ The Android system manages all subtypes exposed by all IMEs. IME subtypes are
+ treated as modes of the IME they belong to. In the notification bar, a user can select an
+ available subtype for the currently-set IME, as shown in the following screenshot:
</p>
<img
src="{@docRoot}resources/articles/images/inputmethod_subtype_notification.png"
@@ -599,9 +512,9 @@ alt=""
</p>
<h3 id="SubtypeSettings">Choosing IME subtypes from System Settings</h3>
<p>
- A user can control how subtypes are used in the “Language &amp; input”
-settings panel in the
- System Settings area. In the <a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/">
+ A user can control how subtypes are used in the “Language &amp; input” settings panel in the
+ System Settings area. In the
+ <a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/">
SoftKeyboard</a> sample app, the file <code>InputMethodSettingsFragment.java</code> contains an
implementation that facilitates a subtype enabler in the IME settings. Refer to the
<a href="https://android.googlesource.com/platform/development/+/master/samples/SoftKeyboard/">
@@ -617,15 +530,14 @@ alt=""
<h2 id="Switching">Switching among IME Subtypes</h2>
-<p>You can allow users to switch easily among multiple IME subtypes by providing
-a switching key, such as the globe-shaped language icon, as part of the keyboard. Doing so greatly
-improves the keyboard's usability, and can help avoid user frustration.
+<p>You can allow users to switch easily among multiple IME subtypes by providing a switching key,
+such as the globe-shaped language icon, as part of the keyboard. Doing so greatly improves the
+keyboard's usability, and can help avoid user frustration.
To enable such switching, perform the following steps:</p>
<p>
<ol>
- <li>Declare <code>supportsSwitchingToNextInputMethod = "true"</code> in the
-input method's XML resource files. Your declaration
- should look similar to the following snippet:
+ <li>Declare <code>supportsSwitchingToNextInputMethod = "true"</code> in the input method's XML
+ resource files. Your declaration should look similar to the following snippet:
<pre>
&lt;input-method xmlns:android="http://schemas.android.com/apk/res/android"
android:settingsActivity="com.example.softkeyboard.Settings"
@@ -646,8 +558,7 @@ input method's XML resource files. Your declaration
<strong>Caution:</strong> Prior to Android 5.0 (API level 21),
{@link android.view.inputmethod.InputMethodManager#switchToNextInputMethod switchToNextInputMethod()}
is not aware of the <code>supportsSwitchingToNextInputMethod</code> attribute. If the user switches
-into an IME without a switching key, he or she may get stuck in that IME, unable to switch out of it
-easily.</p>
+into an IME without a switching key, he or she may get stuck in that IME, unable to switch out of it easily.</p>
<p>
@@ -662,31 +573,23 @@ easily.</p>
Provide a way for users to set options directly from the IME's UI.
</li>
<li>
- Because multiple IMEs may be installed on the device, provide a way for the
-user to switch to a
+ Because multiple IMEs may be installed on the device, provide a way for the user to switch to a
different IME directly from the input method UI.
</li>
<li>
- Bring up the IME's UI quickly. Preload or load on demand any large
-resources so that users
- see the IME as soon as they tap on a text field. Cache resources and views
-for subsequent
+ Bring up the IME's UI quickly. Preload or load on demand any large resources so that users
+ see the IME as soon as they tap on a text field. Cache resources and views for subsequent
invocations of the input method.
</li>
<li>
- Conversely, you should release large memory allocations soon after the
-input method window is
- hidden, so that applications can have sufficient memory to run. Consider
-using a delayed message
- to release resources if the IME is in a hidden state for a few seconds.
+ Conversely, you should release large memory allocations soon after the input method window is
+ hidden, so that applications can have sufficient memory to run. Consider using a delayed
+ message to release resources if the IME is in a hidden state for a few seconds.
</li>
<li>
- Make sure that users can enter as many characters as possible for the
-language or locale
- associated with the IME. Remember that users may use punctuation in
-passwords or user
- names, so your IME has to provide many different characters to allow users
-to enter a
+ Make sure that users can enter as many characters as possible for the language or locale
+ associated with the IME. Remember that users may use punctuation in passwords or user
+ names, so your IME has to provide many different characters to allow users to enter a
password and get access to the device.
</li>
</ul> \ No newline at end of file
diff --git a/docs/html/images/tools/studio-build-variant.png b/docs/html/images/tools/studio-build-variant.png
new file mode 100644
index 000000000000..a400ad459182
--- /dev/null
+++ b/docs/html/images/tools/studio-build-variant.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/heads-up.png b/docs/html/images/ui/notifications/heads-up.png
index 42fbbcd74b2f..75cc95e15234 100644
--- a/docs/html/images/ui/notifications/heads-up.png
+++ b/docs/html/images/ui/notifications/heads-up.png
Binary files differ
diff --git a/docs/html/sdk/installing/adding-packages.jd b/docs/html/sdk/installing/adding-packages.jd
index 22d055c14aef..b8d892526d76 100644
--- a/docs/html/sdk/installing/adding-packages.jd
+++ b/docs/html/sdk/installing/adding-packages.jd
@@ -1,6 +1,6 @@
page.title=Adding SDK Packages
-page.tags=studio, sdk tools, eclipse adt, sdk manager, google play services, support library
+page.tags=sdk manager
helpoutsWidget=true
@jd:body
diff --git a/docs/html/sdk/installing/index.jd b/docs/html/sdk/installing/index.jd
index 6a99952319df..68f4eb78ef11 100644
--- a/docs/html/sdk/installing/index.jd
+++ b/docs/html/sdk/installing/index.jd
@@ -1,6 +1,6 @@
page.title=Installing the Android SDK
-page.tags=studio, sdk tools, eclipse adt
+page.tags=sdk tools
helpoutsWidget=true
@jd:body
@@ -74,9 +74,9 @@ Continue: Adding SDK Packages</a></p>
<!-- ################ STUDIO ##################### -->
<div id="studio" heading="Installing Android Studio" style="display:none">
-<p>Android Studio provides everything you need to start developing apps, including
-the Android SDK tools and the Android Studio IDE (powered by IntelliJ) to
-streamline your Android app development.</p>
+<p>Android Studio provides the tools you need to start developing apps, including
+the Android Studio IDE (powered by IntelliJ) and guides you to install
+the Android SDK tools to streamline your Android app development.</p>
<p>If you didn't download Android Studio, go <a href="{@docRoot}sdk/installing/studio.html"
><b>download Android Studio now</b></a>, or switch to the
@@ -103,8 +103,9 @@ style="float:right;font-size:13px"><a href='' onclick='showAll();return false;'
<p><b>To set up Android Studio on Windows:</b></p>
<ol>
- <li>Launch the downloaded EXE file, {@code android-studio-bundle-&lt;version&gt;.exe}.</li>
- <li>Follow the setup wizard to install Android Studio.
+ <li>Unzip the file, {@code android-studio-ide-&lt;version&gt;-windows.zip} and launch the
+ <code>studio.exe</code> file.</li>
+ <li>Follow the setup wizard to install Android Studio and the SDK Tools.
<p>On some Windows systems, the launcher script does not find where Java is installed.
If you encounter this problem,
@@ -119,11 +120,10 @@ style="float:right;font-size:13px"><a href='' onclick='showAll();return false;'
</ol>
-<p>The individual tools and
-other SDK packages are saved within the Android Studio application directory.
-If you need to access the tools directly, use a terminal to navigate into the application and locate
-the {@code sdk/} directory. For example:</p>
-<p><code>\Users\&lt;user&gt;\AppData\Local\Android\android-studio\sdk\</code></p>
+<p>The individual tools and other SDK packages are saved outside the Android Studio application
+directory. If you need to access the tools directly, use a terminal to navigate to the location
+where they are installed. For example:</p>
+<p><code>\Users\&lt;user&gt;\sdk\</code></p>
@@ -134,7 +134,7 @@ the {@code sdk/} directory. For example:</p>
<p><b>To set up Android Studio on Mac OSX:</b></p>
<ol>
- <li>Open the downloaded DMG file, {@code android-studio-bundle-&lt;version&gt;.dmg}.</li>
+ <li>Unzip the downloaded zip file, {@code android-studio-ide-&lt;version&gt;-mac.zip}.</li>
<li>Drag and drop Android Studio into the Applications folder.
<p>
Depending on your security settings, when you attempt to open Android Studio, you might
@@ -143,13 +143,13 @@ the {@code sdk/} directory. For example:</p>
<strong>Allow applications downloaded from</strong>, select <strong>Anywhere</strong>.
Then open Android Studio again.</p>
</li>
+ <li>Follow the links to install the SDK outside of the Android Studio directories.</li>
</ol>
-<p>The individual tools and
-other SDK packages are saved within the Android Studio application directory.
-If you need access the tools directly, use a terminal to navigate into the application and locate
-the {@code sdk/} directory. For example:</p>
-<p><code>/Applications/Android\ Studio.app/sdk/</code></p>
+<p>The individual tools and other SDK packages are saved outside the Android Studio application
+directory. If you need access the tools directly, use a terminal to navigate into the location
+where they are installed. For example:</p>
+<p><code>/Applications/sdk/</code></p>
</div><!-- end mac -->
@@ -160,13 +160,14 @@ the {@code sdk/} directory. For example:</p>
<p><b>To set up Android Studio on Linux:</b></p>
<ol>
- <li>Unpack the downloaded Tar file, {@code android-studio-bundle-&lt;version&gt;.tgz}, into an appropriate
- location for your applications.
+ <li>Unpack the downloaded Tar file, {@code android-studio-ide-&lt;version&gt;-linux.zip}, into an
+ appropriate location for your applications.
<li>To launch Android Studio, navigate to the {@code android-studio/bin/} directory
in a terminal and execute {@code studio.sh}.
<p>You may want to add {@code android-studio/bin/} to your PATH environmental
variable so that you can start Android Studio from any directory.</p>
</li>
+ <li>Follow the links to install the SDK outside of the Android Studio directories.</li>
</ol>
</div><!-- end linux -->
@@ -217,11 +218,12 @@ style="float:right;font-size:13px"><a href='' onclick='showAll();return false;'
<p>Your download package is an executable file that starts an installer. The installer checks your machine
for required tools, such as the proper Java SE Development Kit (JDK) and installs it if necessary.
- The installer then saves the Android SDK Tools into a default location (or you can specify the location).</p>
+ The installer then saves the Android SDK Tools to a specified the location outside of the Android
+ Studio directories.</p>
<ol>
<li>Double-click the executable ({@code .exe} file) to start the install.</li>
-<li>Make a note of the name and location in which it saves the SDK on your system&mdash;you will need to
+<li>Make a note of the name and location where you save the SDK on your system&mdash;you will need to
refer to the SDK directory later when using
the SDK tools from the command line.</li>
<li>Once the installation completes, the installer starts the Android SDK Manager.
@@ -237,8 +239,8 @@ the SDK tools from the command line.</li>
<p><b>To get started on Mac OSX:</b></p>
<p>Unpack the ZIP file you've downloaded. By default, it's unpacked
-into a directory named <code>android-sdk-mac_x86</code>. Move it to an appropriate location on your machine,
-such as a "Development" directory in your home directory.</p>
+into a directory named <code>android-sdk-mac_x86</code>. Move it to an appropriate location on your
+machine, such as a "Development" directory in your home directory.</p>
<p>Make a note of the name and location of the SDK directory on your system&mdash;you will need to
refer to the SDK directory later when using
@@ -253,9 +255,8 @@ the SDK tools from the command line.</p>
<p><b>To get started on Linux:</b></p>
-<p>Unpack the {@code .tgz} file you've downloaded. By default, the SDK files are unpacked
-into a directory named <code>android-sdk-linux_x86</code>. Move it to an appropriate location on your machine,
-such as a "Development" directory in your home directory.</p>
+<p>Unpack the {@code .zip} file you've downloaded. The SDK files are download separately to a
+user-specified directory. </p>
<p>Make a note of the name and location of the SDK directory on your system&mdash;you will need to
refer to the SDK directory later when using
diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd
index b0567e7c1b11..6991dea301d9 100644
--- a/docs/html/sdk/installing/studio.jd
+++ b/docs/html/sdk/installing/studio.jd
@@ -194,12 +194,12 @@ This is the Android Software Development Kit License Agreement
href="" style="display:none;width:368px;margin:0 auto;display:block;font-size:18px" ></a>
<div style="margin:20px 0 0 0">
-<p style="margin-bottom:8px">This download includes:</p>
+<p style="margin-bottom:8px">This installation includes:</p>
<ul style="margin-bottom:20px">
-<li>Android Studio Beta</li>
-<li>All the Android SDK Tools to design, test, and debug your app</li>
-<li>A version of the Android platform to compile your app</li>
-<li>A version of the Android system image to run your app in the emulator</li>
+ <li>Android Studio Beta</li>
+ <li>All the Android SDK Tools to design, test, and debug your app</li>
+ <li>A version of the Android platform to compile your app</li>
+ <li>A version of the Android system image to run your app in the emulator</li>
</ul>
</div>
@@ -244,43 +244,41 @@ download (or continue to use)
<th>Platform</th>
<th>Package</th>
<th>Size</th>
- <th>MD5 Checksum</th>
+ <th>SHA Sum</th>
</tr>
<tr>
<td>Windows</td>
<td>
<a onclick="return onDownload(this)" id="win-studio"
- href="https://dl.google.com/android/studio/install/0.8.6/android-studio-bundle-135.1339820-windows.exe">
- android-studio-bundle-135.1339820-windows.exe
+ href="https://dl.google.com/dl/android/studio/ide-zips/0.8.14/android-studio-ide-135.1538390-windows.zip">android-studio-ide-135.1538390-windows.zip
</a>
</td>
- <td>379497130 bytes</td>
- <td>024e002b8c8fa7dcd2ff69fd69e06e56</td>
+ <td>177343814 bytes</td>
+ <td>b533480200ba893616c73b32477e66ebb357a1b3</td>
</tr>
<tr>
<td><nobr>Mac OS X</nobr></td>
<td>
<a onclick="return onDownload(this)" id="mac-studio"
- href="https://dl.google.com/android/studio/install/0.8.6/android-studio-bundle-135.1339820-mac.dmg">
- android-studio-bundle-135.1339820-mac.dmg
+ href="https://dl.google.com/dl/android/studio/ide-zips/0.8.14/android-studio-ide-135.1538390-mac.zip">
+ android-studio-ide-135.1538390-mac.zip
</a>
</td>
- <td>368507143 bytes</td>
- <td>4143f2aa556634eae91701965d88899b</td>
+ <td>176745627 bytes</td>
+ <td>4070e6f6a44d042266f46f1f2f9ca3448ac23f8cd</td>
</tr>
<tr>
<td>Linux</td>
<td>
<a onclick="return onDownload(this)" id="linux-studio"
- href="https://dl.google.com/android/studio/install/0.8.6/android-studio-bundle-135.1339820-linux.tgz">
- android-studio-bundle-135.1339820-linux.tgz
+ href="https://dl.google.com/dl/android/studio/ide-zips/0.8.14/android-studio-ide-135.1538390-linux.zip">android-studio-ide-135.1538390-linux.zip
</a>
</td>
- <td>417631443 bytes</td>
- <td>fa403762ecd0a5da87acbeff485f81cc</td>
+ <td>176358193 bytes</td>
+ <td>718356b49254f6c4e55c64b99164d311995205dd</td>
</tr>
</table>
@@ -301,44 +299,48 @@ download (or continue to use)
<tr>
<td>
<ul>
- <li>Microsoft Windows 8, 7, Vista, 2003, or XP (32 or 64 bit)</li>
- <li>1 GB of RAM minimum, 2 GB recommended</li>
- <li>400 MB of disk space</li>
- <li>At least 1 GB of additional disk space for the Android SDK, emulator system images, and caches</li>
+ <li>Microsoft Windows 8/7/Vista/2003 (32 or 64 bit)</li>
+ <li>2 GB RAM minimum, 4 GB RAM recommended</li>
+ <li>400 MB disk space </li>
+ <li>At least 1 GB for Android SDK, emulator system images, and caches</li>
<li>1280x800 minimum screen resolution</li>
- <li>Java Development Kit (JDK) 6 or higher</li>
+ <li>Java Development Kit (JDK) 7 or higher</li>
+ <li>(Optional for accelerated emulator: Intel processor with support for Intel VT-x, Intel
+ EM64T (Intel 64), and Execute Disable (XD) Bit functionality)</li>
</ul>
</td>
<td>
<ul>
<li>Mac OS X 10.8.5 or higher, up to 10.9 (Mavericks)</li>
- <li>1 GB of RAM minimum, 2 GB recommended</li>
- <li>400 MB of disk space</li>
- <li>At least 1 GB of additional disk space for the Android SDK, emulator system images, and caches</li>
+ <li>2 GB RAM minimum, 4 GB RAM recommended</li>
+ <li>400 MB disk space</li>
+ <li>At least 1 GB for Android SDK, emulator system images, and caches</li>
<li>1280x800 minimum screen resolution</li>
- <li>Java Runtime Environment (JRE) 6 *</li>
- <li>Java Development Kit (JDK) 6 or JDK 7</li>
+ <li>Java Runtime Environment (JRE) 6</li>
+ <li>Java Development Kit (JDK) 7 or higher
+ <p>On Mac OS, run Android Studio with Java Runtime Environment (JRE) 6 for optimized font
+ rendering. You can then configure your project to use Java Development Kit (JDK) JDK 7.</p></li>
+ <li>(Optional for accelerated emulator: Intel processor with support for Intel VT-x, Intel
+ EM64T (Intel 64), and Execute Disable (XD) Bit functionality)</li>
</ul>
-<p>* On Mac OS, run Android Studio with Java Runtime Environment (JRE) 6 for optimized font
-rendering. You can then configure your project to use Java Development Kit (JDK) 6 or JDK 7.</p>
+
</td>
<td>
<ul>
- <li>64-bit distribution capable of running 32-bit applications</li>
+ <li>GNOME or KDE desktop.</li>
+ <li>Tested on Ubuntu 12.04, Precise Pangolin (64-bit distribution capable of running 32-bit
+ applications)</li>
<li>GNU C Library (glibc) 2.11 or later is required.</li>
- <li>Tested on Ubuntu 12.04, Precise Pangolin</li>
- <li>GNOME or KDE desktop</li>
- <li>1 GB of RAM minimum, 2 GB recommended</li>
- <li>400 MB of disk space</li>
- <li>At least 1 GB of additional disk space for the Android SDK, emulator system images, and caches</li>
+ <li>2 GB RAM minimum, 4 GB RAM recommended</li>
+ <li>400 MB disk space</li>
+ <li>At least 1 GB for Android SDK, emulator system images, and caches</li>
<li>1280x800 minimum screen resolution</li>
- <li>Oracle Java Development Kit (JDK) 6 or JDK 7</li>
+ <li>Java Development Kit (JDK) 7 or higher</li>
</ul>
</td>
</tr>
</table>
-<p class="note"><strong>Note:</strong> Java Development Kit (JDK) 7 is required if you're targeting
-the Android L Developer Preview.</p>
+<p class="note"><strong>Note:</strong> The full SDK/NDK requires 13 GB of disk space.</p>
</div><!-- end pax -->
@@ -425,7 +427,7 @@ installation.</p>
<p><strong>Caution:</strong> Replacing your existing installation of
Android Studio will remove any additional SDK packages you've installed, such as target
platforms, system images, and sample apps. To preserve these, copy them from your current
-SDK directory under Android Studio to a temporary location
+SDK directory to a temporary location
before installing the update. Then move them back once the update is complete.
If you fail to copy these packages, then you can instead download them again through
the Android SDK Manager.</p>
@@ -453,6 +455,17 @@ style="vertical-align:bottom;margin:0;height:19px" /> in the toolbar.</p>
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>Android Studio v0.8.14</a> <em>(October 2014)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+ <p>See <a href="http://tools.android.com/recent">tools.android.com</a> for a full list of changes.</p>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>Android Studio v0.8.6</a> <em>(August 2014)</em>
</p>
@@ -650,7 +663,7 @@ for possible resolutions to known issues: <a href="http://tools.android.com/know
if (os) {
/* set up primary ACE download button */
$('#download-ide-button').show();
- $('#download-ide-button').append("Download Android Studio Beta <span class='small'>v0.8.6</span>"
+ $('#download-ide-button').append("Download Android Studio Beta <span class='small'>v0.8.14</span>"
+ "<br/> <span class='small'>with the Android SDK for " + os + "</span>");
$('#download-ide-button').click(function() {return onDownload(this,true);}).attr('href', bundlename);
diff --git a/docs/html/tools/building/multidex.jd b/docs/html/tools/building/multidex.jd
new file mode 100644
index 000000000000..49cde8ccddce
--- /dev/null
+++ b/docs/html/tools/building/multidex.jd
@@ -0,0 +1,458 @@
+page.title=Building Apps with Over 65K Methods
+page.tags="65536","references","max","65k","dex","64k","multidex","multi-dex","methods"</p>
+
+@jd:body
+
+<div id="qv-wrapper">
+ <div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#about">
+ About the 65K Reference Limit</a>
+ <ol>
+ <li><a href="#mdex-pre-l">Multidex support prior to Android 5.0</a></li>
+ <li><a href="#mdex-on-l">Multidex support for Android 5.0 and higher</a></li>
+ </ol>
+ </li>
+ <li><a href="#avoid">
+ Avoiding the 65K Limit</a></li>
+ <li><a href="#mdex-gradle">
+ Configuring Your App for Multidex with Gradle</a>
+ <ol>
+ <li><a href="#limitations">
+ Limitations of the multidex support library</a></li>
+ </ol>
+ </li>
+ <li><a href="#dev-build">
+ Optimizing Multidex Development Builds</a>
+ <ol>
+ <li><a href="#variants-studio">
+ Using Build Variants in Android Studio</a></li>
+ </ol>
+ </li>
+ <li><a href="#testing">
+ Testing Multidex Apps</a></li>
+ </ol>
+
+ <h2>See Also</h2>
+ <ol>
+ <li><a href="{@docRoot}tools/help/proguard.html">ProGuard</a>
+ </li>
+ </ol>
+ </div>
+</div>
+
+
+<p>
+ As the Android platform has continued to grow, so has the size of Android apps. When your
+ application and the libraries it references reach a certain size, you encounter build errors that
+ indicate your app has reached a limit of the Android app build architecture. Earlier versions of
+ the build system report this error as follows:
+</p>
+
+<pre>
+Conversion to Dalvik format failed:
+Unable to execute dex: method ID not in [0, 0xffff]: 65536
+</pre>
+
+<p>
+ More recent versions of the Android build system display a different error, which is an
+ indication of the same problem:
+</p>
+
+<pre>
+trouble writing output:
+Too many field references: 131000; max is 65536.
+You may try using --multi-dex option.
+</pre>
+
+<p>
+ Both these error conditions display a common number: 65,536. This number is significant in that
+ it represents the total number of references that can be invoked by the code within a single
+ Dalvik Executable (dex) bytecode file. If you have built an Android app and received this error,
+ then congratulations, you have a lot of code! This document explains how to move past this
+ limitation and continue building your app.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> The guidance provided in this document supersedes the guidance given in
+ the Android Developers blog post <a href=
+ "http://android-developers.blogspot.com/2011/07/custom-class-loading-in-dalvik.html">Custom Class
+ Loading in Dalvik</a>.
+</p>
+
+
+<h2 id="about">About the 65K Reference Limit</h2>
+
+<p>
+ Android application (APK) files contain executable bytecode files in the form of <a href=
+ "https://source.android.com/devices/tech/dalvik/">Dalvik</a> Executable (DEX) files, which
+ contain the compiled code used to run your app. The Dalvik Executable specification limits the
+ total number of methods that can be referenced within a single DEX file to 65,536, including
+ Android framework methods, library methods, and methods in your own code. Getting past this limit
+ requires that you configure your app build process to generate more than one DEX file, known as a
+ <em>multidex</em> configuration.
+</p>
+
+
+<h3 id="mdex-pre-l">Multidex support prior to Android 5.0</h3>
+
+<p>
+ Versions of the platform prior to Android 5.0 use the Dalvik runtime for executing app code. By
+ default, Dalvik limits apps to a single classes.dex bytecode file per APK. In order to get around
+ this limitation, you can use the <a href="{@docRoot}tools/support-library/features.html#multidex">
+ multidex support library</a>, which becomes part of the primary DEX file of your app and then
+ manages access to the additional DEX files and the code they contain.
+</p>
+
+
+<h3 id="mdex-on-l">Multidex support for Android 5.0 and higher</h3>
+
+<p>
+ Android 5.0 and higher uses a runtime called ART which natively supports loading multiple dex
+ files from application APK files. ART performs pre-compilation at application install time which
+ scans for classes(..N).dex files and compiles them into a single .oat file for execution by the
+ Android device. For more information on the Android 5.0 runtime, see <a href=
+ "https://source.android.com/devices/tech/dalvik/art.html">Introducing ART</a>.
+</p>
+
+
+<h2 id="avoid">Avoiding the 65K Limit</h2>
+
+<p>
+ Before configuring your app to enable use of 65K or more method references, you should take steps
+ to reduce the total number of references called by your app code, including methods defined by
+ your app code or included libraries. The following strategies can help you avoid hitting the dex
+ reference limit:
+</p>
+
+<ul>
+ <li>
+ <strong>Review your app's direct and transitive dependencies</strong> - Ensure any large library
+ dependency you include in your app is used in a manner that outweighs the amount of code
+ being added to the application. A common anti-pattern is to include a very large library
+ because a few utility methods were useful. Reducing your app code dependencies can often help
+ you avoid the dex reference limit.
+ </li>
+ <li>
+ <strong>Remove unused code with ProGuard</strong> - Configure the <a href=
+ "{@docRoot}tools/help/proguard.html">ProGuard</a> settings for your app to run ProGuard and
+ ensure you have shrinking enabled for release builds. Enabling shrinking ensures you
+ are not shipping unused code with your APKs.
+ </li>
+</ul>
+
+
+<p>
+ Using these techniques can help you avoid the build configuration changes required to enable more
+ method references in your app. These steps can also decrease the size of your APKs, which is
+ particularly important for markets where bandwidth costs are high.
+</p>
+
+
+<h2 id="mdex-gradle">Configuring Your App for Multidex with Gradle</h2>
+
+<p>
+ The Android plugin for Gradle available in Android SDK Build Tools 21.1 and higher supports
+ multidex as part of your build configuration. Make sure you update the Android SDK Build Tools
+ tools and the Android Support Repository to the latest version using the <a href=
+ "{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> before attempting to configure your app
+ for multidex.
+</p>
+
+<p>
+ Setting up your app development project to use a multidex configuration requires that you make a
+ few modifications to your app development project. In particular you need to perform the
+ following steps:
+</p>
+
+<ul>
+ <li>Change your Gradle build configuration to enable multidex</li>
+ <li>Modify your manifest to reference the {@link android.support.multidex.MultiDexApplication}
+ class</li>
+</ul>
+
+<p>
+ Modify your app Gradle build file configuration to include the support library and enable
+ multidex output, as shown in the following Gradle build file snippet:
+</p>
+
+<pre>
+android {
+ compileSdkVersion 21
+ buildToolsVersion "21.1.0"
+
+ defaultConfig {
+ ...
+ minSdkVersion 14
+ targetSdkVersion 21
+ ...
+
+ // Enabling multidex support.
+ multiDexEnabled true
+ }
+ ...
+}
+
+dependencies {
+ compile 'com.android.support:multidex:1.0.0'
+}
+</pre>
+
+<p class="note">
+ <strong>Note:</strong> You can specify the <code>multiDexEnabled</code> setting in the
+ <code>defaultConfig,</code> <code>buildType</code>, or <code>productFlavor</code> sections of
+ your Gradle build file.
+</p>
+
+
+<p>
+ In your manifest add the {@link android.support.multidex.MultiDexApplication} class from the
+ multidex support library to the application element.
+</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.multidex.myapplication"&gt;
+ &lt;application
+ ...
+ android:name="android.support.multidex.MultiDexApplication"&gt;
+ ...
+ &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+<p>
+ When these configuration settings are added to an app, the Android build tools construct a
+ primary dex (classes.dex) and supporting (classes2.dex, classes3.dex) as needed. The build system
+ will then package them into an APK file for distribution.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> If your app uses extends the {@link android.app.Application} class, you
+ can override the attachBaseContext() method and call MultiDex.install(this) to enable multidex.
+ For more information, see the {@link android.support.multidex.MultiDexApplication} reference
+ documentation.
+</p>
+
+<h3 id="limitations">Limitations of the multidex support library</h3>
+
+<p>
+ The multidex support library has some known limitations that you should be aware of and test for
+ when you incorporate it into your app build configuration:
+</p>
+
+<ul>
+ <li>The installation of .dex files during startup onto a device's data partition is complex and
+ can result in Application Not Responding (ANR) errors if the secondary dex files are large. In
+ this case, you should apply code shrinking techniques with ProGuard to minimize the size of dex
+ files and remove unused portions of code.
+ </li>
+
+ <li>Applications that use multidex may not start on devices that run versions of the platform
+ earlier than Android 4.0 (API level 14) due to a Dalvik linearAlloc bug (Issue <a href=
+ "http://b.android.com/22586">22586</a>). If you are targeting API levels earlier than 14, make
+ sure to perform testing with these versions of the platform as your application can have issues
+ at startup or when particular groups of classes are loaded. Code shrinking can reduce or possibly
+ eliminate these potential issues.
+ </li>
+
+ <li>Applications using a multidex configuration that make very large memory allocation
+ requests may crash during run time due to a Dalvik linearAlloc limit (Issue <a href=
+ "http://b.android.com/78035">78035</a>). The allocation limit was increased in Android 4.0 (API
+ level 14), but apps may still run into this limit on Android versions prior to
+ Android 5.0 (API level 21).
+ </li>
+
+ <li>There are complex requirements regarding what classes are needed in the primary dex file when
+ executing in the Dalvik runtime. The Android build tooling updates handle the Android
+ requirements, but it is possible that other included libraries have additional dependency
+ requirements including the use of introspection or invocation of Java methods from native code.
+ Some libraries may not be able to be used until the multidex build tools are updated to allow you
+ to specify classes that must be included in the primary dex file.
+ </li>
+</ul>
+
+
+<h2 id="dev-build">Optimizing Multidex Development Builds</h2>
+
+<p>
+ A multidex configuration requires significantly increased build processing time because the build
+ system must make complex decisions about what classes must be included in the primary DEX file
+ and what classes can be included in secondary DEX files. This means that routine builds performed
+ as part of the development process with multidex typically take longer and can potentially slow
+ your development process.
+</p>
+
+<p>
+ In order to mitigate the typically longer build times for multidex output, you should create two
+ variations on your build output using the Android plugin for Gradle
+ <a href="http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Product-flavors">
+ {@code productFlavors}</a>: a development flavor and a production flavor.
+</p>
+
+<p>
+ For the development flavor, set a minimum SDK version of 21. This setting generates multidex
+ output much faster using the ART-supported format. For the release flavor, set a minimum SDK
+ version which matches your actual minimum support level. This setting generates a multidex APK
+ that is compatible with more devices, but takes longer to build.
+</p>
+
+<p>
+ The following build configuration sample demonstrates the how to set up these flavors in a Gradle
+ build file:
+</p>
+
+<pre>
+android {
+ productFlavors {
+ // Define separate dev and prod product flavors.
+ dev {
+ // dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
+ // to pre-dex each module and produce an APK that can be tested on
+ // Android Lollipop without time consuming dex merging processes.
+ minSdkVersion 21
+ }
+ prod {
+ // The actual minSdkVersion for the application.
+ minSdkVersion 14
+ }
+ }
+ ...
+ buildTypes {
+ release {
+ runProguard true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'),
+ 'proguard-rules.pro'
+ }
+ }
+}
+dependencies {
+ compile 'com.android.support:multidex:1.0.0'
+}
+</pre>
+
+<p>
+ After you have completed this configuration change, you can use the <code>devDebug</code> variant
+ of your app, which combines the attributes of the <code>dev</code> productFlavor and the
+ <code>debug</code> buildType. Using this target creates a debug app with proguard disabled,
+ multidex enabled, and minSdkVersion set to Android API level 21. These settings cause the Android
+ gradle plugin to do the following:
+</p>
+
+<ol>
+ <li>Build each module of the application (including dependencies) as separate dex files. This is
+ commonly referred to as pre-dexing.
+ </li>
+
+ <li>Include each dex file in the APK without modification.
+ </li>
+
+ <li>Most importantly, the module dex files will not be combined, and so the long-running
+ calculation to determine the contents of the primary dex file is avoided.
+ </li>
+</ol>
+
+<p>
+ These settings result in fast, incremental builds, because only the dex files of modified modules
+ are recomputed and repackaged into the APK file. The APK that results from these builds can be
+ used to test on Android 5.0 devices only. However, by implementing the configuration as a flavor,
+ you preserve the ability to perform normal builds with the release-appropriate minimum SDK level
+ and proguard settings.
+</p>
+
+<p>
+ You can also build the other variants, including a <code>prodDebug</code> variant
+ build, which takes longer to build, but can be used for testing outside of development.
+ Within the configuration shown, the <code>prodRelease</code> variant would be the final testing
+ and release version. If you are executing gradle tasks from the command line, you can use
+ standard commands with <code>DevDebug</code> appended to the end (such as <code>./gradlew
+ installDevDebug</code>). For more information about using flavors with Gradle tasks, see the
+ <a href="http://tools.android.com/tech-docs/new-build-system/user-guide">Gradle Plugin User
+ Guide</a>.
+</p>
+
+<p>
+ <strong>Tip:</strong> You can also provide a custom manifest, or a custom application class for each
+ flavor, allowing you to use the support library MultiDexApplication class, or calling
+ MultiDex.install() only for the variants that need it.
+</p>
+
+
+<h3 id="variants-studio">Using Build Variants in Android Studio</h3>
+
+<p>
+ Build variants can be very useful for managing the build process when using multidex. Android
+ Studio allows you to select these build variants in the user interface.
+</p>
+
+<p>
+ To have Android Studio build the "devDebug" variant of your app:
+</p>
+
+<ol>
+ <li>Open the <em>Build Variants</em> window from the left-sidebar. The option is located next to
+ <em>Favorites</em>.
+ </li>
+
+ <li>Click the name of the build variant to select a different variant, as shown in Figure 1.
+ </li>
+</ol>
+
+<img src="{@docRoot}images/tools/studio-build-variant.png" alt="" height="XXX" id="figure1">
+<p class="img-caption">
+ <strong>Figure 1.</strong> Screen shot of the Android Studio left panel showing a build variant.
+</p>
+
+<p class="note">
+ <strong>Note</strong>: The option to open this window is only available after you have
+ successfully synchronized Android Studio with your Gradle build file using the <strong>Tools &gt;
+ Android &gt; Sync Project with Gradle Files</strong> command.
+</p>
+
+
+<h2 id="testing">Testing Multidex Apps</h2>
+
+<p>
+ Testing apps that use multidex configuration require some additional steps and configuration.
+ Since the location of code for classes is not within a single DEX file, instrumentation tests do
+ not run properly unless configured for multidex.
+</p>
+
+<p>
+ When testing a multidex app with instrumentation tests, use
+ <a href="{@docRoot}reference/com/android/test/runner/MultiDexTestRunner.html">
+ MultiDexTestRunner</a> from the multidex testing support library. The following sample
+ {@code build.gradle} file, demonstrates how to configure your build to use this test runner:
+</p>
+
+<pre>
+android {
+ defaultConfig {
+ ...
+ testInstrumentationRunner "android.support.multidex.MultiDexTestRunner"
+ }
+}
+
+dependencies {
+ androidTestCompile 'com.android.support:multidex-instrumentation:1.0.0'
+}
+</pre>
+
+<p>
+ You may use the instrumentation test runner class directly or extend it to fit your testing
+ needs. Alternatively, you can override onCreate in existing instrumentations like this:
+</p>
+
+<pre>
+public void onCreate(Bundle arguments) {
+ MultiDex.install(getTargetContext());
+ super.onCreate(arguments);
+ ...
+}
+</pre>
+
+<p class="note">
+ <strong>Note:</strong> Use of multidex for creating a test APK is not currently supported.
+</p> \ No newline at end of file
diff --git a/docs/html/tools/revisions/build-tools.jd b/docs/html/tools/revisions/build-tools.jd
index 6f0775561ffe..ec88efc744be 100644
--- a/docs/html/tools/revisions/build-tools.jd
+++ b/docs/html/tools/revisions/build-tools.jd
@@ -77,6 +77,18 @@ listing in the Android SDK Manager.</p>
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>Build Tools, Revision 21.1</a> <em>(October 2014)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+ <p>Added multidex file support for APKs and Jack suppport to address the 64K method reference
+ limit.</p>
+ </div>
+</div>
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>Build Tools, Revision 21.0.2</a> <em>(October 2014)</em>
</p>
<div class="toggle-content-toggleme">
diff --git a/docs/html/tools/revisions/platforms.jd b/docs/html/tools/revisions/platforms.jd
index 85b9c5ede3a6..ef8575af38eb 100644
--- a/docs/html/tools/revisions/platforms.jd
+++ b/docs/html/tools/revisions/platforms.jd
@@ -88,7 +88,7 @@ class="toggle-content-img" alt="" />Revision 2</a> <em>(October 2014)</em>
<div class="toggle-content-toggleme">
- <p>Added location APIs support for Wear.</p>
+ <p>Updated the rendering library. </p>
<p>Dependencies:</p>
<ul>
diff --git a/docs/html/tools/support-library/features.jd b/docs/html/tools/support-library/features.jd
index 44c504547db8..3ebfc8989fc8 100644
--- a/docs/html/tools/support-library/features.jd
+++ b/docs/html/tools/support-library/features.jd
@@ -8,6 +8,7 @@ page.title=Support Library Features
<h2>In this document</h2>
<ol>
<li><a href="#v4">v4 Support Library</a></li>
+ <li><a href="#multidex">Multidex Support Library</a></li>
<li><a href="#v7">v7 Support Libraries</a>
<ol>
<li><a href="#v7-appcompat">v7 appcompat library</a></li>
@@ -145,6 +146,34 @@ com.android.support:support-v4:21.0.+
<p>This dependency notation specifies the release version 21.0.0 or higher.</p>
+<h2 id="multidex">Multidex Support Library</h2>
+
+<p>
+ This library provides support for building apps with multiple Dalvik Executable (DEX) files.
+ Apps that reference more than 65536 methods are required to use multidex configurations. For
+ more information about using multidex, see <a href="{@docRoot}tools/building/multidex.html">
+ Building Apps with Over 65K Methods</a>.
+</p>
+
+<p>
+ This library is located in the {@code &lt;sdk&gt;/extras/android/support/multidex/} directory
+ after you download the Android Support Libraries. The library does not contain user interface
+ resources. To include it in your application project, follow the instructions for <a href=
+ "{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
+ resources</a>.
+</p>
+
+<p>
+ The Gradle build script dependency identifier for this library is as follows:
+</p>
+
+<pre>
+com.android.support:multidex:1.0.+
+</pre>
+
+<p>This dependency notation specifies the release version 1.0.0 or higher.</p>
+
+
<h2 id="v7">v7 Support Libraries</h2>
<p>There are several libraries designed to be used with Android 2.1 (API level 7) and higher.
diff --git a/docs/html/tools/testing/activity_testing.jd b/docs/html/tools/testing/activity_testing.jd
index 88ac9b2351f7..8baa35de88e8 100644
--- a/docs/html/tools/testing/activity_testing.jd
+++ b/docs/html/tools/testing/activity_testing.jd
@@ -242,7 +242,7 @@ parent.link=index.html
This changes when you run tests against the application. With instrumentation-based classes,
you can invoke methods against the UI of the application under test. The other test classes
don't allow this. To run an entire test method on the UI thread, you can annotate the thread
- with <code>@UIThreadTest</code>. Notice that this will run <em>all</em> of the method statements
+ with <code>@UiThreadTest</code>. Notice that this will run <em>all</em> of the method statements
on the UI thread. Methods that do not interact with the UI are not allowed; for example, you
can't invoke <code>Instrumentation.waitForIdleSync()</code>.
</p>
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index 8eb9cbfcc116..ac331858273b 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -66,10 +66,17 @@
<li class="nav-section">
- <div class="nav-section-header"><a href="<?cs var:toroot ?>tools/building/index.html"><span class="en">Building and Running</span></a></div>
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot ?>tools/building/index.html">
+ <span class="en">Building and Running</span></a>
+ </div>
<ul>
- <li><a href="<?cs var:toroot ?>tools/building/building-eclipse.html"><span class="en">From Eclipse with ADT</span></a></li>
- <li><a href="<?cs var:toroot ?>tools/building/building-cmdline.html"><span class="en">From the Command Line</span></a></li>
+ <li><a href="<?cs var:toroot ?>tools/building/building-eclipse.html">
+ <span class="en">From Eclipse with ADT</span></a></li>
+ <li><a href="<?cs var:toroot ?>tools/building/building-cmdline.html">
+ <span class="en">From the Command Line</span></a></li>
+ <li><a href="<?cs var:toroot ?>tools/building/multidex.html">
+ <span class="en">Apps Over 65K Methods</span></a></li>
</ul>
</li>
diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd
index c0826427fd40..0430cdd8d0c4 100644
--- a/docs/html/training/basics/firstapp/building-ui.jd
+++ b/docs/html/training/basics/firstapp/building-ui.jd
@@ -1,7 +1,7 @@
page.title=Building a Simple User Interface
trainingnavtop=true
-page.tags=ui, views, layouts, widgets, string resources
+page.tags=ui
helpoutsWidget=true
@jd:body
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index 418eb687bb48..2e061036cd89 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -1,6 +1,6 @@
page.title=Creating an Android Project
-page.tags=eclipse adt, sdk tools, project setup
+page.tags=project setup
helpoutsWidget=true
trainingnavtop=true
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
index f9dcba4e59b7..71f66dd74de0 100644
--- a/docs/html/training/basics/firstapp/starting-activity.jd
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -4,7 +4,7 @@ parent.link=index.html
trainingnavtop=true
-page.tags=input events, intents, activity lifecycle
+page.tags=intents
helpoutsWidget=true
@jd:body
diff --git a/docs/html/training/wearables/apps/layouts.jd b/docs/html/training/wearables/apps/layouts.jd
index e62d3e5b8435..a35acb07182f 100644
--- a/docs/html/training/wearables/apps/layouts.jd
+++ b/docs/html/training/wearables/apps/layouts.jd
@@ -90,9 +90,10 @@ PendingIntent notificationPendingIntent = PendingIntent.getActivity(this, 0, not
</ol>
<h2 id="UiLibrary">Create Layouts with the Wearable UI Library</h2>
<p>
-There's an unofficial UI library that is automatically included when you create your wearable
-app with the Android Studio Project Wizard. You can also add the library to your <code>build.gradle</code>
+The Wearable UI Library is automatically included when you create your wearable
+app with the Android Studio Project Wizard. You can also add this library to your <code>build.gradle</code>
file with the following dependency declaration:
+</p>
<pre>
dependencies {
@@ -101,8 +102,11 @@ dependencies {
compile 'com.google.android.gms:play-services-wearable:+'
}
</pre>
-This library helps you build UIs that are designed for wearables. Here are some of the major classes:
-</p>
+
+<p>This library helps you build UIs that are designed for wearables. For more information, see
+<a href="{@docRoot}training/wearables/ui/index.html">Creating Custom UIs for Wear Devices</a>.</p>
+
+<p>Here are some of the major classes in the Wearable UI Library:</p>
<ul>
<li><code>BoxInsetLayout</code> - A FrameLayout that's aware of screen shape and can box its
diff --git a/docs/html/training/wearables/data-layer/index.jd b/docs/html/training/wearables/data-layer/index.jd
index 39d65616c2c3..6ef3fc7ac617 100644
--- a/docs/html/training/wearables/data-layer/index.jd
+++ b/docs/html/training/wearables/data-layer/index.jd
@@ -8,7 +8,7 @@ page.title=Sending and Syncing Data
<h2>Dependencies and prerequisites</h2>
<ul>
<li>Android 4.3 (API Level 18) or higher on the handset device</li>
- <li>The latest version of <a href="{@docRoot}google/play">Google Play services</a></li>
+ <li>The latest version of <a href="{@docRoot}google/play-services/index.html">Google Play services</a></li>
<li>An Android Wear device or Wear AVD</li>
</ul>
</div>
diff --git a/docs/html/training/wearables/notifications/pages.jd b/docs/html/training/wearables/notifications/pages.jd
index d74c8ea40b8c..6315037e00f6 100644
--- a/docs/html/training/wearables/notifications/pages.jd
+++ b/docs/html/training/wearables/notifications/pages.jd
@@ -57,15 +57,14 @@ Notification secondPageNotification =
.setStyle(secondPageStyle)
.build();
-// Add second page with wearable extender and extend the main notification
-Notification twoPageNotification =
- new WearableExtender()
- .addPage(secondPageNotification)
- .extend(notificationBuilder)
- .build();
+// Extend the notification builder with the second page
+Notification notification = notificationBuilder
+ .extend(new NotificationCompat.WearableExtender()
+ .addPage(secondPageNotification))
+ .build();
// Issue the notification
notificationManager =
NotificationManagerCompat.from(this);
-notificationManager.notify(notificationId, twoPageNotification);
+notificationManager.notify(notificationId, notification);
</pre> \ No newline at end of file
diff --git a/docs/html/training/wearables/notifications/voice-input.jd b/docs/html/training/wearables/notifications/voice-input.jd
index 4a27826e56dc..3ce1c8006d3f 100644
--- a/docs/html/training/wearables/notifications/voice-input.jd
+++ b/docs/html/training/wearables/notifications/voice-input.jd
@@ -37,7 +37,7 @@ so you can type replies instead.</p>
<h2 id="VoiceInput">Define the Voice Input</h2>
-<p>To create an action that supports voice input, create an instance of
+<p>To create an action that supports voice input, create an instance of
{@link android.support.v4.app.RemoteInput.Builder} that you can add to your notification action.
This class's constructor accepts a string that the system uses as
the key for the voice input, which you'll later use to retrieve the text of the
@@ -166,9 +166,8 @@ which is referenced by the <code>EXTRA_VOICE_REPLY</code> key that is used in th
private CharSequence getMessageText(Intent intent) {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
- if (remoteInput != null) {
- return remoteInput.getCharSequence(EXTRA_VOICE_REPLY);
- }
+ if (remoteInput != null) {
+ return remoteInput.getCharSequence(EXTRA_VOICE_REPLY);
}
return null;
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index c2e93a7ae479..d2799e1a496c 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -16,6 +16,8 @@
package android.graphics.drawable;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.ColorFilter;
@@ -41,6 +43,7 @@ import com.android.internal.R;
*/
public class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable,
Animatable {
+ private static final String TAG = "AnimatedRotateDrawable";
private AnimatedRotateState mState;
private boolean mMutated;
@@ -186,6 +189,11 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
}
@Override
+ public boolean canApplyTheme() {
+ return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
+ }
+
+ @Override
public void invalidateDrawable(Drawable who) {
final Callback callback = getCallback();
if (callback != null) {
@@ -254,83 +262,113 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
}
@Override
- public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
+ public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
+ @NonNull AttributeSet attrs, @Nullable Theme theme)
throws XmlPullParserException, IOException {
-
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimatedRotateDrawable);
-
super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible);
+ updateStateFromTypedArray(a);
+ a.recycle();
- TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX);
- final boolean pivotXRel = tv.type == TypedValue.TYPE_FRACTION;
- final float pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+ inflateChildElements(r, parser, attrs, theme);
- tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY);
- final boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION;
- final float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+ init();
+ }
- setFramesCount(a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12));
- setFramesDuration(a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150));
+ @Override
+ public void applyTheme(@Nullable Theme t) {
+ super.applyTheme(t);
- final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0);
- Drawable drawable = null;
- if (res > 0) {
- drawable = r.getDrawable(res, theme);
+ final AnimatedRotateState state = mState;
+ if (state == null) {
+ return;
}
- a.recycle();
-
- int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT &&
- (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-
- if (type != XmlPullParser.START_TAG) {
- continue;
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(
+ state.mThemeAttrs, R.styleable.AnimatedRotateDrawable);
+ try {
+ updateStateFromTypedArray(a);
+ verifyRequiredAttributes(a);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ } finally {
+ a.recycle();
}
+ }
- if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
- Log.w("drawable", "Bad element under <animated-rotate>: "
- + parser .getName());
- }
+ if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
+ state.mDrawable.applyTheme(t);
}
- if (drawable == null) {
- Log.w("drawable", "No drawable specified for <animated-rotate>");
+ init();
+ }
+
+ private void updateStateFromTypedArray(TypedArray a) {
+ final AnimatedRotateState state = mState;
+
+ // Account for any configuration changes.
+ state.mChangingConfigurations |= a.getChangingConfigurations();
+
+ // Extract the theme attributes, if any.
+ state.mThemeAttrs = a.extractThemeAttrs();
+
+ if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotX)) {
+ final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX);
+ state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION;
+ state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
}
- final AnimatedRotateState rotateState = mState;
- rotateState.mDrawable = drawable;
- rotateState.mPivotXRel = pivotXRel;
- rotateState.mPivotX = pivotX;
- rotateState.mPivotYRel = pivotYRel;
- rotateState.mPivotY = pivotY;
+ if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotY)) {
+ final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY);
+ state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION;
+ state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+ }
- init();
+ setFramesCount(a.getInt(
+ R.styleable.AnimatedRotateDrawable_framesCount, state.mFramesCount));
+ setFramesDuration(a.getInt(
+ R.styleable.AnimatedRotateDrawable_frameDuration, state.mFrameDuration));
- if (drawable != null) {
- drawable.setCallback(this);
+ final Drawable dr = a.getDrawable(R.styleable.AnimatedRotateDrawable_drawable);
+ if (dr != null) {
+ state.mDrawable = dr;
+ dr.setCallback(this);
}
}
- @Override
- public void applyTheme(Theme t) {
- super.applyTheme(t);
-
+ private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
final AnimatedRotateState state = mState;
- if (state == null) {
- return;
+
+ Drawable dr = null;
+ int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if ((dr = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
+ Log.w(TAG, "Bad element under <animated-rotate>: " + parser.getName());
+ }
}
- if (state.mDrawable != null) {
- state.mDrawable.applyTheme(t);
+ if (dr != null) {
+ state.mDrawable = dr;
+ dr.setCallback(this);
}
}
- @Override
- public boolean canApplyTheme() {
- final AnimatedRotateState state = mState;
- return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
+ private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+ // If we're not waiting on a theme, verify required attributes.
+ if (mState.mDrawable == null && (mState.mThemeAttrs == null
+ || mState.mThemeAttrs[R.styleable.AnimatedRotateDrawable_drawable] == 0)) {
+ throw new XmlPullParserException(a.getPositionDescription()
+ + ": <animated-rotate> tag requires a 'drawable' attribute or "
+ + "child tag defining a drawable");
+ }
}
public void setFramesCount(int framesCount) {
@@ -362,15 +400,16 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
final static class AnimatedRotateState extends Drawable.ConstantState {
Drawable mDrawable;
+ int[] mThemeAttrs;
int mChangingConfigurations;
- boolean mPivotXRel;
- float mPivotX;
- boolean mPivotYRel;
- float mPivotY;
- int mFrameDuration;
- int mFramesCount;
+ boolean mPivotXRel = false;
+ float mPivotX = 0;
+ boolean mPivotYRel = false;
+ float mPivotY = 0;
+ int mFrameDuration = 150;
+ int mFramesCount = 12;
private boolean mCanConstantState;
private boolean mCheckedConstantState;
@@ -387,6 +426,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
mDrawable.setBounds(orig.mDrawable.getBounds());
mDrawable.setLevel(orig.mDrawable.getLevel());
+ mThemeAttrs = orig.mThemeAttrs;
mPivotXRel = orig.mPivotXRel;
mPivotX = orig.mPivotX;
mPivotYRel = orig.mPivotYRel;
@@ -408,6 +448,12 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
}
@Override
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+ || super.canApplyTheme();
+ }
+
+ @Override
public int getChangingConfigurations() {
return mChangingConfigurations;
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 849faecb99d5..5a3a6177d586 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -347,24 +347,62 @@ public class AnimatedStateListDrawable extends StateListDrawable {
throws XmlPullParserException, IOException {
final TypedArray a = obtainAttributes(
r, theme, attrs, R.styleable.AnimatedStateListDrawable);
-
super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedStateListDrawable_visible);
+ updateStateFromTypedArray(a);
+ a.recycle();
+
+ inflateChildElements(r, parser, attrs, theme);
- final StateListState stateListState = getStateListState();
- stateListState.setVariablePadding(a.getBoolean(
- R.styleable.AnimatedStateListDrawable_variablePadding, false));
- stateListState.setConstantSize(a.getBoolean(
- R.styleable.AnimatedStateListDrawable_constantSize, false));
- stateListState.setEnterFadeDuration(a.getInt(
- R.styleable.AnimatedStateListDrawable_enterFadeDuration, 0));
- stateListState.setExitFadeDuration(a.getInt(
- R.styleable.AnimatedStateListDrawable_exitFadeDuration, 0));
+ init();
+ }
+
+ @Override
+ public void applyTheme(@Nullable Theme theme) {
+ super.applyTheme(theme);
- setDither(a.getBoolean(R.styleable.AnimatedStateListDrawable_dither, true));
- setAutoMirrored(a.getBoolean(R.styleable.AnimatedStateListDrawable_autoMirrored, false));
+ final AnimatedStateListState state = mState;
+ if (state == null || state.mAnimThemeAttrs == null) {
+ return;
+ }
+ final TypedArray a = theme.resolveAttributes(
+ state.mAnimThemeAttrs, R.styleable.AnimatedRotateDrawable);
+ updateStateFromTypedArray(a);
a.recycle();
+ init();
+ }
+
+ private void updateStateFromTypedArray(TypedArray a) {
+ final AnimatedStateListState state = mState;
+
+ // Account for any configuration changes.
+ state.mChangingConfigurations |= a.getChangingConfigurations();
+
+ // Extract the theme attributes, if any.
+ state.mAnimThemeAttrs = a.extractThemeAttrs();
+
+ state.setVariablePadding(a.getBoolean(
+ R.styleable.AnimatedStateListDrawable_variablePadding, state.mVariablePadding));
+ state.setConstantSize(a.getBoolean(
+ R.styleable.AnimatedStateListDrawable_constantSize, state.mConstantSize));
+ state.setEnterFadeDuration(a.getInt(
+ R.styleable.AnimatedStateListDrawable_enterFadeDuration, state.mEnterFadeDuration));
+ state.setExitFadeDuration(a.getInt(
+ R.styleable.AnimatedStateListDrawable_exitFadeDuration, state.mExitFadeDuration));
+
+ setDither(a.getBoolean(
+ R.styleable.AnimatedStateListDrawable_dither, state.mDither));
+ setAutoMirrored(a.getBoolean(
+ R.styleable.AnimatedStateListDrawable_autoMirrored, state.mAutoMirrored));
+ }
+
+ private void init() {
+ onStateChange(getState());
+ }
+
+ private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
int type;
final int innerDepth = parser.getDepth() + 1;
@@ -386,8 +424,6 @@ public class AnimatedStateListDrawable extends StateListDrawable {
parseTransition(r, parser, attrs, theme);
}
}
-
- onStateChange(getState());
}
private int parseTransition(@NonNull Resources r, @NonNull XmlPullParser parser,
@@ -507,6 +543,8 @@ public class AnimatedStateListDrawable extends StateListDrawable {
private static final int REVERSE_SHIFT = 32;
private static final int REVERSE_MASK = 0x1;
+ int[] mAnimThemeAttrs;
+
final LongSparseLongArray mTransitions;
final SparseIntArray mStateIds;
@@ -515,6 +553,7 @@ public class AnimatedStateListDrawable extends StateListDrawable {
super(orig, owner, res);
if (orig != null) {
+ mAnimThemeAttrs = orig.mAnimThemeAttrs;
mTransitions = orig.mTransitions.clone();
mStateIds = orig.mStateIds.clone();
} else {
@@ -566,6 +605,11 @@ public class AnimatedStateListDrawable extends StateListDrawable {
}
@Override
+ public boolean canApplyTheme() {
+ return mAnimThemeAttrs != null || super.canApplyTheme();
+ }
+
+ @Override
public Drawable newDrawable() {
return new AnimatedStateListDrawable(this, null);
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index a904067e5c97..e65dbaf077b6 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -316,9 +316,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable {
@Override
public boolean canApplyTheme() {
- return super.canApplyTheme() || mAnimatedVectorState != null
- && mAnimatedVectorState.mVectorDrawable != null
- && mAnimatedVectorState.mVectorDrawable.canApplyTheme();
+ return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme())
+ || super.canApplyTheme();
}
@Override
@@ -374,6 +373,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable {
}
@Override
+ public boolean canApplyTheme() {
+ return (mVectorDrawable != null && mVectorDrawable.canApplyTheme())
+ || super.canApplyTheme();
+ }
+
+ @Override
public Drawable newDrawable() {
return new AnimatedVectorDrawable(this, null);
}
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index c730a2037b23..a8b6c9438474 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -16,6 +16,8 @@
package android.graphics.drawable;
+import com.android.internal.R;
+
import java.io.IOException;
import org.xmlpull.v1.XmlPullParser;
@@ -271,27 +273,25 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawable);
+ super.inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_visible);
+ updateStateFromTypedArray(a);
+ a.recycle();
- TypedArray a = obtainAttributes(r, theme, attrs,
- com.android.internal.R.styleable.AnimationDrawable);
-
- super.inflateWithAttributes(r, parser, a,
- com.android.internal.R.styleable.AnimationDrawable_visible);
-
- mAnimationState.setVariablePadding(a.getBoolean(
- com.android.internal.R.styleable.AnimationDrawable_variablePadding, false));
-
- mAnimationState.mOneShot = a.getBoolean(
- com.android.internal.R.styleable.AnimationDrawable_oneshot, false);
+ inflateChildElements(r, parser, attrs, theme);
- a.recycle();
+ setFrame(0, true, false);
+ }
+ private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
+ TypedArray a;
int type;
final int innerDepth = parser.getDepth()+1;
int depth;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT &&
- ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
if (type != XmlPullParser.START_TAG) {
continue;
}
@@ -300,17 +300,15 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
continue;
}
- a = obtainAttributes(
- r, theme, attrs, com.android.internal.R.styleable.AnimationDrawableItem);
- int duration = a.getInt(
- com.android.internal.R.styleable.AnimationDrawableItem_duration, -1);
+ a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawableItem);
+
+ final int duration = a.getInt(R.styleable.AnimationDrawableItem_duration, -1);
if (duration < 0) {
- throw new XmlPullParserException(
- parser.getPositionDescription()
+ throw new XmlPullParserException(parser.getPositionDescription()
+ ": <item> tag requires a 'duration' attribute");
}
- int drawableRes = a.getResourceId(
- com.android.internal.R.styleable.AnimationDrawableItem_drawable, 0);
+
+ final int drawableRes = a.getResourceId(R.styleable.AnimationDrawableItem_drawable, 0);
a.recycle();
@@ -322,9 +320,9 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
// Empty
}
if (type != XmlPullParser.START_TAG) {
- throw new XmlPullParserException(parser.getPositionDescription() +
- ": <item> tag requires a 'drawable' attribute or child tag" +
- " defining a drawable");
+ throw new XmlPullParserException(parser.getPositionDescription()
+ + ": <item> tag requires a 'drawable' attribute or child tag"
+ + " defining a drawable");
}
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
@@ -334,8 +332,14 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
dr.setCallback(this);
}
}
+ }
- setFrame(0, true, false);
+ private void updateStateFromTypedArray(TypedArray a) {
+ mAnimationState.mVariablePadding = a.getBoolean(
+ R.styleable.AnimationDrawable_variablePadding, mAnimationState.mVariablePadding);
+
+ mAnimationState.mOneShot = a.getBoolean(
+ R.styleable.AnimationDrawable_oneshot, mAnimationState.mOneShot);
}
@Override
@@ -357,7 +361,7 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
private final static class AnimationState extends DrawableContainerState {
private int[] mDurations;
- private boolean mOneShot;
+ private boolean mOneShot = false;
AnimationState(AnimationState orig, AnimationDrawable owner,
Resources res) {
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index 669cef2ccfad..e5b2b768cd16 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -16,6 +16,8 @@
package android.graphics.drawable;
+import com.android.internal.R;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -49,7 +51,7 @@ import java.io.IOException;
* @attr ref android.R.styleable#ClipDrawable_drawable
*/
public class ClipDrawable extends Drawable implements Drawable.Callback {
- private ClipState mClipState;
+ private ClipState mState;
private final Rect mTmpRect = new Rect();
public static final int HORIZONTAL = 1;
@@ -67,9 +69,9 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
public ClipDrawable(Drawable drawable, int gravity, int orientation) {
this(null, null);
- mClipState.mDrawable = drawable;
- mClipState.mGravity = gravity;
- mClipState.mOrientation = orientation;
+ mState.mDrawable = drawable;
+ mState.mGravity = gravity;
+ mState.mOrientation = orientation;
if (drawable != null) {
drawable.setCallback(this);
@@ -81,19 +83,22 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
throws XmlPullParserException, IOException {
super.inflate(r, parser, attrs, theme);
- int type;
-
- TypedArray a = obtainAttributes(
- r, theme, attrs, com.android.internal.R.styleable.ClipDrawable);
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ClipDrawable);
- int orientation = a.getInt(
- com.android.internal.R.styleable.ClipDrawable_clipOrientation,
- HORIZONTAL);
- int g = a.getInt(com.android.internal.R.styleable.ClipDrawable_gravity, Gravity.LEFT);
- Drawable dr = a.getDrawable(com.android.internal.R.styleable.ClipDrawable_drawable);
+ // Reset mDrawable to preserve old multiple-inflate behavior. This is
+ // silly, but we have CTS tests that rely on it.
+ mState.mDrawable = null;
+ updateStateFromTypedArray(a);
+ inflateChildElements(r, parser, attrs, theme);
+ verifyRequiredAttributes(a);
a.recycle();
+ }
+ private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
+ Drawable dr = null;
+ int type;
final int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -103,35 +108,68 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
- if (dr == null) {
- throw new IllegalArgumentException("No drawable specified for <clip>");
+ if (dr != null) {
+ mState.mDrawable = dr;
+ dr.setCallback(this);
}
+ }
+
+ private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+ // If we're not waiting on a theme, verify required attributes.
+ if (mState.mDrawable == null && (mState.mThemeAttrs == null
+ || mState.mThemeAttrs[R.styleable.ClipDrawable_drawable] == 0)) {
+ throw new XmlPullParserException(a.getPositionDescription()
+ + ": <clip> tag requires a 'drawable' attribute or "
+ + "child tag defining a drawable");
+ }
+ }
+
+ private void updateStateFromTypedArray(TypedArray a) {
+ final ClipState state = mState;
+
+ // Account for any configuration changes.
+ state.mChangingConfigurations |= a.getChangingConfigurations();
- mClipState.mDrawable = dr;
- mClipState.mOrientation = orientation;
- mClipState.mGravity = g;
+ // Extract the theme attributes, if any.
+ state.mThemeAttrs = a.extractThemeAttrs();
- dr.setCallback(this);
+ state.mOrientation = a.getInt(R.styleable.ClipDrawable_clipOrientation, state.mOrientation);
+ state.mGravity = a.getInt(R.styleable.ClipDrawable_gravity, state.mGravity);
+
+ final Drawable dr = a.getDrawable(R.styleable.ClipDrawable_drawable);
+ if (dr != null) {
+ state.mDrawable = dr;
+ dr.setCallback(this);
+ }
}
@Override
public void applyTheme(Theme t) {
super.applyTheme(t);
- final ClipState state = mClipState;
- if (state == null) {
+ final ClipState state = mState;
+ if (state == null || state.mThemeAttrs == null) {
return;
}
- if (state.mDrawable != null) {
+ final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ClipDrawable);
+ try {
+ updateStateFromTypedArray(a);
+ verifyRequiredAttributes(a);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ } finally {
+ a.recycle();
+ }
+
+ if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
state.mDrawable.applyTheme(t);
}
}
@Override
public boolean canApplyTheme() {
- final ClipState state = mClipState;
- return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
+ return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
}
// overrides from Drawable.Callback
@@ -165,78 +203,78 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
@Override
public int getChangingConfigurations() {
return super.getChangingConfigurations()
- | mClipState.mChangingConfigurations
- | mClipState.mDrawable.getChangingConfigurations();
+ | mState.mChangingConfigurations
+ | mState.mDrawable.getChangingConfigurations();
}
@Override
public boolean getPadding(Rect padding) {
// XXX need to adjust padding!
- return mClipState.mDrawable.getPadding(padding);
+ return mState.mDrawable.getPadding(padding);
}
@Override
public boolean setVisible(boolean visible, boolean restart) {
- mClipState.mDrawable.setVisible(visible, restart);
+ mState.mDrawable.setVisible(visible, restart);
return super.setVisible(visible, restart);
}
@Override
public void setAlpha(int alpha) {
- mClipState.mDrawable.setAlpha(alpha);
+ mState.mDrawable.setAlpha(alpha);
}
@Override
public int getAlpha() {
- return mClipState.mDrawable.getAlpha();
+ return mState.mDrawable.getAlpha();
}
@Override
public void setColorFilter(ColorFilter cf) {
- mClipState.mDrawable.setColorFilter(cf);
+ mState.mDrawable.setColorFilter(cf);
}
@Override
public void setTintList(ColorStateList tint) {
- mClipState.mDrawable.setTintList(tint);
+ mState.mDrawable.setTintList(tint);
}
@Override
public void setTintMode(Mode tintMode) {
- mClipState.mDrawable.setTintMode(tintMode);
+ mState.mDrawable.setTintMode(tintMode);
}
@Override
public int getOpacity() {
- return mClipState.mDrawable.getOpacity();
+ return mState.mDrawable.getOpacity();
}
@Override
public boolean isStateful() {
- return mClipState.mDrawable.isStateful();
+ return mState.mDrawable.isStateful();
}
@Override
protected boolean onStateChange(int[] state) {
- return mClipState.mDrawable.setState(state);
+ return mState.mDrawable.setState(state);
}
@Override
protected boolean onLevelChange(int level) {
- mClipState.mDrawable.setLevel(level);
+ mState.mDrawable.setLevel(level);
invalidateSelf();
return true;
}
@Override
protected void onBoundsChange(Rect bounds) {
- mClipState.mDrawable.setBounds(bounds);
+ mState.mDrawable.setBounds(bounds);
}
@Override
public void draw(Canvas canvas) {
- if (mClipState.mDrawable.getLevel() == 0) {
+ if (mState.mDrawable.getLevel() == 0) {
return;
}
@@ -244,41 +282,41 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
final Rect bounds = getBounds();
int level = getLevel();
int w = bounds.width();
- final int iw = 0; //mClipState.mDrawable.getIntrinsicWidth();
- if ((mClipState.mOrientation & HORIZONTAL) != 0) {
+ final int iw = 0; //mState.mDrawable.getIntrinsicWidth();
+ if ((mState.mOrientation & HORIZONTAL) != 0) {
w -= (w - iw) * (10000 - level) / 10000;
}
int h = bounds.height();
- final int ih = 0; //mClipState.mDrawable.getIntrinsicHeight();
- if ((mClipState.mOrientation & VERTICAL) != 0) {
+ final int ih = 0; //mState.mDrawable.getIntrinsicHeight();
+ if ((mState.mOrientation & VERTICAL) != 0) {
h -= (h - ih) * (10000 - level) / 10000;
}
final int layoutDirection = getLayoutDirection();
- Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection);
+ Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection);
if (w > 0 && h > 0) {
canvas.save();
canvas.clipRect(r);
- mClipState.mDrawable.draw(canvas);
+ mState.mDrawable.draw(canvas);
canvas.restore();
}
}
@Override
public int getIntrinsicWidth() {
- return mClipState.mDrawable.getIntrinsicWidth();
+ return mState.mDrawable.getIntrinsicWidth();
}
@Override
public int getIntrinsicHeight() {
- return mClipState.mDrawable.getIntrinsicHeight();
+ return mState.mDrawable.getIntrinsicHeight();
}
@Override
public ConstantState getConstantState() {
- if (mClipState.canConstantState()) {
- mClipState.mChangingConfigurations = getChangingConfigurations();
- return mClipState;
+ if (mState.canConstantState()) {
+ mState.mChangingConfigurations = getChangingConfigurations();
+ return mState;
}
return null;
}
@@ -286,14 +324,14 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
/** @hide */
@Override
public void setLayoutDirection(int layoutDirection) {
- mClipState.mDrawable.setLayoutDirection(layoutDirection);
+ mState.mDrawable.setLayoutDirection(layoutDirection);
super.setLayoutDirection(layoutDirection);
}
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
- mClipState.mDrawable.mutate();
+ mState.mDrawable.mutate();
mMutated = true;
}
return this;
@@ -304,21 +342,26 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
*/
public void clearMutated() {
super.clearMutated();
- mClipState.mDrawable.clearMutated();
+ mState.mDrawable.clearMutated();
mMutated = false;
}
final static class ClipState extends ConstantState {
- Drawable mDrawable;
+ int[] mThemeAttrs;
int mChangingConfigurations;
- int mOrientation;
- int mGravity;
+
+ Drawable mDrawable;
+
+ int mOrientation = HORIZONTAL;
+ int mGravity = Gravity.LEFT;
private boolean mCheckedConstantState;
private boolean mCanConstantState;
ClipState(ClipState orig, ClipDrawable owner, Resources res) {
if (orig != null) {
+ mThemeAttrs = orig.mThemeAttrs;
+ mChangingConfigurations = orig.mChangingConfigurations;
if (res != null) {
mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
} else {
@@ -335,6 +378,12 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
}
@Override
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+ || super.canApplyTheme();
+ }
+
+ @Override
public Drawable newDrawable() {
return new ClipDrawable(this, null);
}
@@ -360,7 +409,7 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
}
private ClipDrawable(ClipState state, Resources res) {
- mClipState = new ClipState(state, this, res);
+ mState = new ClipState(state, this, res);
}
}
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index a9032887421e..326490ff884a 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -600,11 +600,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
Drawable[] mDrawables;
int mNumChildren;
- boolean mVariablePadding;
+ boolean mVariablePadding = false;
boolean mPaddingChecked;
Rect mConstantPadding;
- boolean mConstantSize;
+ boolean mConstantSize = false;
boolean mComputedConstantSize;
int mConstantWidth;
int mConstantHeight;
@@ -625,8 +625,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback {
boolean mMutated;
int mLayoutDirection;
- int mEnterFadeDuration;
- int mExitFadeDuration;
+ int mEnterFadeDuration = 0;
+ int mExitFadeDuration = 0;
boolean mAutoMirrored;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 47e0e46b0888..14582385e9b5 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -1089,7 +1089,7 @@ public class GradientDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return super.canApplyTheme() || mGradientState != null && mGradientState.canApplyTheme();
+ return (mGradientState != null && mGradientState.canApplyTheme()) || super.canApplyTheme();
}
private void applyThemeChildElements(Theme t) {
@@ -1632,7 +1632,7 @@ public class GradientDrawable extends Drawable {
public boolean canApplyTheme() {
return mThemeAttrs != null || mAttrSize != null || mAttrGradient != null
|| mAttrSolid != null || mAttrStroke != null || mAttrCorners != null
- || mAttrPadding != null;
+ || mAttrPadding != null || super.canApplyTheme();
}
@Override
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index f1800e52aeb9..b88d9e67b069 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -55,7 +55,8 @@ import java.io.IOException;
public class InsetDrawable extends Drawable implements Drawable.Callback {
private final Rect mTmpRect = new Rect();
- private InsetState mInsetState;
+ private final InsetState mState;
+
private boolean mMutated;
/*package*/ InsetDrawable() {
@@ -70,11 +71,11 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
int insetRight, int insetBottom) {
this(null, null);
- mInsetState.mDrawable = drawable;
- mInsetState.mInsetLeft = insetLeft;
- mInsetState.mInsetTop = insetTop;
- mInsetState.mInsetRight = insetRight;
- mInsetState.mInsetBottom = insetBottom;
+ mState.mDrawable = drawable;
+ mState.mInsetLeft = insetLeft;
+ mState.mInsetTop = insetTop;
+ mState.mInsetRight = insetRight;
+ mState.mInsetBottom = insetBottom;
if (drawable != null) {
drawable.setCallback(this);
@@ -87,11 +88,20 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable);
super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible);
- mInsetState.mDrawable = null;
+ // Reset mDrawable to preserve old multiple-inflate behavior. This is
+ // silly, but we have CTS tests that rely on it.
+ mState.mDrawable = null;
+
updateStateFromTypedArray(a);
+ inflateChildElements(r, parser, attrs, theme);
+ verifyRequiredAttributes(a);
+ a.recycle();
+ }
+ private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
// Load inner XML elements.
- if (mInsetState.mDrawable == null) {
+ if (mState.mDrawable == null) {
int type;
while ((type=parser.next()) == XmlPullParser.TEXT) {
}
@@ -102,26 +112,23 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
+ "child tag defining a drawable");
}
final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
- mInsetState.mDrawable = dr;
+ mState.mDrawable = dr;
dr.setCallback(this);
}
-
- verifyRequiredAttributes(a);
- a.recycle();
}
private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
// If we're not waiting on a theme, verify required attributes.
- if (mInsetState.mDrawable == null && (mInsetState.mThemeAttrs == null
- || mInsetState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) {
- throw new XmlPullParserException(a.getPositionDescription() +
- ": <inset> tag requires a 'drawable' attribute or "
+ if (mState.mDrawable == null && (mState.mThemeAttrs == null
+ || mState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) {
+ throw new XmlPullParserException(a.getPositionDescription()
+ + ": <inset> tag requires a 'drawable' attribute or "
+ "child tag defining a drawable");
}
}
private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
- final InsetState state = mInsetState;
+ final InsetState state = mState;
// Account for any configuration changes.
state.mChangingConfigurations |= a.getChangingConfigurations();
@@ -169,7 +176,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
public void applyTheme(Theme t) {
super.applyTheme(t);
- final InsetState state = mInsetState;
+ final InsetState state = mState;
if (state == null) {
return;
}
@@ -193,7 +200,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
@Override
public boolean canApplyTheme() {
- return super.canApplyTheme() || mInsetState != null && mInsetState.canApplyTheme();
+ return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
}
@Override
@@ -222,112 +229,112 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
@Override
public void draw(Canvas canvas) {
- mInsetState.mDrawable.draw(canvas);
+ mState.mDrawable.draw(canvas);
}
@Override
public int getChangingConfigurations() {
return super.getChangingConfigurations()
- | mInsetState.mChangingConfigurations
- | mInsetState.mDrawable.getChangingConfigurations();
+ | mState.mChangingConfigurations
+ | mState.mDrawable.getChangingConfigurations();
}
@Override
public boolean getPadding(Rect padding) {
- boolean pad = mInsetState.mDrawable.getPadding(padding);
+ boolean pad = mState.mDrawable.getPadding(padding);
- padding.left += mInsetState.mInsetLeft;
- padding.right += mInsetState.mInsetRight;
- padding.top += mInsetState.mInsetTop;
- padding.bottom += mInsetState.mInsetBottom;
+ padding.left += mState.mInsetLeft;
+ padding.right += mState.mInsetRight;
+ padding.top += mState.mInsetTop;
+ padding.bottom += mState.mInsetBottom;
- return pad || (mInsetState.mInsetLeft | mInsetState.mInsetRight |
- mInsetState.mInsetTop | mInsetState.mInsetBottom) != 0;
+ return pad || (mState.mInsetLeft | mState.mInsetRight |
+ mState.mInsetTop | mState.mInsetBottom) != 0;
}
/** @hide */
@Override
public Insets getOpticalInsets() {
final Insets contentInsets = super.getOpticalInsets();
- return Insets.of(contentInsets.left + mInsetState.mInsetLeft,
- contentInsets.top + mInsetState.mInsetTop,
- contentInsets.right + mInsetState.mInsetRight,
- contentInsets.bottom + mInsetState.mInsetBottom);
+ return Insets.of(contentInsets.left + mState.mInsetLeft,
+ contentInsets.top + mState.mInsetTop,
+ contentInsets.right + mState.mInsetRight,
+ contentInsets.bottom + mState.mInsetBottom);
}
@Override
public void setHotspot(float x, float y) {
- mInsetState.mDrawable.setHotspot(x, y);
+ mState.mDrawable.setHotspot(x, y);
}
@Override
public void setHotspotBounds(int left, int top, int right, int bottom) {
- mInsetState.mDrawable.setHotspotBounds(left, top, right, bottom);
+ mState.mDrawable.setHotspotBounds(left, top, right, bottom);
}
/** @hide */
@Override
public void getHotspotBounds(Rect outRect) {
- mInsetState.mDrawable.getHotspotBounds(outRect);
+ mState.mDrawable.getHotspotBounds(outRect);
}
@Override
public boolean setVisible(boolean visible, boolean restart) {
- mInsetState.mDrawable.setVisible(visible, restart);
+ mState.mDrawable.setVisible(visible, restart);
return super.setVisible(visible, restart);
}
@Override
public void setAlpha(int alpha) {
- mInsetState.mDrawable.setAlpha(alpha);
+ mState.mDrawable.setAlpha(alpha);
}
@Override
public int getAlpha() {
- return mInsetState.mDrawable.getAlpha();
+ return mState.mDrawable.getAlpha();
}
@Override
public void setColorFilter(ColorFilter cf) {
- mInsetState.mDrawable.setColorFilter(cf);
+ mState.mDrawable.setColorFilter(cf);
}
@Override
public void setTintList(ColorStateList tint) {
- mInsetState.mDrawable.setTintList(tint);
+ mState.mDrawable.setTintList(tint);
}
@Override
public void setTintMode(Mode tintMode) {
- mInsetState.mDrawable.setTintMode(tintMode);
+ mState.mDrawable.setTintMode(tintMode);
}
/** {@hide} */
@Override
public void setLayoutDirection(int layoutDirection) {
- mInsetState.mDrawable.setLayoutDirection(layoutDirection);
+ mState.mDrawable.setLayoutDirection(layoutDirection);
}
@Override
public int getOpacity() {
- return mInsetState.mDrawable.getOpacity();
+ return mState.mDrawable.getOpacity();
}
@Override
public boolean isStateful() {
- return mInsetState.mDrawable.isStateful();
+ return mState.mDrawable.isStateful();
}
@Override
protected boolean onStateChange(int[] state) {
- boolean changed = mInsetState.mDrawable.setState(state);
+ boolean changed = mState.mDrawable.setState(state);
onBoundsChange(getBounds());
return changed;
}
@Override
protected boolean onLevelChange(int level) {
- return mInsetState.mDrawable.setLevel(level);
+ return mState.mDrawable.setLevel(level);
}
@Override
@@ -335,36 +342,36 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
final Rect r = mTmpRect;
r.set(bounds);
- r.left += mInsetState.mInsetLeft;
- r.top += mInsetState.mInsetTop;
- r.right -= mInsetState.mInsetRight;
- r.bottom -= mInsetState.mInsetBottom;
+ r.left += mState.mInsetLeft;
+ r.top += mState.mInsetTop;
+ r.right -= mState.mInsetRight;
+ r.bottom -= mState.mInsetBottom;
- mInsetState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
+ mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
}
@Override
public int getIntrinsicWidth() {
- return mInsetState.mDrawable.getIntrinsicWidth()
- + mInsetState.mInsetLeft + mInsetState.mInsetRight;
+ return mState.mDrawable.getIntrinsicWidth()
+ + mState.mInsetLeft + mState.mInsetRight;
}
@Override
public int getIntrinsicHeight() {
- return mInsetState.mDrawable.getIntrinsicHeight()
- + mInsetState.mInsetTop + mInsetState.mInsetBottom;
+ return mState.mDrawable.getIntrinsicHeight()
+ + mState.mInsetTop + mState.mInsetBottom;
}
@Override
public void getOutline(@NonNull Outline outline) {
- mInsetState.mDrawable.getOutline(outline);
+ mState.mDrawable.getOutline(outline);
}
@Override
public ConstantState getConstantState() {
- if (mInsetState.canConstantState()) {
- mInsetState.mChangingConfigurations = getChangingConfigurations();
- return mInsetState;
+ if (mState.canConstantState()) {
+ mState.mChangingConfigurations = getChangingConfigurations();
+ return mState;
}
return null;
}
@@ -372,7 +379,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
- mInsetState.mDrawable.mutate();
+ mState.mDrawable.mutate();
mMutated = true;
}
return this;
@@ -383,7 +390,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
*/
public void clearMutated() {
super.clearMutated();
- mInsetState.mDrawable.clearMutated();
+ mState.mDrawable.clearMutated();
mMutated = false;
}
@@ -391,7 +398,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
* Returns the drawable wrapped by this InsetDrawable. May be null.
*/
public Drawable getDrawable() {
- return mInsetState.mDrawable;
+ return mState.mDrawable;
}
final static class InsetState extends ConstantState {
@@ -400,13 +407,13 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
Drawable mDrawable;
- int mInsetLeft;
- int mInsetTop;
- int mInsetRight;
- int mInsetBottom;
+ int mInsetLeft = 0;
+ int mInsetTop = 0;
+ int mInsetRight = 0;
+ int mInsetBottom = 0;
- boolean mCheckedConstantState;
- boolean mCanConstantState;
+ private boolean mCheckedConstantState;
+ private boolean mCanConstantState;
InsetState(InsetState orig, InsetDrawable owner, Resources res) {
if (orig != null) {
@@ -430,6 +437,12 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
}
@Override
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+ || super.canApplyTheme();
+ }
+
+ @Override
public Drawable newDrawable() {
return new InsetDrawable(this, null);
}
@@ -444,12 +457,6 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
return mChangingConfigurations;
}
- @Override
- public boolean canApplyTheme() {
- return super.canApplyTheme() || mThemeAttrs != null
- || mDrawable != null && mDrawable.canApplyTheme();
- }
-
boolean canConstantState() {
if (!mCheckedConstantState) {
mCanConstantState = mDrawable.getConstantState() != null;
@@ -461,7 +468,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback {
}
private InsetDrawable(InsetState state, Resources res) {
- mInsetState = new InsetState(state, this, res);
+ mState = new InsetState(state, this, res);
}
}
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 5107e10226b0..689d225fad30 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -275,7 +275,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
@Override
public boolean canApplyTheme() {
- return super.canApplyTheme() || mLayerState != null && mLayerState.canApplyTheme();
+ return (mLayerState != null && mLayerState.canApplyTheme()) || super.canApplyTheme();
}
/**
@@ -1020,7 +1020,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
@Override
public boolean canApplyTheme() {
- if (mThemeAttrs != null) {
+ if (mThemeAttrs != null || super.canApplyTheme()) {
return true;
}
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 316139b87a25..e658279ec0dd 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -473,7 +473,7 @@ public class RippleDrawable extends LayerDrawable {
@Override
public boolean canApplyTheme() {
- return super.canApplyTheme() || mState != null && mState.canApplyTheme();
+ return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
}
@Override
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 3f75bc398af2..3304b335ac45 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -31,7 +31,6 @@ import android.content.res.TypedArray;
import android.content.res.Resources.Theme;
import android.util.TypedValue;
import android.util.AttributeSet;
-import android.util.Log;
import java.io.IOException;
@@ -314,6 +313,11 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
}
@Override
+ public boolean canApplyTheme() {
+ return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
+ }
+
+ @Override
public void invalidateDrawable(Drawable who) {
final Callback callback = getCallback();
if (callback != null) {
@@ -401,100 +405,104 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- final TypedArray a = obtainAttributes(r, theme, attrs,
- com.android.internal.R.styleable.RotateDrawable);
-
- super.inflateWithAttributes(r, parser, a,
- com.android.internal.R.styleable.RotateDrawable_visible);
-
- TypedValue tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotX);
- final boolean pivotXRel;
- final float pivotX;
- if (tv == null) {
- pivotXRel = true;
- pivotX = 0.5f;
- } else {
- pivotXRel = tv.type == TypedValue.TYPE_FRACTION;
- pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
- }
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.RotateDrawable);
+ super.inflateWithAttributes(r, parser, a, R.styleable.RotateDrawable_visible);
+
+ // Reset mDrawable to preserve old multiple-inflate behavior. This is
+ // silly, but we have CTS tests that rely on it.
+ mState.mDrawable = null;
+
+ updateStateFromTypedArray(a);
+ inflateChildElements(r, parser, attrs, theme);
+ verifyRequiredAttributes(a);
+ a.recycle();
+ }
- tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotY);
- final boolean pivotYRel;
- final float pivotY;
- if (tv == null) {
- pivotYRel = true;
- pivotY = 0.5f;
- } else {
- pivotYRel = tv.type == TypedValue.TYPE_FRACTION;
- pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+ @Override
+ public void applyTheme(Theme t) {
+ super.applyTheme(t);
+
+ final RotateState state = mState;
+ if (state == null) {
+ return;
}
- final float fromDegrees = a.getFloat(
- com.android.internal.R.styleable.RotateDrawable_fromDegrees, 0.0f);
- final float toDegrees = a.getFloat(
- com.android.internal.R.styleable.RotateDrawable_toDegrees, 360.0f);
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.RotateDrawable);
+ try {
+ updateStateFromTypedArray(a);
+ verifyRequiredAttributes(a);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ } finally {
+ a.recycle();
+ }
+ }
- final int res = a.getResourceId(
- com.android.internal.R.styleable.RotateDrawable_drawable, 0);
- Drawable drawable = null;
- if (res > 0) {
- drawable = r.getDrawable(res, theme);
+ if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
+ state.mDrawable.applyTheme(t);
}
- a.recycle();
+ }
- final int outerDepth = parser.getDepth();
+ private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
+ Drawable dr = null;
int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT &&
- (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-
+ final int outerDepth = parser.getDepth();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type != XmlPullParser.START_TAG) {
continue;
}
-
- if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
- Log.w("drawable", "Bad element under <rotate>: "
- + parser .getName());
- }
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
- if (drawable == null) {
- Log.w("drawable", "No drawable specified for <rotate>");
+ if (dr != null) {
+ mState.mDrawable = dr;
+ dr.setCallback(this);
}
+ }
- final RotateState st = mState;
- st.mDrawable = drawable;
- st.mPivotXRel = pivotXRel;
- st.mPivotX = pivotX;
- st.mPivotYRel = pivotYRel;
- st.mPivotY = pivotY;
- st.mFromDegrees = fromDegrees;
- st.mCurrentDegrees = fromDegrees;
- st.mToDegrees = toDegrees;
-
- if (drawable != null) {
- drawable.setCallback(this);
+ private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+ // If we're not waiting on a theme, verify required attributes.
+ if (mState.mDrawable == null && (mState.mThemeAttrs == null
+ || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) {
+ throw new XmlPullParserException(a.getPositionDescription()
+ + ": <rotate> tag requires a 'drawable' attribute or "
+ + "child tag defining a drawable");
}
}
- @Override
- public void applyTheme(Theme t) {
- super.applyTheme(t);
-
+ private void updateStateFromTypedArray(TypedArray a) {
final RotateState state = mState;
- if (state == null) {
- return;
+
+ // Account for any configuration changes.
+ state.mChangingConfigurations |= a.getChangingConfigurations();
+
+ // Extract the theme attributes, if any.
+ state.mThemeAttrs = a.extractThemeAttrs();
+
+ if (a.hasValue(R.styleable.RotateDrawable_pivotX)) {
+ final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotX);
+ state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION;
+ state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
}
- if (state.mDrawable != null) {
- state.mDrawable.applyTheme(t);
+ if (a.hasValue(R.styleable.RotateDrawable_pivotY)) {
+ final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotY);
+ state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION;
+ state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
}
- }
- @Override
- public boolean canApplyTheme() {
- final RotateState state = mState;
- return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
+ state.mFromDegrees = a.getFloat(R.styleable.RotateDrawable_fromDegrees, state.mFromDegrees);
+ state.mToDegrees = a.getFloat(R.styleable.RotateDrawable_toDegrees, state.mToDegrees);
+
+ final Drawable dr = a.getDrawable(R.styleable.RotateDrawable_drawable);
+ if (dr != null) {
+ state.mDrawable = dr;
+ dr.setCallback(this);
+ }
}
@Override
@@ -521,25 +529,28 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
* rotations at the same time.
*/
final static class RotateState extends Drawable.ConstantState {
- Drawable mDrawable;
-
+ int[] mThemeAttrs;
int mChangingConfigurations;
- boolean mPivotXRel;
- float mPivotX;
- boolean mPivotYRel;
- float mPivotY;
+ Drawable mDrawable;
- float mFromDegrees;
- float mToDegrees;
+ boolean mPivotXRel = true;
+ float mPivotX = 0.5f;
+ boolean mPivotYRel = true;
+ float mPivotY = 0.5f;
- float mCurrentDegrees;
+ float mFromDegrees = 0.0f;
+ float mToDegrees = 360.0f;
+
+ float mCurrentDegrees = 0.0f;
- private boolean mCanConstantState;
private boolean mCheckedConstantState;
+ private boolean mCanConstantState;
- public RotateState(RotateState orig, RotateDrawable owner, Resources res) {
+ RotateState(RotateState orig, RotateDrawable owner, Resources res) {
if (orig != null) {
+ mThemeAttrs = orig.mThemeAttrs;
+ mChangingConfigurations = orig.mChangingConfigurations;
if (res != null) {
mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
} else {
@@ -553,13 +564,20 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
mPivotX = orig.mPivotX;
mPivotYRel = orig.mPivotYRel;
mPivotY = orig.mPivotY;
- mFromDegrees = mCurrentDegrees = orig.mFromDegrees;
+ mFromDegrees = orig.mFromDegrees;
mToDegrees = orig.mToDegrees;
- mCanConstantState = mCheckedConstantState = true;
+ mCurrentDegrees = orig.mCurrentDegrees;
+ mCheckedConstantState = mCanConstantState = true;
}
}
@Override
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+ || super.canApplyTheme();
+ }
+
+ @Override
public Drawable newDrawable() {
return new RotateDrawable(this, null);
}
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 9a5b8fbc83aa..35ef76f81d0b 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -16,6 +16,8 @@
package android.graphics.drawable;
+import com.android.internal.R;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -47,7 +49,7 @@ import java.io.IOException;
* @attr ref android.R.styleable#ScaleDrawable_drawable
*/
public class ScaleDrawable extends Drawable implements Drawable.Callback {
- private ScaleState mScaleState;
+ private ScaleState mState;
private boolean mMutated;
private final Rect mTmpRect = new Rect();
@@ -58,10 +60,10 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
public ScaleDrawable(Drawable drawable, int gravity, float scaleWidth, float scaleHeight) {
this(null, null);
- mScaleState.mDrawable = drawable;
- mScaleState.mGravity = gravity;
- mScaleState.mScaleWidth = scaleWidth;
- mScaleState.mScaleHeight = scaleHeight;
+ mState.mDrawable = drawable;
+ mState.mGravity = gravity;
+ mState.mScaleWidth = scaleWidth;
+ mState.mScaleHeight = scaleHeight;
if (drawable != null) {
drawable.setCallback(this);
@@ -72,18 +74,18 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
* Returns the drawable scaled by this ScaleDrawable.
*/
public Drawable getDrawable() {
- return mScaleState.mDrawable;
+ return mState.mDrawable;
}
- private static float getPercent(TypedArray a, int name) {
- String s = a.getString(name);
+ private static float getPercent(TypedArray a, int name, float defaultValue) {
+ final String s = a.getString(name);
if (s != null) {
if (s.endsWith("%")) {
String f = s.substring(0, s.length() - 1);
return Float.parseFloat(f) / 100.0f;
}
}
- return -1;
+ return defaultValue;
}
@Override
@@ -91,20 +93,48 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
throws XmlPullParserException, IOException {
super.inflate(r, parser, attrs, theme);
- int type;
-
- TypedArray a = obtainAttributes(
- r, theme, attrs, com.android.internal.R.styleable.ScaleDrawable);
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ScaleDrawable);
- float sw = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleWidth);
- float sh = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleHeight);
- int g = a.getInt(com.android.internal.R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT);
- boolean min = a.getBoolean(
- com.android.internal.R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false);
- Drawable dr = a.getDrawable(com.android.internal.R.styleable.ScaleDrawable_drawable);
+ // Reset mDrawable to preserve old multiple-inflate behavior. This is
+ // silly, but we have CTS tests that rely on it.
+ mState.mDrawable = null;
+ updateStateFromTypedArray(a);
+ inflateChildElements(r, parser, attrs, theme);
+ verifyRequiredAttributes(a);
a.recycle();
+ }
+
+ @Override
+ public void applyTheme(Theme t) {
+ super.applyTheme(t);
+
+ final ScaleState state = mState;
+ if (state == null) {
+ return;
+ }
+
+ if (state.mThemeAttrs != null) {
+ final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ScaleDrawable);
+ try {
+ updateStateFromTypedArray(a);
+ verifyRequiredAttributes(a);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ } finally {
+ a.recycle();
+ }
+ }
+ if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
+ state.mDrawable.applyTheme(t);
+ }
+ }
+
+ private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
+ Drawable dr = null;
+ int type;
final int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -114,38 +144,49 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
- if (dr == null) {
- throw new IllegalArgumentException("No drawable specified for <scale>");
- }
-
- mScaleState.mDrawable = dr;
- mScaleState.mScaleWidth = sw;
- mScaleState.mScaleHeight = sh;
- mScaleState.mGravity = g;
- mScaleState.mUseIntrinsicSizeAsMin = min;
if (dr != null) {
+ mState.mDrawable = dr;
dr.setCallback(this);
}
}
- @Override
- public void applyTheme(Theme t) {
- super.applyTheme(t);
-
- final ScaleState state = mScaleState;
- if (state == null) {
- return;
+ private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+ // If we're not waiting on a theme, verify required attributes.
+ if (mState.mDrawable == null && (mState.mThemeAttrs == null
+ || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) {
+ throw new XmlPullParserException(a.getPositionDescription()
+ + ": <scale> tag requires a 'drawable' attribute or "
+ + "child tag defining a drawable");
}
+ }
- if (state.mDrawable != null) {
- state.mDrawable.applyTheme(t);
+ private void updateStateFromTypedArray(TypedArray a) {
+ final ScaleState state = mState;
+
+ // Account for any configuration changes.
+ state.mChangingConfigurations |= a.getChangingConfigurations();
+
+ // Extract the theme attributes, if any.
+ state.mThemeAttrs = a.extractThemeAttrs();
+
+ state.mScaleWidth = getPercent(
+ a, R.styleable.ScaleDrawable_scaleWidth, state.mScaleWidth);
+ state.mScaleHeight = getPercent(
+ a, R.styleable.ScaleDrawable_scaleHeight, state.mScaleHeight);
+ state.mGravity = a.getInt(R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT);
+ state.mUseIntrinsicSizeAsMin = a.getBoolean(
+ R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false);
+
+ final Drawable dr = a.getDrawable(R.styleable.ScaleDrawable_drawable);
+ if (dr != null) {
+ state.mDrawable = dr;
+ dr.setCallback(this);
}
}
@Override
public boolean canApplyTheme() {
- final ScaleState state = mScaleState;
- return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
+ return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
}
// overrides from Drawable.Callback
@@ -172,74 +213,74 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
@Override
public void draw(Canvas canvas) {
- if (mScaleState.mDrawable.getLevel() != 0)
- mScaleState.mDrawable.draw(canvas);
+ if (mState.mDrawable.getLevel() != 0)
+ mState.mDrawable.draw(canvas);
}
@Override
public int getChangingConfigurations() {
return super.getChangingConfigurations()
- | mScaleState.mChangingConfigurations
- | mScaleState.mDrawable.getChangingConfigurations();
+ | mState.mChangingConfigurations
+ | mState.mDrawable.getChangingConfigurations();
}
@Override
public boolean getPadding(Rect padding) {
// XXX need to adjust padding!
- return mScaleState.mDrawable.getPadding(padding);
+ return mState.mDrawable.getPadding(padding);
}
@Override
public boolean setVisible(boolean visible, boolean restart) {
- mScaleState.mDrawable.setVisible(visible, restart);
+ mState.mDrawable.setVisible(visible, restart);
return super.setVisible(visible, restart);
}
@Override
public void setAlpha(int alpha) {
- mScaleState.mDrawable.setAlpha(alpha);
+ mState.mDrawable.setAlpha(alpha);
}
@Override
public int getAlpha() {
- return mScaleState.mDrawable.getAlpha();
+ return mState.mDrawable.getAlpha();
}
@Override
public void setColorFilter(ColorFilter cf) {
- mScaleState.mDrawable.setColorFilter(cf);
+ mState.mDrawable.setColorFilter(cf);
}
@Override
public void setTintList(ColorStateList tint) {
- mScaleState.mDrawable.setTintList(tint);
+ mState.mDrawable.setTintList(tint);
}
@Override
public void setTintMode(Mode tintMode) {
- mScaleState.mDrawable.setTintMode(tintMode);
+ mState.mDrawable.setTintMode(tintMode);
}
@Override
public int getOpacity() {
- return mScaleState.mDrawable.getOpacity();
+ return mState.mDrawable.getOpacity();
}
@Override
public boolean isStateful() {
- return mScaleState.mDrawable.isStateful();
+ return mState.mDrawable.isStateful();
}
@Override
protected boolean onStateChange(int[] state) {
- boolean changed = mScaleState.mDrawable.setState(state);
+ boolean changed = mState.mDrawable.setState(state);
onBoundsChange(getBounds());
return changed;
}
@Override
protected boolean onLevelChange(int level) {
- mScaleState.mDrawable.setLevel(level);
+ mState.mDrawable.setLevel(level);
onBoundsChange(getBounds());
invalidateSelf();
return true;
@@ -248,41 +289,41 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
@Override
protected void onBoundsChange(Rect bounds) {
final Rect r = mTmpRect;
- final boolean min = mScaleState.mUseIntrinsicSizeAsMin;
+ final boolean min = mState.mUseIntrinsicSizeAsMin;
int level = getLevel();
int w = bounds.width();
- if (mScaleState.mScaleWidth > 0) {
- final int iw = min ? mScaleState.mDrawable.getIntrinsicWidth() : 0;
- w -= (int) ((w - iw) * (10000 - level) * mScaleState.mScaleWidth / 10000);
+ if (mState.mScaleWidth > 0) {
+ final int iw = min ? mState.mDrawable.getIntrinsicWidth() : 0;
+ w -= (int) ((w - iw) * (10000 - level) * mState.mScaleWidth / 10000);
}
int h = bounds.height();
- if (mScaleState.mScaleHeight > 0) {
- final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0;
- h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000);
+ if (mState.mScaleHeight > 0) {
+ final int ih = min ? mState.mDrawable.getIntrinsicHeight() : 0;
+ h -= (int) ((h - ih) * (10000 - level) * mState.mScaleHeight / 10000);
}
final int layoutDirection = getLayoutDirection();
- Gravity.apply(mScaleState.mGravity, w, h, bounds, r, layoutDirection);
+ Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection);
if (w > 0 && h > 0) {
- mScaleState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
+ mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
}
}
@Override
public int getIntrinsicWidth() {
- return mScaleState.mDrawable.getIntrinsicWidth();
+ return mState.mDrawable.getIntrinsicWidth();
}
@Override
public int getIntrinsicHeight() {
- return mScaleState.mDrawable.getIntrinsicHeight();
+ return mState.mDrawable.getIntrinsicHeight();
}
@Override
public ConstantState getConstantState() {
- if (mScaleState.canConstantState()) {
- mScaleState.mChangingConfigurations = getChangingConfigurations();
- return mScaleState;
+ if (mState.canConstantState()) {
+ mState.mChangingConfigurations = getChangingConfigurations();
+ return mState;
}
return null;
}
@@ -290,7 +331,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
- mScaleState.mDrawable.mutate();
+ mState.mDrawable.mutate();
mMutated = true;
}
return this;
@@ -301,23 +342,28 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
*/
public void clearMutated() {
super.clearMutated();
- mScaleState.mDrawable.clearMutated();
+ mState.mDrawable.clearMutated();
mMutated = false;
}
final static class ScaleState extends ConstantState {
- Drawable mDrawable;
+ int[] mThemeAttrs;
int mChangingConfigurations;
- float mScaleWidth;
- float mScaleHeight;
- int mGravity;
- boolean mUseIntrinsicSizeAsMin;
+
+ Drawable mDrawable;
+
+ float mScaleWidth = 1.0f;
+ float mScaleHeight = 1.0f;
+ int mGravity = Gravity.LEFT;
+ boolean mUseIntrinsicSizeAsMin = false;
private boolean mCheckedConstantState;
private boolean mCanConstantState;
ScaleState(ScaleState orig, ScaleDrawable owner, Resources res) {
if (orig != null) {
+ mThemeAttrs = orig.mThemeAttrs;
+ mChangingConfigurations = orig.mChangingConfigurations;
if (res != null) {
mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
} else {
@@ -336,6 +382,12 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
}
@Override
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+ || super.canApplyTheme();
+ }
+
+ @Override
public Drawable newDrawable() {
return new ScaleDrawable(this, null);
}
@@ -361,7 +413,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
}
private ScaleDrawable(ScaleState state, Resources res) {
- mScaleState = new ScaleState(state, this, res);
+ mState = new ScaleState(state, this, res);
}
}
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index a299b3c7c4db..963943b5fa5d 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -117,26 +117,48 @@ public class StateListDrawable extends DrawableContainer {
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
-
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.StateListDrawable);
+ super.inflateWithAttributes(r, parser, a, R.styleable.StateListDrawable_visible);
+ updateStateFromTypedArray(a);
+ a.recycle();
- super.inflateWithAttributes(r, parser, a,
- R.styleable.StateListDrawable_visible);
-
- mStateListState.setVariablePadding(a.getBoolean(
- R.styleable.StateListDrawable_variablePadding, false));
- mStateListState.setConstantSize(a.getBoolean(
- R.styleable.StateListDrawable_constantSize, false));
- mStateListState.setEnterFadeDuration(a.getInt(
- R.styleable.StateListDrawable_enterFadeDuration, 0));
- mStateListState.setExitFadeDuration(a.getInt(
- R.styleable.StateListDrawable_exitFadeDuration, 0));
+ inflateChildElements(r, parser, attrs, theme);
- setDither(a.getBoolean(R.styleable.StateListDrawable_dither, DEFAULT_DITHER));
- setAutoMirrored(a.getBoolean(R.styleable.StateListDrawable_autoMirrored, false));
+ onStateChange(getState());
+ }
- a.recycle();
+ /**
+ * Updates the constant state from the values in the typed array.
+ */
+ private void updateStateFromTypedArray(TypedArray a) {
+ final StateListState state = mStateListState;
+
+ // Account for any configuration changes.
+ state.mChangingConfigurations |= a.getChangingConfigurations();
+
+ // Extract the theme attributes, if any.
+ state.mThemeAttrs = a.extractThemeAttrs();
+
+ state.mVariablePadding = a.getBoolean(
+ R.styleable.StateListDrawable_variablePadding, state.mVariablePadding);
+ state.mConstantSize = a.getBoolean(
+ R.styleable.StateListDrawable_constantSize, state.mConstantSize);
+ state.mEnterFadeDuration = a.getInt(
+ R.styleable.StateListDrawable_enterFadeDuration, state.mEnterFadeDuration);
+ state.mExitFadeDuration = a.getInt(
+ R.styleable.StateListDrawable_exitFadeDuration, state.mExitFadeDuration);
+ state.mDither = a.getBoolean(
+ R.styleable.StateListDrawable_dither, state.mDither);
+ state.mAutoMirrored = a.getBoolean(
+ R.styleable.StateListDrawable_autoMirrored, state.mAutoMirrored);
+ }
+ /**
+ * Inflates child elements from XML.
+ */
+ private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
+ final StateListState state = mStateListState;
final int innerDepth = parser.getDepth() + 1;
int type;
int depth;
@@ -185,10 +207,8 @@ public class StateListDrawable extends DrawableContainer {
dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
- mStateListState.addStateSet(states, dr);
+ state.addStateSet(states, dr);
}
-
- onStateChange(getState());
}
StateListState getStateListState() {
@@ -282,6 +302,7 @@ public class StateListDrawable extends DrawableContainer {
}
static class StateListState extends DrawableContainerState {
+ int[] mThemeAttrs;
int[][] mStateSets;
StateListState(StateListState orig, StateListDrawable owner, Resources res) {
@@ -298,7 +319,11 @@ public class StateListDrawable extends DrawableContainer {
mStateSets[i] = set.clone();
}
}
+
+ mThemeAttrs = orig.mThemeAttrs;
+ mStateSets = Arrays.copyOf(orig.mStateSets, orig.mStateSets.length);
} else {
+ mThemeAttrs = null;
mStateSets = new int[getCapacity()][];
}
}
@@ -331,6 +356,11 @@ public class StateListDrawable extends DrawableContainer {
}
@Override
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null || super.canApplyTheme();
+ }
+
+ @Override
public void growArray(int oldSize, int newSize) {
super.growArray(oldSize, newSize);
final int[][] newStateSets = new int[newSize][];
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 848fc53d04c8..8b0f635482e0 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -361,7 +361,7 @@ public class VectorDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return super.canApplyTheme() || mVectorState != null && mVectorState.canApplyTheme();
+ return (mVectorState != null && mVectorState.canApplyTheme()) || super.canApplyTheme();
}
@Override
@@ -750,8 +750,8 @@ public class VectorDrawable extends Drawable {
@Override
public boolean canApplyTheme() {
- return super.canApplyTheme() || mThemeAttrs != null
- || (mVPathRenderer != null && mVPathRenderer.canApplyTheme());
+ return mThemeAttrs != null || (mVPathRenderer != null && mVPathRenderer.canApplyTheme())
+ || super.canApplyTheme();
}
public VectorDrawableState() {
diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java
index 9837139bbe0d..2b70b6a45f82 100644
--- a/graphics/java/android/graphics/pdf/PdfEditor.java
+++ b/graphics/java/android/graphics/pdf/PdfEditor.java
@@ -17,6 +17,10 @@
package android.graphics.pdf;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Matrix;
+import android.graphics.Point;
+import android.graphics.Rect;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.OsConstants;
@@ -55,6 +59,10 @@ public final class PdfEditor {
*
* @param input Seekable file descriptor to read from.
*
+ * @throws java.io.IOException If an error occurs while reading the file.
+ * @throws java.lang.SecurityException If the file requires a password or
+ * the security scheme is not supported.
+ *
* @see #close()
*/
public PdfEditor(@NonNull ParcelFileDescriptor input) throws IOException {
@@ -98,6 +106,109 @@ public final class PdfEditor {
}
/**
+ * Sets a transformation and clip for a given page. The transformation matrix if
+ * non-null must be affine as per {@link android.graphics.Matrix#isAffine()}. If
+ * the clip is null, then no clipping is performed.
+ *
+ * @param pageIndex The page whose transform to set.
+ * @param transform The transformation to apply.
+ * @param clip The clip to apply.
+ */
+ public void setTransformAndClip(int pageIndex, @Nullable Matrix transform,
+ @Nullable Rect clip) {
+ throwIfClosed();
+ throwIfPageNotInDocument(pageIndex);
+ throwIfNotNullAndNotAfine(transform);
+ if (transform == null) {
+ transform = Matrix.IDENTITY_MATRIX;
+ }
+ if (clip == null) {
+ Point size = new Point();
+ getPageSize(pageIndex, size);
+ nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance,
+ 0, 0, size.x, size.y);
+ } else {
+ nativeSetTransformAndClip(mNativeDocument, pageIndex, transform.native_instance,
+ clip.left, clip.top, clip.right, clip.bottom);
+ }
+ }
+
+ /**
+ * Gets the size of a given page in mils (1/72").
+ *
+ * @param pageIndex The page index.
+ * @param outSize The size output.
+ */
+ public void getPageSize(int pageIndex, @NonNull Point outSize) {
+ throwIfClosed();
+ throwIfOutSizeNull(outSize);
+ throwIfPageNotInDocument(pageIndex);
+ nativeGetPageSize(mNativeDocument, pageIndex, outSize);
+ }
+
+ /**
+ * Gets the media box of a given page in mils (1/72").
+ *
+ * @param pageIndex The page index.
+ * @param outMediaBox The media box output.
+ */
+ public boolean getPageMediaBox(int pageIndex, @NonNull Rect outMediaBox) {
+ throwIfClosed();
+ throwIfOutMediaBoxNull(outMediaBox);
+ throwIfPageNotInDocument(pageIndex);
+ return nativeGetPageMediaBox(mNativeDocument, pageIndex, outMediaBox);
+ }
+
+ /**
+ * Sets the media box of a given page in mils (1/72").
+ *
+ * @param pageIndex The page index.
+ * @param mediaBox The media box.
+ */
+ public void setPageMediaBox(int pageIndex, @NonNull Rect mediaBox) {
+ throwIfClosed();
+ throwIfMediaBoxNull(mediaBox);
+ throwIfPageNotInDocument(pageIndex);
+ nativeSetPageMediaBox(mNativeDocument, pageIndex, mediaBox);
+ }
+
+ /**
+ * Gets the crop box of a given page in mils (1/72").
+ *
+ * @param pageIndex The page index.
+ * @param outCropBox The crop box output.
+ */
+ public boolean getPageCropBox(int pageIndex, @NonNull Rect outCropBox) {
+ throwIfClosed();
+ throwIfOutCropBoxNull(outCropBox);
+ throwIfPageNotInDocument(pageIndex);
+ return nativeGetPageCropBox(mNativeDocument, pageIndex, outCropBox);
+ }
+
+ /**
+ * Sets the crop box of a given page in mils (1/72").
+ *
+ * @param pageIndex The page index.
+ * @param cropBox The crop box.
+ */
+ public void setPageCropBox(int pageIndex, @NonNull Rect cropBox) {
+ throwIfClosed();
+ throwIfCropBoxNull(cropBox);
+ throwIfPageNotInDocument(pageIndex);
+ nativeSetPageCropBox(mNativeDocument, pageIndex, cropBox);
+ }
+
+ /**
+ * Gets whether the document prefers to be scaled for printing.
+ *
+ * @return Whether to scale the document.
+ */
+ public boolean shouldScaleForPrinting() {
+ throwIfClosed();
+ return nativeScaleForPrinting(mNativeDocument);
+ }
+
+ /**
* Writes the PDF file to the provided destination.
* <p>
* <strong>Note:</strong> This method takes ownership of the passed in file
@@ -154,9 +265,57 @@ public final class PdfEditor {
}
}
+ private void throwIfNotNullAndNotAfine(Matrix matrix) {
+ if (matrix != null && !matrix.isAffine()) {
+ throw new IllegalStateException("Matrix must be afine");
+ }
+ }
+
+ private void throwIfOutSizeNull(Point outSize) {
+ if (outSize == null) {
+ throw new NullPointerException("outSize cannot be null");
+ }
+ }
+
+ private void throwIfOutMediaBoxNull(Rect outMediaBox) {
+ if (outMediaBox == null) {
+ throw new NullPointerException("outMediaBox cannot be null");
+ }
+ }
+
+ private void throwIfMediaBoxNull(Rect mediaBox) {
+ if (mediaBox == null) {
+ throw new NullPointerException("mediaBox cannot be null");
+ }
+ }
+
+ private void throwIfOutCropBoxNull(Rect outCropBox) {
+ if (outCropBox == null) {
+ throw new NullPointerException("outCropBox cannot be null");
+ }
+ }
+
+ private void throwIfCropBoxNull(Rect cropBox) {
+ if (cropBox == null) {
+ throw new NullPointerException("cropBox cannot be null");
+ }
+ }
+
private static native long nativeOpen(int fd, long size);
private static native void nativeClose(long documentPtr);
private static native int nativeGetPageCount(long documentPtr);
private static native int nativeRemovePage(long documentPtr, int pageIndex);
private static native void nativeWrite(long documentPtr, int fd);
+ private static native void nativeSetTransformAndClip(long documentPtr, int pageIndex,
+ long transformPtr, int clipLeft, int clipTop, int clipRight, int clipBottom);
+ private static native void nativeGetPageSize(long documentPtr, int pageIndex, Point outSize);
+ private static native boolean nativeGetPageMediaBox(long documentPtr, int pageIndex,
+ Rect outMediaBox);
+ private static native void nativeSetPageMediaBox(long documentPtr, int pageIndex,
+ Rect mediaBox);
+ private static native boolean nativeGetPageCropBox(long documentPtr, int pageIndex,
+ Rect outMediaBox);
+ private static native void nativeSetPageCropBox(long documentPtr, int pageIndex,
+ Rect mediaBox);
+ private static native boolean nativeScaleForPrinting(long documentPtr);
}
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index 359c29480d03..79934da09aa1 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -131,6 +131,10 @@ public final class PdfRenderer implements AutoCloseable {
* </p>
*
* @param input Seekable file descriptor to read from.
+ *
+ * @throws java.io.IOException If an error occurs while reading the file.
+ * @throws java.lang.SecurityException If the file requires a password or
+ * the security scheme is not supported.
*/
public PdfRenderer(@NonNull ParcelFileDescriptor input) throws IOException {
if (input == null) {
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index ac5eca08a4ff..85e442da0184 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -253,7 +253,8 @@ struct Res_value
// Type of the data value.
enum {
- // Contains no data.
+ // The 'data' is either 0 or 1, specifying this resource is either
+ // undefined or empty, respectively.
TYPE_NULL = 0x00,
// The 'data' holds a ResTable_ref, a reference to another resource
// table entry.
@@ -351,6 +352,14 @@ struct Res_value
COMPLEX_MANTISSA_MASK = 0xffffff
};
+ // Possible data values for TYPE_NULL.
+ enum {
+ // The value is not defined.
+ DATA_NULL_UNDEFINED = 0,
+ // The value is explicitly defined as empty.
+ DATA_NULL_EMPTY = 1
+ };
+
// The data for this item, as interpreted according to dataType.
uint32_t data;
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index b5d2885e3f37..3bbca1a0165e 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -4639,8 +4639,15 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString,
// It's a reference!
if (len == 5 && s[1]=='n' && s[2]=='u' && s[3]=='l' && s[4]=='l') {
+ // Special case @null as undefined. This will be converted by
+ // AssetManager to TYPE_NULL with data DATA_NULL_UNDEFINED.
outValue->data = 0;
return true;
+ } else if (len == 6 && s[1]=='e' && s[2]=='m' && s[3]=='p' && s[4]=='t' && s[5]=='y') {
+ // Special case @empty as explicitly defined empty value.
+ outValue->dataType = Res_value::TYPE_NULL;
+ outValue->data = Res_value::DATA_NULL_EMPTY;
+ return true;
} else {
bool createIfNotFound = false;
const char16_t* resourceRefName;
@@ -6251,7 +6258,14 @@ String8 ResTable::normalizeForOutput( const char *input )
void ResTable::print_value(const Package* pkg, const Res_value& value) const
{
if (value.dataType == Res_value::TYPE_NULL) {
- printf("(null)\n");
+ if (value.data == Res_value::DATA_NULL_UNDEFINED) {
+ printf("(null)\n");
+ } else if (value.data == Res_value::DATA_NULL_EMPTY) {
+ printf("(null empty)\n");
+ } else {
+ // This should never happen.
+ printf("(null) 0x%08x\n", value.data);
+ }
} else if (value.dataType == Res_value::TYPE_REFERENCE) {
printf("(reference) 0x%08x\n", value.data);
} else if (value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE) {
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index f0bf7b22ff01..ad50894ee073 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -265,14 +265,27 @@ void Caches::dumpMemoryUsage() {
}
void Caches::dumpMemoryUsage(String8 &log) {
+ uint32_t total = 0;
log.appendFormat("Current memory usage / total memory usage (bytes):\n");
log.appendFormat(" TextureCache %8d / %8d\n",
textureCache.getSize(), textureCache.getMaxSize());
log.appendFormat(" LayerCache %8d / %8d (numLayers = %zu)\n",
layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount());
- log.appendFormat(" Garbage layers %8zu\n", mLayerGarbage.size());
- log.appendFormat(" Active layers %8zu\n",
- mRenderState ? mRenderState->mActiveLayers.size() : 0);
+ if (mRenderState) {
+ int memused = 0;
+ for (std::set<const Layer*>::iterator it = mRenderState->mActiveLayers.begin();
+ it != mRenderState->mActiveLayers.end(); it++) {
+ const Layer* layer = *it;
+ log.appendFormat(" Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n",
+ layer->getWidth(), layer->getHeight(),
+ layer->isTextureLayer(), layer->getTexture(),
+ layer->getFbo(), layer->getStrongCount());
+ memused = layer->getWidth() * layer->getHeight() * 4;
+ }
+ log.appendFormat(" Layers total %8d (numLayers = %zu)\n",
+ memused, mRenderState->mActiveLayers.size());
+ total += memused;
+ }
log.appendFormat(" RenderBufferCache %8d / %8d\n",
renderBufferCache.getSize(), renderBufferCache.getMaxSize());
log.appendFormat(" GradientCache %8d / %8d\n",
@@ -297,9 +310,7 @@ void Caches::dumpMemoryUsage(String8 &log) {
log.appendFormat(" FboCache %8d / %8d\n",
fboCache.getSize(), fboCache.getMaxSize());
- uint32_t total = 0;
total += textureCache.getSize();
- total += layerCache.getSize();
total += renderBufferCache.getSize();
total += gradientCache.getSize();
total += pathCache.getSize();
@@ -323,27 +334,6 @@ void Caches::clearGarbage() {
textureCache.clearGarbage();
pathCache.clearGarbage();
patchCache.clearGarbage();
-
- Vector<Layer*> layers;
-
- { // scope for the lock
- Mutex::Autolock _l(mGarbageLock);
- layers = mLayerGarbage;
- mLayerGarbage.clear();
- }
-
- size_t count = layers.size();
- for (size_t i = 0; i < count; i++) {
- Layer* layer = layers.itemAt(i);
- delete layer;
- }
- layers.clear();
-}
-
-void Caches::deleteLayerDeferred(Layer* layer) {
- Mutex::Autolock _l(mGarbageLock);
- layer->state = Layer::kState_InGarbageList;
- mLayerGarbage.push(layer);
}
void Caches::flush(FlushMode mode) {
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index a6d7e78b87bf..d02455c8fc1d 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -24,25 +24,6 @@
namespace android {
namespace uirenderer {
-class DeleteLayerTask : public renderthread::RenderTask {
-public:
- DeleteLayerTask(renderthread::EglManager& eglManager, Layer* layer)
- : mEglManager(eglManager)
- , mLayer(layer)
- {}
-
- virtual void run() {
- mEglManager.requireGlContext();
- LayerRenderer::destroyLayer(mLayer);
- mLayer = 0;
- delete this;
- }
-
-private:
- renderthread::EglManager& mEglManager;
- Layer* mLayer;
-};
-
DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, Layer* layer)
: mSurfaceTexture(0)
, mTransform(0)
@@ -62,7 +43,7 @@ DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, L
DeferredLayerUpdater::~DeferredLayerUpdater() {
SkSafeUnref(mColorFilter);
setTransform(0);
- mRenderThread.queue(new DeleteLayerTask(mRenderThread.eglManager(), mLayer));
+ mLayer->postDecStrong();
mLayer = 0;
}
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index d8932ce4631e..4a927cfc6399 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -61,10 +61,6 @@ void DisplayListData::cleanupResources() {
caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
}
- for (size_t i = 0; i < layers.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(layers.itemAt(i));
- }
-
caches.resourceCache.unlock();
for (size_t i = 0; i < paints.size(); i++) {
@@ -86,7 +82,6 @@ void DisplayListData::cleanupResources() {
paints.clear();
regions.clear();
paths.clear();
- layers.clear();
}
size_t DisplayListData::addChild(DrawRenderNodeOp* op) {
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index dea109cd57b7..cb8a8d1cbc88 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -147,7 +147,6 @@ public:
Vector<const SkPath*> paths;
SortedVector<const SkPath*> sourcePaths;
Vector<const SkRegion*> regions;
- Vector<Layer*> layers;
Vector<Functor*> functors;
const Vector<Chunk>& getChunks() const {
@@ -157,11 +156,7 @@ public:
size_t addChild(DrawRenderNodeOp* childOp);
const Vector<DrawRenderNodeOp*>& children() { return mChildren; }
- void refProperty(CanvasPropertyPrimitive* prop) {
- mReferenceHolders.push(prop);
- }
-
- void refProperty(CanvasPropertyPaint* prop) {
+ void ref(VirtualLightRefBase* prop) {
mReferenceHolders.push(prop);
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 1f7092147686..c17dd098d4e6 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -189,7 +189,7 @@ status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty
}
status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y) {
- layer = refLayer(layer);
+ mDisplayListData->ref(layer);
addDrawOp(new (alloc()) DrawLayerOp(layer, x, y));
return DrawGlInfo::kStatusDone;
}
@@ -280,13 +280,13 @@ status_t DisplayListRenderer::drawRoundRect(
CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
CanvasPropertyPaint* paint) {
- mDisplayListData->refProperty(left);
- mDisplayListData->refProperty(top);
- mDisplayListData->refProperty(right);
- mDisplayListData->refProperty(bottom);
- mDisplayListData->refProperty(rx);
- mDisplayListData->refProperty(ry);
- mDisplayListData->refProperty(paint);
+ mDisplayListData->ref(left);
+ mDisplayListData->ref(top);
+ mDisplayListData->ref(right);
+ mDisplayListData->ref(bottom);
+ mDisplayListData->ref(rx);
+ mDisplayListData->ref(ry);
+ mDisplayListData->ref(paint);
addDrawOp(new (alloc()) DrawRoundRectPropsOp(&left->value, &top->value,
&right->value, &bottom->value, &rx->value, &ry->value, &paint->value));
return DrawGlInfo::kStatusDone;
@@ -300,10 +300,10 @@ status_t DisplayListRenderer::drawCircle(float x, float y, float radius, const S
status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
- mDisplayListData->refProperty(x);
- mDisplayListData->refProperty(y);
- mDisplayListData->refProperty(radius);
- mDisplayListData->refProperty(paint);
+ mDisplayListData->ref(x);
+ mDisplayListData->ref(y);
+ mDisplayListData->ref(radius);
+ mDisplayListData->ref(paint);
addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value,
&radius->value, &paint->value));
return DrawGlInfo::kStatusDone;
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 3a3fc3af9f0f..901e8f02fa7a 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -267,12 +267,6 @@ private:
return regionCopy;
}
- inline Layer* refLayer(Layer* layer) {
- mDisplayListData->layers.add(layer);
- mCaches.resourceCache.incrementRefcount(layer);
- return layer;
- }
-
inline const SkBitmap* refBitmap(const SkBitmap* bitmap) {
// Note that this assumes the bitmap is immutable. There are cases this won't handle
// correctly, such as creating the bitmap from scratch, drawing with it, changing its
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index b5089aa79ff3..b95636bbf7db 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -35,6 +35,9 @@ Layer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth
, renderState(renderState)
, texture(caches)
, type(layerType) {
+ // TODO: This is a violation of Android's typical ref counting, but it
+ // preserves the old inc/dec ref locations. This should be changed...
+ incStrong(0);
mesh = NULL;
meshElementCount = 0;
cacheable = true;
@@ -53,20 +56,14 @@ Layer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth
forceFilter = false;
deferredList = NULL;
convexMask = NULL;
- caches.resourceCache.incrementRefcount(this);
rendererLightPosDirty = true;
wasBuildLayered = false;
- if (!isTextureLayer()) {
- // track only non-texture layer lifecycles in renderstate,
- // because texture layers are destroyed via finalizer
- renderState.registerLayer(this);
- }
+ renderState.registerLayer(this);
}
Layer::~Layer() {
- if (!isTextureLayer()) {
- renderState.unregisterLayer(this);
- }
+ renderState.requireGLContext();
+ renderState.unregisterLayer(this);
SkSafeUnref(colorFilter);
removeFbo();
deleteTexture();
@@ -292,5 +289,9 @@ void Layer::render(const OpenGLRenderer& rootRenderer) {
renderNode = NULL;
}
+void Layer::postDecStrong() {
+ renderState.postDecStrong(this);
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index a8e1c2671064..64d1d1226ffb 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -52,7 +52,7 @@ class DeferStateStruct;
/**
* A layer has dimensions and is backed by an OpenGL texture or FBO.
*/
-class Layer {
+class Layer : public VirtualLightRefBase {
public:
enum Type {
kType_Texture,
@@ -280,6 +280,12 @@ public:
void render(const OpenGLRenderer& rootRenderer);
/**
+ * Posts a decStrong call to the appropriate thread.
+ * Thread-safe.
+ */
+ void postDecStrong();
+
+ /**
* Bounds of the layer.
*/
Rect layer;
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 833f64bc96e7..3033dc689c22 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -84,7 +84,7 @@ void LayerCache::deleteLayer(Layer* layer) {
layer->getFbo());
mSize -= layer->getWidth() * layer->getHeight() * 4;
layer->state = Layer::kState_DeletedFromCache;
- Caches::getInstance().resourceCache.decrementRefcount(layer);
+ layer->decStrong(0);
}
}
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 103c84324627..394c64795aee 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -212,7 +212,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width
// Creating a new layer always increment its refcount by 1, this allows
// us to destroy the layer object if one was created for us
- Caches::getInstance().resourceCache.decrementRefcount(layer);
+ layer->decStrong(0);
return NULL;
}
@@ -240,7 +240,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width
if (glGetError() != GL_NO_ERROR) {
ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height);
renderState.bindFramebuffer(previousFbo);
- caches.resourceCache.decrementRefcount(layer);
+ layer->decStrong(0);
return NULL;
}
}
@@ -316,7 +316,7 @@ void LayerRenderer::destroyLayer(Layer* layer) {
if (!Caches::getInstance().layerCache.put(layer)) {
LAYER_RENDERER_LOGD(" Destroyed!");
- Caches::getInstance().resourceCache.decrementRefcount(layer);
+ layer->decStrong(0);
} else {
LAYER_RENDERER_LOGD(" Cached!");
#if DEBUG_LAYER_RENDERER
@@ -328,14 +328,6 @@ void LayerRenderer::destroyLayer(Layer* layer) {
}
}
-void LayerRenderer::destroyLayerDeferred(Layer* layer) {
- if (layer) {
- LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->getFbo());
-
- Caches::getInstance().deleteLayerDeferred(layer);
- }
-}
-
void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) {
#ifdef GL_EXT_discard_framebuffer
if (!layer) return;
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index bf7828c3c175..4d8620b8a4ea 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -60,7 +60,6 @@ public:
static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform);
static void destroyLayer(Layer* layer);
- ANDROID_API static void destroyLayerDeferred(Layer* layer);
static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap);
static void flushLayer(RenderState& renderState, Layer* layer);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 19fc9a3caf0d..d570b0d5bc9c 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -509,11 +509,8 @@ void OpenGLRenderer::updateLayers() {
// Note: it is very important to update the layers in order
for (int i = 0; i < count; i++) {
- Layer* layer = mLayerUpdates.itemAt(i);
+ Layer* layer = mLayerUpdates.itemAt(i).get();
updateLayer(layer, false);
- if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
- mCaches.resourceCache.decrementRefcount(layer);
- }
}
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
@@ -532,7 +529,7 @@ void OpenGLRenderer::flushLayers() {
// Note: it is very important to update the layers in order
for (int i = 0; i < count; i++) {
- Layer* layer = mLayerUpdates.itemAt(i);
+ Layer* layer = mLayerUpdates.itemAt(i).get();
sprintf(layerName, "Layer #%d", i);
startMark(layerName);
@@ -542,8 +539,6 @@ void OpenGLRenderer::flushLayers() {
ATRACE_END();
endMark();
-
- mCaches.resourceCache.decrementRefcount(layer);
}
mLayerUpdates.clear();
@@ -565,7 +560,6 @@ void OpenGLRenderer::pushLayerUpdate(Layer* layer) {
}
}
mLayerUpdates.push_back(layer);
- mCaches.resourceCache.incrementRefcount(layer);
}
}
@@ -574,25 +568,12 @@ void OpenGLRenderer::cancelLayerUpdate(Layer* layer) {
for (int i = mLayerUpdates.size() - 1; i >= 0; i--) {
if (mLayerUpdates.itemAt(i) == layer) {
mLayerUpdates.removeAt(i);
- mCaches.resourceCache.decrementRefcount(layer);
break;
}
}
}
}
-void OpenGLRenderer::clearLayerUpdates() {
- size_t count = mLayerUpdates.size();
- if (count > 0) {
- mCaches.resourceCache.lock();
- for (size_t i = 0; i < count; i++) {
- mCaches.resourceCache.decrementRefcountLocked(mLayerUpdates.itemAt(i));
- }
- mCaches.resourceCache.unlock();
- mLayerUpdates.clear();
- }
-}
-
void OpenGLRenderer::flushLayerUpdates() {
ATRACE_CALL();
syncState();
@@ -956,7 +937,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto
layer->setConvexMask(NULL);
if (!mCaches.layerCache.put(layer)) {
LAYER_LOGD("Deleting layer");
- Caches::getInstance().resourceCache.decrementRefcount(layer);
+ layer->decStrong(0);
}
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index c2c0b0efc72e..e1c3d10fc9c9 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -140,7 +140,6 @@ public:
void pushLayerUpdate(Layer* layer);
void cancelLayerUpdate(Layer* layer);
- void clearLayerUpdates();
void flushLayerUpdates();
void markLayersAsBuildLayers();
@@ -982,7 +981,7 @@ private:
// List of rectangles to clear after saveLayer() is invoked
Vector<Rect*> mLayers;
// List of layers to update at the beginning of a frame
- Vector<Layer*> mLayerUpdates;
+ Vector< sp<Layer> > mLayerUpdates;
// The following fields are used to setup drawing
// Used to describe the shaders to generate
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 40cd13ef4f02..c9ed9a7d780b 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -87,7 +87,11 @@ RenderNode::RenderNode()
RenderNode::~RenderNode() {
deleteDisplayListData();
delete mStagingDisplayListData;
- LayerRenderer::destroyLayerDeferred(mLayer);
+ if (mLayer) {
+ ALOGW("Memory Warning: Layer %p missed its detachment, held on to for far too long!", mLayer);
+ mLayer->postDecStrong();
+ mLayer = 0;
+ }
}
void RenderNode::setStagingDisplayList(DisplayListData* data) {
@@ -201,6 +205,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
info.damageAccumulator->peekAtDirty(&dirty);
if (!mLayer) {
+ Caches::getInstance().dumpMemoryUsage();
if (info.errorHandler) {
std::string msg = "Unable to create layer for ";
msg += getName();
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index f32928301fc4..2ce7cb7f3034 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -101,7 +101,7 @@ public:
kReplayFlag_ClipChildren = 0x1
};
- ANDROID_API static void outputLogBuffer(int fd);
+ static void outputLogBuffer(int fd);
void debugDumpLayers(const char* prefix);
ANDROID_API void setStagingDisplayList(DisplayListData* newData);
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
index 86bd7dd00ccd..a8cf26f0d5da 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/RenderState.cpp
@@ -16,15 +16,18 @@
#include "RenderState.h"
#include "renderthread/CanvasContext.h"
+#include "renderthread/EglManager.h"
namespace android {
namespace uirenderer {
-RenderState::RenderState()
- : mCaches(NULL)
+RenderState::RenderState(renderthread::RenderThread& thread)
+ : mRenderThread(thread)
+ , mCaches(NULL)
, mViewportWidth(0)
, mViewportHeight(0)
, mFramebuffer(0) {
+ mThreadId = pthread_self();
}
RenderState::~RenderState() {
@@ -39,7 +42,6 @@ void RenderState::onGLContextCreated() {
void RenderState::onGLContextDestroyed() {
/*
- AutoMutex _lock(mLayerLock);
size_t size = mActiveLayers.size();
if (CC_UNLIKELY(size != 0)) {
ALOGE("Crashing, have %d contexts and %d layers at context destruction. isempty %d",
@@ -146,5 +148,34 @@ void RenderState::debugOverdraw(bool enable, bool clear) {
}
}
+void RenderState::requireGLContext() {
+ assertOnGLThread();
+ mRenderThread.eglManager().requireGlContext();
+}
+
+void RenderState::assertOnGLThread() {
+ pthread_t curr = pthread_self();
+ LOG_ALWAYS_FATAL_IF(!pthread_equal(mThreadId, curr), "Wrong thread!");
+}
+
+
+class DecStrongTask : public renderthread::RenderTask {
+public:
+ DecStrongTask(VirtualLightRefBase* object) : mObject(object) {}
+
+ virtual void run() {
+ mObject->decStrong(0);
+ mObject = 0;
+ delete this;
+ }
+
+private:
+ VirtualLightRefBase* mObject;
+};
+
+void RenderState::postDecStrong(VirtualLightRefBase* object) {
+ mRenderThread.queue(new DecStrongTask(object));
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
index cbe7cfc3db4e..afeef950d5cd 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/RenderState.h
@@ -53,16 +53,10 @@ public:
void debugOverdraw(bool enable, bool clear);
void registerLayer(const Layer* layer) {
- /*
- AutoMutex _lock(mLayerLock);
mActiveLayers.insert(layer);
- */
}
void unregisterLayer(const Layer* layer) {
- /*
- AutoMutex _lock(mLayerLock);
mActiveLayers.erase(layer);
- */
}
void registerCanvasContext(renderthread::CanvasContext* context) {
@@ -73,16 +67,24 @@ public:
mRegisteredContexts.erase(context);
}
+ void requireGLContext();
+
+ // TODO: This system is a little clunky feeling, this could use some
+ // more thinking...
+ void postDecStrong(VirtualLightRefBase* object);
+
private:
friend class renderthread::RenderThread;
friend class Caches;
void interruptForFunctorInvoke();
void resumeFromFunctorInvoke();
+ void assertOnGLThread();
- RenderState();
+ RenderState(renderthread::RenderThread& thread);
~RenderState();
+ renderthread::RenderThread& mRenderThread;
Caches* mCaches;
std::set<const Layer*> mActiveLayers;
std::set<renderthread::CanvasContext*> mRegisteredContexts;
@@ -90,7 +92,8 @@ private:
GLsizei mViewportWidth;
GLsizei mViewportHeight;
GLuint mFramebuffer;
- Mutex mLayerLock;
+
+ pthread_t mThreadId;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 8b553d1383d4..329d92f0be13 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -75,10 +75,6 @@ void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
incrementRefcount((void*) patchResource, kNinePatch);
}
-void ResourceCache::incrementRefcount(Layer* layerResource) {
- incrementRefcount((void*) layerResource, kLayer);
-}
-
void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) {
ssize_t index = mCache->indexOfKey(resource);
ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
@@ -103,10 +99,6 @@ void ResourceCache::incrementRefcountLocked(const Res_png_9patch* patchResource)
incrementRefcountLocked((void*) patchResource, kNinePatch);
}
-void ResourceCache::incrementRefcountLocked(Layer* layerResource) {
- incrementRefcountLocked((void*) layerResource, kLayer);
-}
-
void ResourceCache::decrementRefcount(void* resource) {
Mutex::Autolock _l(mLock);
decrementRefcountLocked(resource);
@@ -126,10 +118,6 @@ void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
decrementRefcount((void*) patchResource);
}
-void ResourceCache::decrementRefcount(Layer* layerResource) {
- decrementRefcount((void*) layerResource);
-}
-
void ResourceCache::decrementRefcountLocked(void* resource) {
ssize_t index = mCache->indexOfKey(resource);
ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
@@ -157,10 +145,6 @@ void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource)
decrementRefcountLocked((void*) patchResource);
}
-void ResourceCache::decrementRefcountLocked(Layer* layerResource) {
- decrementRefcountLocked((void*) layerResource);
-}
-
void ResourceCache::destructor(SkPath* resource) {
Mutex::Autolock _l(mLock);
destructorLocked(resource);
@@ -274,7 +258,7 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource
if (ref->recycled && ref->resourceType == kBitmap) {
((SkBitmap*) resource)->setPixels(NULL, NULL);
}
- if (ref->destroyed || ref->resourceType == kLayer) {
+ if (ref->destroyed) {
switch (ref->resourceType) {
case kBitmap: {
SkBitmap* bitmap = (SkBitmap*) resource;
@@ -305,11 +289,6 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource
}
}
break;
- case kLayer: {
- Layer* layer = (Layer*) resource;
- Caches::getInstance().deleteLayerDeferred(layer);
- }
- break;
}
}
mCache->removeItem(resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 3864d4bf2a7d..8539d123b09a 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -36,8 +36,7 @@ namespace uirenderer {
enum ResourceType {
kBitmap,
kNinePatch,
- kPath,
- kLayer
+ kPath
};
class ResourceReference {
@@ -69,22 +68,18 @@ public:
void incrementRefcount(const SkPath* resource);
void incrementRefcount(const SkBitmap* resource);
void incrementRefcount(const Res_png_9patch* resource);
- void incrementRefcount(Layer* resource);
void incrementRefcountLocked(const SkPath* resource);
void incrementRefcountLocked(const SkBitmap* resource);
void incrementRefcountLocked(const Res_png_9patch* resource);
- void incrementRefcountLocked(Layer* resource);
void decrementRefcount(const SkBitmap* resource);
void decrementRefcount(const SkPath* resource);
void decrementRefcount(const Res_png_9patch* resource);
- void decrementRefcount(Layer* resource);
void decrementRefcountLocked(const SkBitmap* resource);
void decrementRefcountLocked(const SkPath* resource);
void decrementRefcountLocked(const Res_png_9patch* resource);
- void decrementRefcountLocked(Layer* resource);
void destructor(SkPath* resource);
void destructor(const SkBitmap* resource);
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 9d2ae8b6d8ad..b499dd086312 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -236,6 +236,8 @@ void CanvasContext::draw() {
if (status & DrawGlInfo::kStatusDrew) {
swapBuffers();
+ } else {
+ mEglManager.cancelFrame();
}
profiler().finishFrame();
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 760fc15a8cf7..9bd6f41a9614 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -73,7 +73,8 @@ EglManager::EglManager(RenderThread& thread)
, mAllowPreserveBuffer(load_dirty_regions_property())
, mCurrentSurface(EGL_NO_SURFACE)
, mAtlasMap(NULL)
- , mAtlasMapSize(0) {
+ , mAtlasMapSize(0)
+ , mInFrame(false) {
mCanSetPreserveBuffer = mAllowPreserveBuffer;
ALOGD("Use EGL_SWAP_BEHAVIOR_PRESERVED: %s", mAllowPreserveBuffer ? "true" : "false");
}
@@ -105,9 +106,10 @@ bool EglManager::hasEglContext() {
void EglManager::requireGlContext() {
LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "No EGL context");
- // We don't care *WHAT* surface is active, just that one is active to give
- // us access to the GL context
- if (mCurrentSurface == EGL_NO_SURFACE) {
+ if (!mInFrame) {
+ // We can't be certain about the state of the current surface (whether
+ // or not it is destroyed, for example), so err on the side of using
+ // the pbuffer surface which we fully control
usePBufferSurface();
}
}
@@ -252,9 +254,11 @@ void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) {
eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
}
eglBeginFrame(mEglDisplay, surface);
+ mInFrame = true;
}
bool EglManager::swapBuffers(EGLSurface surface) {
+ mInFrame = false;
eglSwapBuffers(mEglDisplay, surface);
EGLint err = eglGetError();
if (CC_LIKELY(err == EGL_SUCCESS)) {
@@ -273,6 +277,10 @@ bool EglManager::swapBuffers(EGLSurface surface) {
return false;
}
+void EglManager::cancelFrame() {
+ mInFrame = false;
+}
+
bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) {
if (CC_UNLIKELY(!mAllowPreserveBuffer)) return false;
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index ae03ea1fc3b8..e12db3acbe2f 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -48,6 +48,7 @@ public:
bool makeCurrent(EGLSurface surface);
void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
bool swapBuffers(EGLSurface surface);
+ void cancelFrame();
// Returns true iff the surface is now preserving buffers.
bool setPreserveBuffer(EGLSurface surface, bool preserve);
@@ -80,6 +81,12 @@ private:
sp<GraphicBuffer> mAtlasBuffer;
int64_t* mAtlasMap;
size_t mAtlasMapSize;
+
+ // Whether or not we are in the middle of drawing a frame. This is used
+ // to avoid switching surfaces mid-frame if requireGlContext() is called
+ // TODO: Need to be better about surface/context management so that this isn't
+ // necessary
+ bool mInFrame;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 8f99b4ed90c6..5d55ea62af1f 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -235,12 +235,7 @@ void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
// waitForCompletion = true is expected to be fairly rare and only
// happen in destruction. Thus it should be fine to temporarily
// create a Mutex
- Mutex mutex;
- Condition condition;
- SignalingRenderTask syncTask(task, &mutex, &condition);
- AutoMutex _lock(mutex);
- thread.queue(&syncTask);
- condition.wait(mutex);
+ staticPostAndWait(task);
} else {
thread.queue(task);
}
@@ -258,17 +253,6 @@ void RenderProxy::runWithGlContext(RenderTask* gltask) {
postAndWait(task);
}
-CREATE_BRIDGE1(destroyLayer, Layer* layer) {
- LayerRenderer::destroyLayer(args->layer);
- return NULL;
-}
-
-void RenderProxy::enqueueDestroyLayer(Layer* layer) {
- SETUP_TASK(destroyLayer);
- args->layer = layer;
- RenderThread::getInstance().queue(task);
-}
-
CREATE_BRIDGE2(createTextureLayer, RenderThread* thread, CanvasContext* context) {
Layer* layer = args->context->createTextureLayer();
if (!layer) return 0;
@@ -400,6 +384,17 @@ void RenderProxy::dumpProfileInfo(int fd) {
postAndWait(task);
}
+CREATE_BRIDGE1(outputLogBuffer, int fd) {
+ RenderNode::outputLogBuffer(args->fd);
+ return NULL;
+}
+
+void RenderProxy::outputLogBuffer(int fd) {
+ SETUP_TASK(outputLogBuffer);
+ args->fd = fd;
+ staticPostAndWait(task);
+}
+
CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) {
CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size);
args->buffer->decStrong(0);
@@ -430,6 +425,19 @@ void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
return retval;
}
+void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) {
+ RenderThread& thread = RenderThread::getInstance();
+ void* retval;
+ task->setReturnPtr(&retval);
+ Mutex mutex;
+ Condition condition;
+ SignalingRenderTask syncTask(task, &mutex, &condition);
+ AutoMutex _lock(mutex);
+ thread.queue(&syncTask);
+ condition.wait(mutex);
+ return retval;
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index dddf0c746249..4989b1492838 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -81,7 +81,6 @@ public:
ANDROID_API void runWithGlContext(RenderTask* task);
- static void enqueueDestroyLayer(Layer* layer);
ANDROID_API DeferredLayerUpdater* createTextureLayer();
ANDROID_API void buildLayer(RenderNode* node);
ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
@@ -97,6 +96,7 @@ public:
ANDROID_API void notifyFramePending();
ANDROID_API void dumpProfileInfo(int fd);
+ ANDROID_API static void outputLogBuffer(int fd);
ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
@@ -114,6 +114,8 @@ private:
void post(RenderTask* task);
void* postAndWait(MethodInvokeRenderTask* task);
+ static void* staticPostAndWait(MethodInvokeRenderTask* task);
+
// Friend class to help with bridging
friend class RenderProxyBridge;
};
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 403e1644bc7b..f887103e28ae 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -168,7 +168,7 @@ void RenderThread::initializeDisplayEventReceiver() {
void RenderThread::initThreadLocals() {
initializeDisplayEventReceiver();
mEglManager = new EglManager(*this);
- mRenderState = new RenderState();
+ mRenderState = new RenderState(*this);
}
int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 17d3251b3a6f..20c4978e779b 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -161,6 +161,12 @@ public final class AudioAttributes implements Parcelable {
* Usage value to use when the usage is for game audio.
*/
public final static int USAGE_GAME = 14;
+ /**
+ * @hide
+ * Usage value to use when feeding audio to the platform and replacing "traditional" audio
+ * source, such as audio capture devices.
+ */
+ public final static int USAGE_VIRTUAL_SOURCE = 15;
/**
* Flag defining a behavior where the audibility of the sound will be ensured by the system.
@@ -374,6 +380,7 @@ public final class AudioAttributes implements Parcelable {
case USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
case USAGE_ASSISTANCE_SONIFICATION:
case USAGE_GAME:
+ case USAGE_VIRTUAL_SOURCE:
mUsage = usage;
break;
default:
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 716ff992c008..8fc0b8e4a86d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2663,9 +2663,13 @@ public class AudioManager {
}
IAudioService service = getService();
try {
- if (!service.registerAudioPolicy(policy.getConfig(), policy.token())) {
+ String regId = service.registerAudioPolicy(policy.getConfig(), policy.token());
+ if (regId == null) {
return ERROR;
+ } else {
+ policy.setRegistration(regId);
}
+ // successful registration
} catch (RemoteException e) {
Log.e(TAG, "Dead object in registerAudioPolicyAsync()", e);
return ERROR;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index a84fe440736e..2f683828d3b1 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -48,6 +48,7 @@ import android.hardware.hdmi.HdmiTvClient;
import android.hardware.usb.UsbManager;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
+import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioPolicyConfig;
import android.media.session.MediaSessionLegacyHelper;
import android.os.Binder;
@@ -118,6 +119,10 @@ public class AudioService extends IAudioService.Stub {
/** Debug audio mode */
protected static final boolean DEBUG_MODE = Log.isLoggable(TAG + ".MOD", Log.DEBUG);
+
+ /** Debug audio policy feature */
+ protected static final boolean DEBUG_AP = Log.isLoggable(TAG + ".AP", Log.DEBUG);
+
/** Debug volumes */
protected static final boolean DEBUG_VOL = Log.isLoggable(TAG + ".VOL", Log.DEBUG);
@@ -2574,13 +2579,17 @@ public class AudioService extends IAudioService.Stub {
if (mScoAudioState == SCO_STATE_INACTIVE) {
mScoAudioMode = scoAudioMode;
if (scoAudioMode == SCO_MODE_UNDEFINED) {
- mScoAudioMode = new Integer(Settings.Global.getInt(
- mContentResolver,
- "bluetooth_sco_channel_"+
- mBluetoothHeadsetDevice.getAddress(),
- SCO_MODE_VIRTUAL_CALL));
- if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
- mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
+ if (mBluetoothHeadsetDevice != null) {
+ mScoAudioMode = new Integer(Settings.Global.getInt(
+ mContentResolver,
+ "bluetooth_sco_channel_"+
+ mBluetoothHeadsetDevice.getAddress(),
+ SCO_MODE_VIRTUAL_CALL));
+ if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
+ mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
+ }
+ } else {
+ mScoAudioMode = SCO_MODE_RAW;
}
}
if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
@@ -5630,31 +5639,33 @@ public class AudioService extends IAudioService.Stub {
//==========================================================================================
// Audio policy management
//==========================================================================================
- public boolean registerAudioPolicy(AudioPolicyConfig policyConfig, IBinder cb) {
+ public String registerAudioPolicy(AudioPolicyConfig policyConfig, IBinder cb) {
//Log.v(TAG, "registerAudioPolicy for " + cb + " got policy:" + policyConfig);
+ String regId = null;
boolean hasPermissionForPolicy =
(PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
android.Manifest.permission.MODIFY_AUDIO_ROUTING));
if (!hasPermissionForPolicy) {
Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid "
+ Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
- return false;
+ return null;
}
synchronized (mAudioPolicies) {
- AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, cb);
try {
+ AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, cb);
cb.linkToDeath(app, 0/*flags*/);
+ regId = app.connectMixes();
mAudioPolicies.put(cb, app);
} catch (RemoteException e) {
// audio policy owner has already died!
Slog.w(TAG, "Audio policy registration failed, could not link to " + cb +
" binder death", e);
- return false;
+ return null;
}
}
- // TODO implement registration with native audio policy (including permission check)
- return true;
+ return regId;
}
+
public void unregisterAudioPolicyAsync(IBinder cb) {
synchronized (mAudioPolicies) {
AudioPolicyProxy app = mAudioPolicies.remove(cb);
@@ -5664,27 +5675,59 @@ public class AudioService extends IAudioService.Stub {
} else {
cb.unlinkToDeath(app, 0/*flags*/);
}
+ app.disconnectMixes();
}
- // TODO implement registration with native audio policy
+ // TODO implement clearing mix attribute matching info in native audio policy
}
- public class AudioPolicyProxy implements IBinder.DeathRecipient {
+ /**
+ * This internal class inherits from AudioPolicyConfig which contains all the mixes and
+ * their configurations.
+ */
+ public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
private static final String TAG = "AudioPolicyProxy";
AudioPolicyConfig mConfig;
IBinder mToken;
AudioPolicyProxy(AudioPolicyConfig config, IBinder token) {
- mConfig = config;
+ super(config);
+ setRegistration(new String(config.toString() + ":ap:" + mAudioPolicyCounter++));
mToken = token;
}
public void binderDied() {
synchronized (mAudioPolicies) {
- Log.v(TAG, "audio policy " + mToken + " died");
+ Log.i(TAG, "audio policy " + mToken + " died");
mAudioPolicies.remove(mToken);
+ disconnectMixes();
+ }
+ }
+
+ String connectMixes() {
+ updateMixes(AudioSystem.DEVICE_STATE_AVAILABLE);
+ return mRegistrationId;
+ }
+
+ void disconnectMixes() {
+ updateMixes(AudioSystem.DEVICE_STATE_UNAVAILABLE);
+ }
+
+ void updateMixes(int connectionState) {
+ for (AudioMix mix : mMixes) {
+ // TODO implement sending the mix attribute matching info to native audio policy
+ if (DEBUG_AP) {
+ Log.v(TAG, "AudioPolicyProxy connect mix state=" + connectionState
+ + " addr=" + mix.getRegistration()); }
+ AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_REMOTE_SUBMIX,
+ connectionState,
+ mix.getRegistration());
+ AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX,
+ connectionState,
+ mix.getRegistration());
}
}
};
private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
new HashMap<IBinder, AudioPolicyProxy>();
+ private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 2d8042cb367e..317cc212c463 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -207,6 +207,6 @@ interface IAudioService {
boolean isHdmiSystemAudioSupported();
- boolean registerAudioPolicy(in AudioPolicyConfig policyConfig, IBinder cb);
+ String registerAudioPolicy(in AudioPolicyConfig policyConfig, IBinder cb);
oneway void unregisterAudioPolicyAsync(in IBinder cb);
}
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index f7967f1f7d7b..bb5268261d78 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -24,13 +24,14 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
- * @hide CANDIDATE FOR PUBLIC API
+ * @hide
*/
public class AudioMix {
private AudioMixingRule mRule;
private AudioFormat mFormat;
private int mRouteFlags;
+ private String mRegistrationId;
/**
* All parameters are guaranteed valid through the Builder.
@@ -39,6 +40,7 @@ public class AudioMix {
mRule = rule;
mFormat = format;
mRouteFlags = routeFlags;
+ mRegistrationId = null;
}
/**
@@ -65,6 +67,15 @@ public class AudioMix {
return mRule;
}
+ void setRegistration(String regId) {
+ mRegistrationId = regId;
+ }
+
+ /** @hide */
+ public String getRegistration() {
+ return mRegistrationId;
+ }
+
/** @hide */
@IntDef(flag = true,
value = { ROUTE_FLAG_RENDER, ROUTE_FLAG_LOOP_BACK } )
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index ced78817a992..2e06a807624f 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -23,7 +23,7 @@ import java.util.Iterator;
/**
- * @hide CANDIDATE FOR PUBLIC API
+ * @hide
*
* Here's an example of creating a mixing rule for all media playback:
* <pre>
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 314eb887d1d1..255d828b4bfa 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -17,18 +17,26 @@
package android.media.audiopolicy;
import android.annotation.IntDef;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioManager;
+import android.media.AudioRecord;
+import android.media.AudioSystem;
+import android.media.AudioTrack;
+import android.media.MediaRecorder;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
+import android.util.Slog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
/**
- * @hide CANDIDATE FOR PUBLIC API
+ * @hide
* AudioPolicy provides access to the management of audio routing and audio focus.
*/
public class AudioPolicy {
@@ -49,11 +57,13 @@ public class AudioPolicy {
public static final int POLICY_STATUS_REGISTERED = 2;
private int mStatus;
- private AudioPolicyStatusListener mStatusListener = null;
+ private String mRegistrationId;
+ private AudioPolicyStatusListener mStatusListener;
private final IBinder mToken = new Binder();
/** @hide */
public IBinder token() { return mToken; }
+ private Context mContext;
private AudioPolicyConfig mConfig;
/** @hide */
@@ -62,13 +72,14 @@ public class AudioPolicy {
/**
* The parameter is guaranteed non-null through the Builder
*/
- private AudioPolicy(AudioPolicyConfig config) {
+ private AudioPolicy(AudioPolicyConfig config, Context context) {
mConfig = config;
if (mConfig.mMixes.isEmpty()) {
mStatus = POLICY_STATUS_INVALID;
} else {
mStatus = POLICY_STATUS_UNREGISTERED;
}
+ mContext = context;
}
/**
@@ -76,12 +87,15 @@ public class AudioPolicy {
*/
public static class Builder {
private ArrayList<AudioMix> mMixes;
+ private Context mContext;
/**
* Constructs a new Builder with no audio mixes.
+ * @param context the context for the policy
*/
- public Builder() {
+ public Builder(Context context) {
mMixes = new ArrayList<AudioMix>();
+ mContext = context;
}
/**
@@ -99,10 +113,115 @@ public class AudioPolicy {
}
public AudioPolicy build() {
- return new AudioPolicy(new AudioPolicyConfig(mMixes));
+ return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext);
}
}
+ /** @hide */
+ public void setRegistration(String regId) {
+ mRegistrationId = regId;
+ mConfig.setRegistration(regId);
+ }
+
+ private boolean policyReadyToUse() {
+ if (mContext == null) {
+ Log.e(TAG, "Cannot use AudioPolicy without context");
+ return false;
+ }
+ if (mRegistrationId == null) {
+ Log.e(TAG, "Cannot use unregistered AudioPolicy");
+ return false;
+ }
+ if (!(PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
+ Slog.w(TAG, "Cannot use AudioPolicy for pid " + Binder.getCallingPid() + " / uid "
+ + Binder.getCallingUid() + ", needs MODIFY_AUDIO_ROUTING");
+ return false;
+ }
+ return true;
+ }
+
+ private void checkMixReadyToUse(AudioMix mix, boolean forTrack)
+ throws IllegalArgumentException{
+ if (mix == null) {
+ String msg = forTrack ? "Invalid null AudioMix for AudioTrack creation"
+ : "Invalid null AudioMix for AudioRecord creation";
+ throw new IllegalArgumentException(msg);
+ }
+ if (!mConfig.mMixes.contains(mix)) {
+ throw new IllegalArgumentException("Invalid mix: not part of this policy");
+ }
+ if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) != AudioMix.ROUTE_FLAG_LOOP_BACK)
+ {
+ throw new IllegalArgumentException("Invalid AudioMix: not defined for loop back");
+ }
+ }
+
+ /**
+ * @hide
+ * Create an {@link AudioRecord} instance that is associated with the given {@link AudioMix}.
+ * Audio buffers recorded through the created instance will contain the mix of the audio
+ * streams that fed the given mixer.
+ * @param mix a non-null {@link AudioMix} instance whose routing flags was defined with
+ * {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, previously added to this policy.
+ * @return a new {@link AudioRecord} instance whose data format is the one defined in the
+ * {@link AudioMix}, or null if this policy was not successfully registered
+ * with {@link AudioManager#registerAudioPolicy(AudioPolicy)}.
+ * @throws IllegalArgumentException
+ */
+ public AudioRecord createAudioRecordSink(AudioMix mix) throws IllegalArgumentException {
+ if (!policyReadyToUse()) {
+ Log.e(TAG, "Cannot create AudioRecord sink for AudioMix");
+ return null;
+ }
+ checkMixReadyToUse(mix, false/*not for an AudioTrack*/);
+ // create the AudioRecord, configured for loop back, using the same format as the mix
+ AudioRecord ar = new AudioRecord(
+ new AudioAttributes.Builder()
+ .setInternalCapturePreset(MediaRecorder.AudioSource.REMOTE_SUBMIX)
+ .addTag(mix.getRegistration())
+ .build(),
+ mix.getFormat(),
+ AudioRecord.getMinBufferSize(mix.getFormat().getSampleRate(),
+ // using stereo for buffer size to avoid the current poor support for masks
+ AudioFormat.CHANNEL_IN_STEREO, mix.getFormat().getEncoding()),
+ AudioManager.AUDIO_SESSION_ID_GENERATE
+ );
+ return ar;
+ }
+
+ /**
+ * @hide
+ * Create an {@link AudioTrack} instance that is associated with the given {@link AudioMix}.
+ * Audio buffers played through the created instance will be sent to the given mix
+ * to be recorded through the recording APIs.
+ * @param mix a non-null {@link AudioMix} instance whose routing flags was defined with
+ * {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, previously added to this policy.
+ * @returna new {@link AudioTrack} instance whose data format is the one defined in the
+ * {@link AudioMix}, or null if this policy was not successfully registered
+ * with {@link AudioManager#registerAudioPolicy(AudioPolicy)}.
+ * @throws IllegalArgumentException
+ */
+ public AudioTrack createAudioTrackSource(AudioMix mix) throws IllegalArgumentException {
+ if (!policyReadyToUse()) {
+ Log.e(TAG, "Cannot create AudioTrack source for AudioMix");
+ return null;
+ }
+ checkMixReadyToUse(mix, true/*for an AudioTrack*/);
+ // create the AudioTrack, configured for loop back, using the same format as the mix
+ AudioTrack at = new AudioTrack(
+ new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_VIRTUAL_SOURCE)
+ .addTag(mix.getRegistration())
+ .build(),
+ mix.getFormat(),
+ AudioTrack.getMinBufferSize(mix.getFormat().getSampleRate(),
+ mix.getFormat().getChannelMask(), mix.getFormat().getEncoding()),
+ AudioTrack.MODE_STREAM,
+ AudioManager.AUDIO_SESSION_ID_GENERATE
+ );
+ return at;
+ }
public int getStatus() {
return mStatus;
@@ -118,10 +237,9 @@ public class AudioPolicy {
}
/** @hide */
- @Override
- public String toString () {
+ public String toLogFriendlyString() {
String textDump = new String("android.media.audiopolicy.AudioPolicy:\n");
- textDump += "config=" + mConfig.toString();
+ textDump += "config=" + mConfig.toLogFriendlyString();
return (textDump);
}
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 2fc6d58b2e61..a9a4175916ce 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -36,7 +36,13 @@ public class AudioPolicyConfig implements Parcelable {
private static final String TAG = "AudioPolicyConfig";
- ArrayList<AudioMix> mMixes;
+ protected ArrayList<AudioMix> mMixes;
+
+ protected String mRegistrationId = null;
+
+ protected AudioPolicyConfig(AudioPolicyConfig conf) {
+ mMixes = conf.mMixes;
+ }
AudioPolicyConfig(ArrayList<AudioMix> mixes) {
mMixes = mixes;
@@ -117,7 +123,6 @@ public class AudioPolicyConfig implements Parcelable {
}
}
- /** @hide */
public static final Parcelable.Creator<AudioPolicyConfig> CREATOR
= new Parcelable.Creator<AudioPolicyConfig>() {
/**
@@ -133,9 +138,7 @@ public class AudioPolicyConfig implements Parcelable {
}
};
- /** @hide */
- @Override
- public String toString () {
+ public String toLogFriendlyString () {
String textDump = new String("android.media.audiopolicy.AudioPolicyConfig:\n");
textDump += mMixes.size() + " AudioMix:\n";
for(AudioMix mix : mMixes) {
@@ -166,4 +169,13 @@ public class AudioPolicyConfig implements Parcelable {
}
return textDump;
}
+
+ public void setRegistration(String regId) {
+ mRegistrationId = regId;
+ int mixIndex = 0;
+ for (AudioMix mix : mMixes) {
+ mix.setRegistration(mRegistrationId + "mix:" + mixIndex++);
+ }
+ }
+
}
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index b8cdc4b4d60d..1ac80c14f458 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -166,6 +166,7 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
@Override
public void release() {
+ mTvInputSessionImpl.scheduleOverlayViewCleanup();
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_RELEASE));
}
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 691df77e9541..5b922664e15e 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -856,6 +856,9 @@ public final class TvContract {
/**
* The start time of this TV program, in milliseconds since the epoch.
* <p>
+ * The value should be equal to or larger than {@link #COLUMN_END_TIME_UTC_MILLIS} of the
+ * previous program in the same channel.
+ * </p><p>
* Type: INTEGER (long)
* </p>
*/
@@ -864,6 +867,9 @@ public final class TvContract {
/**
* The end time of this TV program, in milliseconds since the epoch.
* <p>
+ * The value should be equal to or less than {@link #COLUMN_START_TIME_UTC_MILLIS} of the
+ * next program in the same channel.
+ * </p><p>
* Type: INTEGER (long)
* </p>
*/
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 5d5ea027f72a..0ca5810f1002 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -25,10 +25,12 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.text.TextUtils;
@@ -44,10 +46,12 @@ import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.CaptioningManager;
+import android.widget.FrameLayout;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -241,16 +245,25 @@ public abstract class TvInputService extends Service {
* Base class for derived classes to implement to provide a TV input session.
*/
public abstract static class Session implements KeyEvent.Callback {
+ private static final int DETACH_OVERLAY_VIEW_TIMEOUT = 5000;
private final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState();
private final WindowManager mWindowManager;
final Handler mHandler;
private WindowManager.LayoutParams mWindowParams;
private Surface mSurface;
+ private Context mContext;
+ private FrameLayout mOverlayViewContainer;
private View mOverlayView;
+ private OverlayViewCleanUpTask mOverlayViewCleanUpTask;
private boolean mOverlayViewEnabled;
private IBinder mWindowToken;
private Rect mOverlayFrame;
+
+ private Object mLock = new Object();
+ // @GuardedBy("mLock")
private ITvInputSessionCallback mSessionCallback;
+ // @GuardedBy("mLock")
+ private List<Runnable> mPendingActions = new ArrayList<>();
/**
* Creates a new Session.
@@ -258,6 +271,7 @@ public abstract class TvInputService extends Service {
* @param context The context of the application
*/
public Session(Context context) {
+ mContext = context;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mHandler = new Handler(context.getMainLooper());
}
@@ -295,11 +309,12 @@ public abstract class TvInputService extends Service {
* @param eventArgs Optional arguments of the event.
* @hide
*/
+ @SystemApi
public void notifySessionEvent(final String eventType, final Bundle eventArgs) {
if (eventType == null) {
throw new IllegalArgumentException("eventType should not be null.");
}
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -318,7 +333,7 @@ public abstract class TvInputService extends Service {
* @param channelUri The URI of a channel.
*/
public void notifyChannelRetuned(final Uri channelUri) {
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -355,7 +370,7 @@ public abstract class TvInputService extends Service {
trackIdSet.clear();
// TODO: Validate the track list.
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -383,7 +398,7 @@ public abstract class TvInputService extends Service {
* @see #onSelectTrack
*/
public void notifyTrackSelected(final int type, final String trackId) {
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -404,7 +419,7 @@ public abstract class TvInputService extends Service {
* @see #notifyVideoUnavailable
*/
public void notifyVideoAvailable() {
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -436,7 +451,7 @@ public abstract class TvInputService extends Service {
|| reason > TvInputManager.VIDEO_UNAVAILABLE_REASON_END) {
throw new IllegalArgumentException("Unknown reason: " + reason);
}
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -475,7 +490,7 @@ public abstract class TvInputService extends Service {
* @see TvInputManager
*/
public void notifyContentAllowed() {
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -515,7 +530,7 @@ public abstract class TvInputService extends Service {
* @see TvInputManager
*/
public void notifyContentBlocked(final TvContentRating rating) {
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -544,7 +559,7 @@ public abstract class TvInputService extends Service {
if (left > right || top > bottm) {
throw new IllegalArgumentException("Invalid parameter");
}
- runOnMainThread(new Runnable() {
+ executeOrPostRunnable(new Runnable() {
@Override
public void run() {
try {
@@ -846,12 +861,18 @@ public abstract class TvInputService extends Service {
* session.
*/
void release() {
- removeOverlayView(true);
onRelease();
if (mSurface != null) {
mSurface.release();
mSurface = null;
}
+ synchronized(mLock) {
+ mSessionCallback = null;
+ mPendingActions.clear();
+ }
+ // Removes the overlay view lastly so that any hanging on the main thread can be handled
+ // in {@link #scheduleOverlayViewCleanup}.
+ removeOverlayView(true);
}
/**
@@ -936,9 +957,8 @@ public abstract class TvInputService extends Service {
* @param frame A position of the overlay view.
*/
void createOverlayView(IBinder windowToken, Rect frame) {
- if (mOverlayView != null) {
- mWindowManager.removeView(mOverlayView);
- mOverlayView = null;
+ if (mOverlayViewContainer != null) {
+ removeOverlayView(false);
}
if (DEBUG) Log.d(TAG, "create overlay view(" + frame + ")");
mWindowToken = windowToken;
@@ -951,6 +971,15 @@ public abstract class TvInputService extends Service {
if (mOverlayView == null) {
return;
}
+ if (mOverlayViewCleanUpTask != null) {
+ mOverlayViewCleanUpTask.cancel(true);
+ mOverlayViewCleanUpTask = null;
+ }
+ // Creates a container view to check hanging on the overlay view detaching.
+ // Adding/removing the overlay view to/from the container make the view attach/detach
+ // logic run on the main thread.
+ mOverlayViewContainer = new FrameLayout(mContext);
+ mOverlayViewContainer.addView(mOverlayView);
// TvView's window type is TYPE_APPLICATION_MEDIA and we want to create
// an overlay window above the media window but below the application window.
int type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
@@ -967,7 +996,7 @@ public abstract class TvInputService extends Service {
WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
mWindowParams.gravity = Gravity.START | Gravity.TOP;
mWindowParams.token = windowToken;
- mWindowManager.addView(mOverlayView, mWindowParams);
+ mWindowManager.addView(mOverlayViewContainer, mWindowParams);
}
/**
@@ -984,33 +1013,51 @@ public abstract class TvInputService extends Service {
onOverlayViewSizeChanged(frame.right - frame.left, frame.bottom - frame.top);
}
mOverlayFrame = frame;
- if (!mOverlayViewEnabled || mOverlayView == null) {
+ if (!mOverlayViewEnabled || mOverlayViewContainer == null) {
return;
}
mWindowParams.x = frame.left;
mWindowParams.y = frame.top;
mWindowParams.width = frame.right - frame.left;
mWindowParams.height = frame.bottom - frame.top;
- mWindowManager.updateViewLayout(mOverlayView, mWindowParams);
+ mWindowManager.updateViewLayout(mOverlayViewContainer, mWindowParams);
}
/**
* Removes the current overlay view.
*/
void removeOverlayView(boolean clearWindowToken) {
- if (DEBUG) Log.d(TAG, "removeOverlayView(" + mOverlayView + ")");
+ if (DEBUG) Log.d(TAG, "removeOverlayView(" + mOverlayViewContainer + ")");
if (clearWindowToken) {
mWindowToken = null;
mOverlayFrame = null;
}
- if (mOverlayView != null) {
- mWindowManager.removeView(mOverlayView);
+ if (mOverlayViewContainer != null) {
+ // Removes the overlay view from the view hierarchy in advance so that it can be
+ // cleaned up in the {@link OverlayViewCleanUpTask} if the remove process is
+ // hanging.
+ mOverlayViewContainer.removeView(mOverlayView);
mOverlayView = null;
+ mWindowManager.removeView(mOverlayViewContainer);
+ mOverlayViewContainer = null;
mWindowParams = null;
}
}
/**
+ * Schedules a task which checks whether the overlay view is detached and kills the process
+ * if it is not. Note that this method is expected to be called in a non-main thread.
+ */
+ void scheduleOverlayViewCleanup() {
+ View overlayViewParent = mOverlayViewContainer;
+ if (overlayViewParent != null) {
+ mOverlayViewCleanUpTask = new OverlayViewCleanUpTask();
+ mOverlayViewCleanUpTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
+ overlayViewParent);
+ }
+ }
+
+ /**
* Takes care of dispatching incoming input events and tells whether the event was handled.
*/
int dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
@@ -1039,37 +1086,70 @@ public abstract class TvInputService extends Service {
}
}
}
- if (mOverlayView == null || !mOverlayView.isAttachedToWindow()) {
+ if (mOverlayViewContainer == null || !mOverlayViewContainer.isAttachedToWindow()) {
return TvInputManager.Session.DISPATCH_NOT_HANDLED;
}
- if (!mOverlayView.hasWindowFocus()) {
- mOverlayView.getViewRootImpl().windowFocusChanged(true, true);
+ if (!mOverlayViewContainer.hasWindowFocus()) {
+ mOverlayViewContainer.getViewRootImpl().windowFocusChanged(true, true);
}
- if (isNavigationKey && mOverlayView.hasFocusable()) {
+ if (isNavigationKey && mOverlayViewContainer.hasFocusable()) {
// If mOverlayView has focusable views, navigation key events should be always
// handled. If not, it can make the application UI navigation messed up.
// For example, in the case that the left-most view is focused, a left key event
// will not be handled in ViewRootImpl. Then, the left key event will be handled in
// the application during the UI navigation of the TV input.
- mOverlayView.getViewRootImpl().dispatchInputEvent(event);
+ mOverlayViewContainer.getViewRootImpl().dispatchInputEvent(event);
return TvInputManager.Session.DISPATCH_HANDLED;
} else {
- mOverlayView.getViewRootImpl().dispatchInputEvent(event, receiver);
+ mOverlayViewContainer.getViewRootImpl().dispatchInputEvent(event, receiver);
return TvInputManager.Session.DISPATCH_IN_PROGRESS;
}
}
- private void setSessionCallback(ITvInputSessionCallback callback) {
- mSessionCallback = callback;
+ private void initialize(ITvInputSessionCallback callback) {
+ synchronized(mLock) {
+ mSessionCallback = callback;
+ for (Runnable runnable : mPendingActions) {
+ runnable.run();
+ }
+ mPendingActions.clear();
+ }
}
- private final void runOnMainThread(Runnable action) {
- if (mHandler.getLooper().isCurrentThread() && mSessionCallback != null) {
- action.run();
- } else {
- // Posts the runnable if this is not called from the main thread or the session
- // is not initialized yet.
- mHandler.post(action);
+ private final void executeOrPostRunnable(Runnable action) {
+ synchronized(mLock) {
+ if (mSessionCallback == null) {
+ // The session is not initialized yet.
+ mPendingActions.add(action);
+ } else {
+ if (mHandler.getLooper().isCurrentThread()) {
+ action.run();
+ } else {
+ // Posts the runnable if this is not called from the main thread
+ mHandler.post(action);
+ }
+ }
+ }
+ }
+
+ private final class OverlayViewCleanUpTask extends AsyncTask<View, Void, Void> {
+ @Override
+ protected Void doInBackground(View... views) {
+ View overlayViewParent = views[0];
+ try {
+ Thread.sleep(DETACH_OVERLAY_VIEW_TIMEOUT);
+ } catch (InterruptedException e) {
+ return null;
+ }
+ if (isCancelled()) {
+ return null;
+ }
+ if (overlayViewParent.isAttachedToWindow()) {
+ Log.e(TAG, "Time out on releasing overlay view. Killing "
+ + overlayViewParent.getContext().getPackageName());
+ Process.killProcess(Process.myPid());
+ }
+ return null;
}
}
}
@@ -1125,13 +1205,15 @@ public abstract class TvInputService extends Service {
mHardwareSession = session;
SomeArgs args = SomeArgs.obtain();
if (session != null) {
- args.arg1 = mProxySession;
- args.arg2 = mProxySessionCallback;
- args.arg3 = session.getToken();
+ args.arg1 = HardwareSession.this;
+ args.arg2 = mProxySession;
+ args.arg3 = mProxySessionCallback;
+ args.arg4 = session.getToken();
} else {
args.arg1 = null;
- args.arg2 = mProxySessionCallback;
- args.arg3 = null;
+ args.arg2 = null;
+ args.arg3 = mProxySessionCallback;
+ args.arg4 = null;
onRelease();
}
mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_SESSION_CREATED, args)
@@ -1269,7 +1351,6 @@ public abstract class TvInputService extends Service {
}
return;
}
- sessionImpl.setSessionCallback(cb);
ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this,
sessionImpl, channel);
if (sessionImpl instanceof HardwareSession) {
@@ -1300,9 +1381,10 @@ public abstract class TvInputService extends Service {
proxySession.mHardwareSessionCallback, mServiceHandler);
} else {
SomeArgs someArgs = SomeArgs.obtain();
- someArgs.arg1 = stub;
- someArgs.arg2 = cb;
- someArgs.arg3 = null;
+ someArgs.arg1 = sessionImpl;
+ someArgs.arg2 = stub;
+ someArgs.arg3 = cb;
+ someArgs.arg4 = null;
mServiceHandler.obtainMessage(ServiceHandler.DO_NOTIFY_SESSION_CREATED,
someArgs).sendToTarget();
}
@@ -1310,14 +1392,18 @@ public abstract class TvInputService extends Service {
}
case DO_NOTIFY_SESSION_CREATED: {
SomeArgs args = (SomeArgs) msg.obj;
- ITvInputSession stub = (ITvInputSession) args.arg1;
- ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg2;
- IBinder hardwareSessionToken = (IBinder) args.arg3;
+ Session sessionImpl = (Session) args.arg1;
+ ITvInputSession stub = (ITvInputSession) args.arg2;
+ ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg3;
+ IBinder hardwareSessionToken = (IBinder) args.arg4;
try {
cb.onSessionCreated(stub, hardwareSessionToken);
} catch (RemoteException e) {
Log.e(TAG, "error in onSessionCreated");
}
+ if (sessionImpl != null) {
+ sessionImpl.initialize(cb);
+ }
args.recycle();
return;
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/OpenDocumentCallback.java b/packages/PrintSpooler/src/com/android/printspooler/model/OpenDocumentCallback.java
new file mode 100644
index 000000000000..50f424ad4842
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/OpenDocumentCallback.java
@@ -0,0 +1,37 @@
+/*
+ * 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.printspooler.model;
+
+/**
+ * Callbacks interface for opening a file.
+ */
+public interface OpenDocumentCallback {
+ public static final int ERROR_MALFORMED_PDF_FILE = -1;
+ public static final int ERROR_SECURE_PDF_FILE = -2;
+
+ /**
+ * Called after the file is opened.
+ */
+ public void onSuccess();
+
+ /**
+ * Called after opening the file failed.
+ *
+ * @param error The error.
+ */
+ public void onFailure(int error);
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index a54334aeba52..882b364daa51 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -78,13 +78,8 @@ public final class PageContentRepository {
public void onPageContentAvailable(BitmapDrawable content);
}
- public interface OnMalformedPdfFileListener {
- public void onMalformedPdfFile();
- }
-
- public PageContentRepository(Context context,
- OnMalformedPdfFileListener malformedPdfFileListener) {
- mRenderer = new AsyncRenderer(context, malformedPdfFileListener);
+ public PageContentRepository(Context context) {
+ mRenderer = new AsyncRenderer(context);
mState = STATE_CLOSED;
if (DEBUG) {
Log.i(LOG_TAG, "STATE_CLOSED");
@@ -92,7 +87,7 @@ public final class PageContentRepository {
mCloseGuard.open("destroy");
}
- public void open(ParcelFileDescriptor source, final Runnable callback) {
+ public void open(ParcelFileDescriptor source, final OpenDocumentCallback callback) {
throwIfNotClosed();
mState = STATE_OPENED;
if (DEBUG) {
@@ -412,8 +407,6 @@ public final class PageContentRepository {
private final ArrayMap<Integer, RenderPageTask> mPageToRenderTaskMap = new ArrayMap<>();
- private final OnMalformedPdfFileListener mOnMalformedPdfFileListener;
-
private int mPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
@GuardedBy("mLock")
@@ -422,9 +415,8 @@ public final class PageContentRepository {
private boolean mBoundToService;
private boolean mDestroyed;
- public AsyncRenderer(Context context, OnMalformedPdfFileListener malformedPdfFileListener) {
+ public AsyncRenderer(Context context) {
mContext = context;
- mOnMalformedPdfFileListener = malformedPdfFileListener;
ActivityManager activityManager = (ActivityManager)
mContext.getSystemService(Context.ACTIVITY_SERVICE);
@@ -447,7 +439,7 @@ public final class PageContentRepository {
}
}
- public void open(final ParcelFileDescriptor source, final Runnable callback) {
+ public void open(final ParcelFileDescriptor source, final OpenDocumentCallback callback) {
// Opening a new document invalidates the cache as it has pages
// from the last document. We keep the cache even when the document
// is closed to show pages while the other side is writing the new
@@ -463,7 +455,8 @@ public final class PageContentRepository {
}
Intent intent = new Intent(PdfManipulationService.ACTION_GET_RENDERER);
intent.setClass(mContext, PdfManipulationService.class);
- intent.setData(Uri.fromParts("fake-scheme", String.valueOf(hashCode()), null));
+ intent.setData(Uri.fromParts("fake-scheme", String.valueOf(
+ AsyncRenderer.this.hashCode()), null));
mContext.bindService(intent, AsyncRenderer.this, Context.BIND_AUTO_CREATE);
mBoundToService = true;
}
@@ -482,7 +475,7 @@ public final class PageContentRepository {
return mRenderer.openDocument(source);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Cannot open PDF document");
- return PdfManipulationService.MALFORMED_PDF_FILE_ERROR;
+ return PdfManipulationService.ERROR_MALFORMED_PDF_FILE;
} finally {
// Close the fd as we passed it to another process
// which took ownership.
@@ -493,14 +486,25 @@ public final class PageContentRepository {
@Override
public void onPostExecute(Integer pageCount) {
- if (pageCount == PdfManipulationService.MALFORMED_PDF_FILE_ERROR) {
- mOnMalformedPdfFileListener.onMalformedPdfFile();
- mPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
- } else {
- mPageCount = pageCount;
- }
- if (callback != null) {
- callback.run();
+ switch (pageCount) {
+ case PdfManipulationService.ERROR_MALFORMED_PDF_FILE: {
+ mPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
+ if (callback != null) {
+ callback.onFailure(OpenDocumentCallback.ERROR_MALFORMED_PDF_FILE);
+ }
+ } break;
+ case PdfManipulationService.ERROR_SECURE_PDF_FILE: {
+ mPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
+ if (callback != null) {
+ callback.onFailure(OpenDocumentCallback.ERROR_SECURE_PDF_FILE);
+ }
+ } break;
+ default: {
+ mPageCount = pageCount;
+ if (callback != null) {
+ callback.onSuccess();
+ }
+ } break;
}
}
}.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index f6ace41d6e9d..1b6e9ce2db37 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -304,6 +304,18 @@ public final class RemotePrintDocument {
disconnectFromRemoteDocument();
}
+ public void kill(String reason) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "[CALLED] kill()");
+ }
+
+ try {
+ mPrintDocumentAdapter.kill(reason);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error calling kill()", re);
+ }
+ }
+
public boolean isUpdating() {
return mState == STATE_UPDATING || mState == STATE_CANCELING;
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl
index b450ccb2e777..01cabe127bf2 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl
@@ -18,6 +18,7 @@ package com.android.printspooler.renderer;
import android.os.ParcelFileDescriptor;
import android.print.PageRange;
+import android.print.PrintAttributes;
/**
* Interface for communication with a remote pdf editor.
@@ -25,6 +26,7 @@ import android.print.PageRange;
interface IPdfEditor {
int openDocument(in ParcelFileDescriptor source);
void removePages(in PageRange[] pages);
+ void applyPrintAttributes(in PrintAttributes attributes);
void write(in ParcelFileDescriptor destination);
void closeDocument();
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
index 00e505149d1d..7db207498775 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
@@ -47,7 +47,9 @@ public final class PdfManipulationService extends Service {
public static final String ACTION_GET_EDITOR =
"com.android.printspooler.renderer.ACTION_GET_EDITOR";
- public static final int MALFORMED_PDF_FILE_ERROR = -2;
+ public static final int ERROR_MALFORMED_PDF_FILE = -2;
+
+ public static final int ERROR_SECURE_PDF_FILE = -3;
private static final String LOG_TAG = "PdfManipulationService";
private static final boolean DEBUG = false;
@@ -87,10 +89,14 @@ public final class PdfManipulationService extends Service {
}
mRenderer = new PdfRenderer(source);
return mRenderer.getPageCount();
- } catch (IOException|IllegalStateException e) {
+ } catch (IOException | IllegalStateException e) {
+ IoUtils.closeQuietly(source);
+ Log.e(LOG_TAG, "Cannot open file", e);
+ return ERROR_MALFORMED_PDF_FILE;
+ } catch (SecurityException e) {
IoUtils.closeQuietly(source);
Log.e(LOG_TAG, "Cannot open file", e);
- return MALFORMED_PDF_FILE_ERROR;
+ return ERROR_SECURE_PDF_FILE;
}
}
}
@@ -217,7 +223,7 @@ public final class PdfManipulationService extends Service {
}
mEditor = new PdfEditor(source);
return mEditor.getPageCount();
- } catch (IOException|IllegalStateException e) {
+ } catch (IOException | IllegalStateException e) {
IoUtils.closeQuietly(source);
Log.e(LOG_TAG, "Cannot open file", e);
throw new RemoteException(e.toString());
@@ -246,6 +252,111 @@ public final class PdfManipulationService extends Service {
}
@Override
+ public void applyPrintAttributes(PrintAttributes attributes) {
+ synchronized (mLock) {
+ throwIfNotOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "applyPrintAttributes()");
+ }
+
+ Rect mediaBox = new Rect();
+ Rect cropBox = new Rect();
+ Matrix transform = new Matrix();
+
+ final boolean contentPortrait = attributes.getMediaSize().isPortrait();
+
+ final boolean layoutDirectionRtl = getResources().getConfiguration()
+ .getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+
+ // We do not want to rotate the media box, so take into account orientation.
+ final int dstWidthPts = contentPortrait
+ ? pointsFromMils(attributes.getMediaSize().getWidthMils())
+ : pointsFromMils(attributes.getMediaSize().getHeightMils());
+ final int dstHeightPts = contentPortrait
+ ? pointsFromMils(attributes.getMediaSize().getHeightMils())
+ : pointsFromMils(attributes.getMediaSize().getWidthMils());
+
+ final boolean scaleForPrinting = mEditor.shouldScaleForPrinting();
+
+ final int pageCount = mEditor.getPageCount();
+ for (int i = 0; i < pageCount; i++) {
+ if (!mEditor.getPageMediaBox(i, mediaBox)) {
+ Log.e(LOG_TAG, "Malformed PDF file");
+ return;
+ }
+
+ final int srcWidthPts = mediaBox.width();
+ final int srcHeightPts = mediaBox.height();
+
+ // Update the media box with the desired size.
+ mediaBox.right = dstWidthPts;
+ mediaBox.bottom = dstHeightPts;
+ mEditor.setPageMediaBox(i, mediaBox);
+
+ // Make sure content is top-left after media box resize.
+ transform.setTranslate(0, srcHeightPts - dstHeightPts);
+
+ // Rotate the content if in landscape.
+ if (!contentPortrait) {
+ transform.postRotate(270);
+ transform.postTranslate(0, dstHeightPts);
+ }
+
+ // Scale the content if document allows it.
+ final float scale;
+ if (scaleForPrinting) {
+ if (contentPortrait) {
+ scale = Math.min((float) dstWidthPts / srcWidthPts,
+ (float) dstHeightPts / srcHeightPts);
+ transform.postScale(scale, scale);
+ } else {
+ scale = Math.min((float) dstWidthPts / srcHeightPts,
+ (float) dstHeightPts / srcWidthPts);
+ transform.postScale(scale, scale, mediaBox.left, mediaBox.bottom);
+ }
+ } else {
+ scale = 1.0f;
+ }
+
+ // Update the crop box relatively to the media box change, if needed.
+ if (mEditor.getPageCropBox(i, cropBox)) {
+ cropBox.left = (int) (cropBox.left * scale + 0.5f);
+ cropBox.top = (int) (cropBox.top * scale + 0.5f);
+ cropBox.right = (int) (cropBox.right * scale + 0.5f);
+ cropBox.bottom = (int) (cropBox.bottom * scale + 0.5f);
+ cropBox.intersect(mediaBox);
+ mEditor.setPageCropBox(i, cropBox);
+ }
+
+ // If in RTL mode put the content in the logical top-right corner.
+ if (layoutDirectionRtl) {
+ final float dx = contentPortrait
+ ? dstWidthPts - (int) (srcWidthPts * scale + 0.5f) : 0;
+ final float dy = contentPortrait
+ ? 0 : - (dstHeightPts - (int) (srcWidthPts * scale + 0.5f));
+ transform.postTranslate(dx, dy);
+ }
+
+ // Adjust the physical margins if needed.
+ Margins minMargins = attributes.getMinMargins();
+ final int paddingLeftPts = pointsFromMils(minMargins.getLeftMils());
+ final int paddingTopPts = pointsFromMils(minMargins.getTopMils());
+ final int paddingRightPts = pointsFromMils(minMargins.getRightMils());
+ final int paddingBottomPts = pointsFromMils(minMargins.getBottomMils());
+
+ Rect clip = new Rect(mediaBox);
+ clip.left += paddingLeftPts;
+ clip.top += paddingTopPts;
+ clip.right -= paddingRightPts;
+ clip.bottom -= paddingBottomPts;
+
+ // Apply the accumulated transforms.
+ mEditor.setTransformAndClip(i, transform, clip);
+ }
+ }
+ }
+
+ @Override
public void write(ParcelFileDescriptor destination) throws RemoteException {
synchronized (mLock) {
try {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index aa7956859f75..0d2e7361cfdd 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -37,6 +37,7 @@ import android.view.ViewGroup.LayoutParams;
import android.view.View.MeasureSpec;
import android.widget.TextView;
import com.android.printspooler.R;
+import com.android.printspooler.model.OpenDocumentCallback;
import com.android.printspooler.model.PageContentRepository;
import com.android.printspooler.model.PageContentRepository.PageContentProvider;
import com.android.printspooler.util.PageRangeUtils;
@@ -51,8 +52,7 @@ import java.util.List;
/**
* This class represents the adapter for the pages in the print preview list.
*/
-public final class PageAdapter extends Adapter implements
- PageContentRepository.OnMalformedPdfFileListener {
+public final class PageAdapter extends Adapter {
private static final String LOG_TAG = "PageAdapter";
private static final int MAX_PREVIEW_PAGES_BATCH = 50;
@@ -113,6 +113,7 @@ public final class PageAdapter extends Adapter implements
public interface ContentCallbacks {
public void onRequestContentUpdate();
public void onMalformedPdfFile();
+ public void onSecurePdfFile();
}
public interface PreviewArea {
@@ -127,7 +128,7 @@ public final class PageAdapter extends Adapter implements
mCallbacks = callbacks;
mLayoutInflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
- mPageContentRepository = new PageContentRepository(context, this);
+ mPageContentRepository = new PageContentRepository(context);
mPreviewPageMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.preview_page_margin);
@@ -156,11 +157,6 @@ public final class PageAdapter extends Adapter implements
}
}
- @Override
- public void onMalformedPdfFile() {
- mCallbacks.onMalformedPdfFile();
- }
-
public void onOrientationChanged() {
mColumnCount = mContext.getResources().getInteger(
R.integer.preview_page_per_row_count);
@@ -181,12 +177,25 @@ public final class PageAdapter extends Adapter implements
if (DEBUG) {
Log.i(LOG_TAG, "STATE_OPENED");
}
- mPageContentRepository.open(source, new Runnable() {
+ mPageContentRepository.open(source, new OpenDocumentCallback() {
@Override
- public void run() {
+ public void onSuccess() {
notifyDataSetChanged();
callback.run();
}
+
+ @Override
+ public void onFailure(int error) {
+ switch (error) {
+ case OpenDocumentCallback.ERROR_MALFORMED_PDF_FILE: {
+ mCallbacks.onMalformedPdfFile();
+ } break;
+
+ case OpenDocumentCallback.ERROR_SECURE_PDF_FILE: {
+ mCallbacks.onSecurePdfFile();
+ } break;
+ }
+ }
});
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 15ea9a73c665..b76a9cd8b415 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -378,7 +378,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
return true;
}
- if (mState == STATE_PRINT_CANCELED ||mState == STATE_PRINT_CONFIRMED
+ if (mState == STATE_PRINT_CANCELED || mState == STATE_PRINT_CONFIRMED
|| mState == STATE_PRINT_COMPLETED) {
return true;
}
@@ -405,12 +405,23 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
@Override
public void onMalformedPdfFile() {
+ onPrintDocumentError("Cannot print a malformed PDF file");
+ }
+
+ @Override
+ public void onSecurePdfFile() {
+ onPrintDocumentError("Cannot print a password protected PDF file");
+ }
+
+ private void onPrintDocumentError(String message) {
mProgressMessageController.cancel();
ensureErrorUiShown(null, PrintErrorFragment.ACTION_RETRY);
setState(STATE_UPDATE_FAILED);
updateOptionsUi();
+
+ mPrintedDocument.kill(message);
}
@Override
@@ -592,7 +603,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
mDestinationSpinner.post(new Runnable() {
@Override
public void run() {
- shredPagesAndFinish(uri);
+ transformDocumentAndFinish(uri);
}
});
} else if (resultCode == RESULT_CANCELED) {
@@ -922,7 +933,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
startCreateDocumentActivity();
} else {
- shredPagesAndFinish(null);
+ transformDocumentAndFinish(null);
}
}
@@ -1597,8 +1608,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
return true;
}
- private void shredPagesAndFinish(final Uri writeToUri) {
- new PageShredder(this, mPrintJob, mFileProvider, new Runnable() {
+ private void transformDocumentAndFinish(final Uri writeToUri) {
+ // If saving to PDF, apply the attibutes as we are acting as a print service.
+ PrintAttributes attributes = mDestinationSpinnerAdapter.getPdfPrinter() == mCurrentPrinter
+ ? mPrintJob.getAttributes() : null;
+ new DocumentTransformer(this, mPrintJob, mFileProvider, attributes, new Runnable() {
@Override
public void run() {
if (writeToUri != null) {
@@ -1606,7 +1620,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
}
doFinish();
}
- }).shred();
+ }).transform();
}
private void doFinish() {
@@ -2329,7 +2343,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
}
}
- private static final class PageShredder implements ServiceConnection {
+ private static final class DocumentTransformer implements ServiceConnection {
private static final String TEMP_FILE_PREFIX = "print_job";
private static final String TEMP_FILE_EXTENSION = ".pdf";
@@ -2341,20 +2355,24 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
private final PageRange[] mPagesToShred;
+ private final PrintAttributes mAttributesToApply;
+
private final Runnable mCallback;
- public PageShredder(Context context, PrintJobInfo printJob,
- MutexFileProvider fileProvider, Runnable callback) {
+ public DocumentTransformer(Context context, PrintJobInfo printJob,
+ MutexFileProvider fileProvider, PrintAttributes attributes,
+ Runnable callback) {
mContext = context;
mPrintJob = printJob;
mFileProvider = fileProvider;
mCallback = callback;
mPagesToShred = computePagesToShred(mPrintJob);
+ mAttributesToApply = attributes;
}
- public void shred() {
+ public void transform() {
// If we have only the pages we want, done.
- if (mPagesToShred.length <= 0) {
+ if (mPagesToShred.length <= 0 && mAttributesToApply == null) {
mCallback.run();
return;
}
@@ -2376,14 +2394,14 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
// final and this code is the last one to touch
// them as shredding is the very last step, so the
// UI is not interactive at this point.
- shredPages(editor);
+ doTransform(editor);
updatePrintJob();
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
- mContext.unbindService(PageShredder.this);
+ mContext.unbindService(DocumentTransformer.this);
mCallback.run();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
@@ -2394,7 +2412,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
/* do nothing */
}
- private void shredPages(IPdfEditor editor) {
+ private void doTransform(IPdfEditor editor) {
File tempFile = null;
ParcelFileDescriptor src = null;
ParcelFileDescriptor dst = null;
@@ -2413,6 +2431,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
// Drop the pages.
editor.removePages(mPagesToShred);
+ // Apply print attributes if needed.
+ if (mAttributesToApply != null) {
+ editor.applyPrintAttributes(mAttributesToApply);
+ }
+
// Write the modified PDF to a temp file.
tempFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_EXTENSION,
mContext.getCacheDir());
diff --git a/packages/SystemUI/res/drawable/ic_dismiss_all.xml b/packages/SystemUI/res/drawable/ic_dismiss_all.xml
index 8e5e572f162b..c32e5b1138fd 100644
--- a/packages/SystemUI/res/drawable/ic_dismiss_all.xml
+++ b/packages/SystemUI/res/drawable/ic_dismiss_all.xml
@@ -16,6 +16,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:autoMirrored="true"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
index adbda4ae968d..7fb423e5fc84 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
@@ -21,14 +21,14 @@ Copyright (C) 2014 The Android Open Source Project
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+ android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/>
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M11.300000,12.700000l-9.300000,9.300000 9.300000,0.000000z"/>
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M17.7,8.0l4.299999,0.0 0.0,-6.0 -20.0,20.0 15.700001,0.0z"/>
<path
- android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
- android:fillColor="#4DFFFFFF"/>
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
index a71e33aa2eb5..8baa4ebd0c26 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_full_1.xml
@@ -21,8 +21,8 @@ Copyright (C) 2014 The Android Open Source Project
android:viewportHeight="24.0">
<path
android:fillColor="#4DFFFFFF"
- android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
+ android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/>
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M11.300000,12.700000l-9.300000,9.300000 9.300000,0.000000z"/>
+ android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
index a53e946236cf..d1124eee9be9 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
@@ -21,14 +21,14 @@ Copyright (C) 2014 The Android Open Source Project
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+ android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/>
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M11.300000,12.700000l-9.300000,9.300000 9.300000,0.000000z"/>
+ android:fillColor="#4DFFFFFF"
+ android:pathData="M17.7,8.0l4.299999,0.0 0.0,-6.0 -20.0,20.0 15.700001,0.0z"/>
<path
- android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
- android:fillColor="#4DFFFFFF"/>
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml
index 6bc55cd2324c..29eda9451dcd 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_1_fully.xml
@@ -21,8 +21,8 @@ Copyright (C) 2014 The Android Open Source Project
android:viewportHeight="24.0">
<path
android:fillColor="#4DFFFFFF"
- android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
+ android:pathData="M2.0,22.0l20.0,0.0 0.0,-20.0z"/>
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M11.300000,12.700000l-9.300000,9.300000 9.300000,0.000000z"/>
+ android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
</vector>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 16027d96f0c0..2e38b2026112 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -43,7 +43,7 @@
<!-- navigation controls -->
<View
- android:layout_width="40dp"
+ android:layout_width="@dimen/navigation_side_padding"
android:layout_height="match_parent"
android:layout_weight="0"
android:visibility="invisible"
@@ -58,7 +58,7 @@
android:contentDescription="@string/accessibility_back"
/>
<View
- android:layout_width="match_parent"
+ android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible"
@@ -70,10 +70,11 @@
systemui:keyCode="3"
systemui:keyRepeat="false"
android:layout_weight="0"
+ android:scaleType="center"
android:contentDescription="@string/accessibility_home"
/>
<View
- android:layout_width="match_parent"
+ android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible"
@@ -83,10 +84,11 @@
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_recent"
android:layout_weight="0"
+ android:scaleType="center"
android:contentDescription="@string/accessibility_recent"
/>
<FrameLayout
- android:layout_width="@dimen/navigation_extra_key_width"
+ android:layout_width="@dimen/navigation_side_padding"
android:layout_height="match_parent"
android:layout_weight="0" >
<com.android.systemui.statusbar.policy.KeyButtonView
@@ -96,6 +98,7 @@
android:contentDescription="@string/accessibility_menu"
android:src="@drawable/ic_sysbar_menu"
android:visibility="invisible"
+ android:layout_gravity="end"
systemui:keyCode="82" />
<com.android.systemui.statusbar.policy.KeyButtonView
@@ -105,7 +108,8 @@
android:contentDescription="@string/accessibility_ime_switch_button"
android:scaleType="centerInside"
android:src="@drawable/ic_ime_switcher_default"
- android:visibility="invisible" />
+ android:visibility="invisible"
+ android:layout_gravity="end" />
</FrameLayout>
</LinearLayout>
@@ -119,9 +123,9 @@
android:visibility="gone"
>
<ImageView
- android:layout_width="80dp"
+ android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
- android:layout_marginStart="40dp"
+ android:layout_marginStart="@dimen/navigation_side_padding"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
android:layout_weight="0"
@@ -133,7 +137,7 @@
android:visibility="invisible"
/>
<ImageView
- android:layout_width="80dp"
+ android:layout_width="@dimen/navigation_key_width"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
@@ -146,8 +150,8 @@
android:visibility="invisible"
/>
<ImageView
- android:layout_width="80dp"
- android:layout_marginEnd="40dp"
+ android:layout_width="@dimen/navigation_key_width"
+ android:layout_marginEnd="@dimen/navigation_side_padding"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
@@ -189,14 +193,15 @@
<FrameLayout
android:layout_weight="0"
android:layout_width="match_parent"
- android:layout_height="40dp" >
+ android:layout_height="@dimen/navigation_side_padding" >
<com.android.systemui.statusbar.policy.KeyButtonView
android:id="@+id/ime_switcher"
android:layout_width="match_parent"
- android:layout_height="40dp"
+ android:layout_height="@dimen/navigation_extra_key_width"
android:contentDescription="@string/accessibility_ime_switch_button"
android:scaleType="centerInside"
android:src="@drawable/ic_ime_switcher_default"
+ android:layout_gravity="top"
android:visibility="invisible" />
<com.android.systemui.statusbar.policy.KeyButtonView
@@ -205,14 +210,16 @@
android:layout_height="40dp"
android:contentDescription="@string/accessibility_menu"
android:src="@drawable/ic_sysbar_menu_land"
+ android:layout_gravity="top"
android:visibility="invisible"
systemui:keyCode="82" />
</FrameLayout>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_height="80dp"
+ android:layout_height="@dimen/navigation_key_width"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_recent_land"
+ android:scaleType="center"
android:layout_weight="0"
android:contentDescription="@string/accessibility_recent"
/>
@@ -223,9 +230,10 @@
android:visibility="invisible"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_height="80dp"
+ android:layout_height="@dimen/navigation_key_width"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_home_land"
+ android:scaleType="center"
systemui:keyCode="3"
systemui:keyRepeat="false"
android:layout_weight="0"
@@ -238,7 +246,7 @@
android:visibility="invisible"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_height="80dp"
+ android:layout_height="@dimen/navigation_key_width"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_back_land"
android:scaleType="center"
@@ -247,7 +255,7 @@
android:contentDescription="@string/accessibility_back"
/>
<View
- android:layout_height="40dp"
+ android:layout_height="@dimen/navigation_side_padding"
android:layout_width="match_parent"
android:layout_weight="0"
android:visibility="invisible"
@@ -263,8 +271,8 @@
android:visibility="gone"
>
<ImageView
- android:layout_height="80dp"
- android:layout_marginTop="40dp"
+ android:layout_height="@dimen/navigation_key_width"
+ android:layout_marginTop="@dimen/navigation_side_padding"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
@@ -277,7 +285,7 @@
android:visibility="invisible"
/>
<ImageView
- android:layout_height="80dp"
+ android:layout_height="@dimen/navigation_key_width"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
@@ -290,8 +298,8 @@
android:visibility="invisible"
/>
<ImageView
- android:layout_height="80dp"
- android:layout_marginBottom="40dp"
+ android:layout_height="@dimen/navigation_key_width"
+ android:layout_marginBottom="@dimen/navigation_side_padding"
android:layout_width="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f08d99ee1c7e..5b21f3ffa674 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"የ<xliff:g id="DATA_LIMIT">%s</xliff:g> ማስጠንቀቂያ"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"የቅርብ ጊዜ ማያ ገጾችዎ እዚህ ይታያሉ"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"የመተግበሪያ መረጃ"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ማያ ገጽ መሰካት"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ን መጀመር አልተቻለም።"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ባትሪ ሞልቷል"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 20111351a9e8..3a2eabd241ed 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Скорошните ви екрани се показват тук"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Информация за приложението"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"фиксиране на екрана"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не можа да стартира."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заредена"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 60872f58125c..ff1d1a0cf623 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> সতর্কতা"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"আপনার সাম্প্রতিক স্ক্রীনগুলো এখানে দেখা যাবে"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"অ্যাপ্লিকেশানের তথ্য"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"স্ক্রীন পিন করা"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"অনুসন্ধান"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> শুরু করা যায়নি৷"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"চার্জ হয়েছে"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 9f7457143689..feb326c044ca 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertiment: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Aquí es mostren les teves pantalles recents."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informació de l\'aplicació"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixació de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No s\'ha pogut iniciar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index c102f13fa4e7..ae8ccf34d31d 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advarsel ved <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Dine seneste skærme vises her"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Oplysninger om applikationen"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skærmfastholdelse"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> kunne ikke startes."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opladet"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index d924ceaf76d2..946dc2c20423 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Προειδοποίηση για <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Οι πρόσφατες οθόνες σας εμφανίζονται εδώ"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"καρφίτσωμα οθόνης"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Δεν ήταν δυνατή η εκκίνηση της εφαρμογής <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Φορτίστηκε"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 0e723ea77d84..d3aab3b79a58 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Las pantallas recientes aparecen aquí."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Fijar pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No se pudo iniciar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index b8e4e4e39f43..1530bf3ac21c 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Aquí aparecerán tus pantallas recientes"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fijación de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"No se ha podido iniciar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index be851664be30..55d6d1fabc87 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> hoiatus"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Teie viimane ekraanikuva ilmub siia"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Rakenduste teave"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekraanikuva kinnitamine"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Rakendust <xliff:g id="APP">%s</xliff:g> ei saanud käivitada."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laetud"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 84874d318580..01cd8600af78 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Abisua: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Ikusitako azken pantailak erakusten dira hemen"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Aplikazioaren informazioa"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pantaila-ainguratzea"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"bilatu"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Ezin izan da hasi <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kargatuta"</string>
@@ -300,7 +299,7 @@
<string name="phone_hint" msgid="3101468054914424646">"Telefonoa irekitzeko, pasatu hatza eskuinera."</string>
<string name="camera_hint" msgid="5241441720959174226">"Kamera irekitzeko, pasatu hatza ezkerrera."</string>
<string name="interruption_level_none" msgid="3831278883136066646">"Bat ere ez"</string>
- <string name="interruption_level_priority" msgid="6517366750688942030">"Lehentasuna"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Lehentas."</string>
<string name="interruption_level_all" msgid="1330581184930945764">"Guztiak"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Kargatzen (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> guztiz kargatu arte)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Aldatu erabiltzailea"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index be27fb131250..0d5281cbd1dd 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> – varoitus"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Äskettäin käytetyt ruudut näkyvät tässä"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Sovellustiedot"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"näytön kiinnitys"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Sovelluksen <xliff:g id="APP">%s</xliff:g> käynnistäminen epäonnistui."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ladattu"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a52655edf44c..5119babc0552 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertissement : <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Vos écrans récents s\'affichent ici"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Détails de l\'application"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargée"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 26fa5a2fb72c..52f05db2b4fa 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertissement : <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Vos écrans récents s\'affichent ici"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informations sur l\'application"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargé"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 1d9b63a5d35c..f5b773f408df 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"As túas pantallas recentes aparecen aquí"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Información da aplicación"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixación de pantalla"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Non foi posible iniciar <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 0ad9f3edce26..101b4cdad7fe 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Ovdje se pojavljuju vaši nedavni zasloni"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"prikačivanje zaslona"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacija <xliff:g id="APP">%s</xliff:g> nije pokrenuta."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjeno"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 591e6fa5af8c..0b7dff3d11f5 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Figyelem! <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"A legutóbbi képernyők itt jelennek meg"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Az alkalmazás adatai"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"képernyő rögzítése"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nem lehet elindítani a következőt: <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Feltöltve"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 5db23b810ba7..e56633a3ceca 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> զգուշացում"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Ձեր վերջին էկրանները տեսանելի են այստեղ"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Հավելվածի մասին"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"էկրանի ամրակցում"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Հնարավոր չէ գործարկել <xliff:g id="APP">%s</xliff:g>-ը:"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Լիցքավորված է"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 0a058647868e..cac5b271b312 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> viðvörun"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Nýlegar skjámyndir birtast hér"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Forritsupplýsingar"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"skjáfesting"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"leita"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Ekki var hægt að ræsa <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Fullhlaðin"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 82711f1a547e..150bcec59661 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avviso <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Le tue schermate recenti vengono visualizzate in questa sezione"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informazioni sull\'applicazione"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"blocco su schermo"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Impossibile avviare <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carica"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 81e38ea4ef5d..22501d2a0b4f 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"警告: 上限は<xliff:g id="DATA_LIMIT">%s</xliff:g>です"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"ここに最近の画面が表示されます"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"アプリ情報"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"画面固定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>を開始できません。"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"充電が完了しました"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index fd9300948321..34ee563adbfe 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> туралы ескерту"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Мұнда жақындағы экрандар көрсетіледі"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Қолданба туралы ақпарат"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экранды бекіту"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"іздеу"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> іске қосу мүмкін болмады."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Зарядталды"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 174c0a955361..99d8acdffdf7 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ಎಚ್ಚರಿಕೆ"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"ನಿಮ್ಮ ಇತ್ತೀಚಿನ ಪರದೆಗಳು ಇಲ್ಲಿ ಕಾಣಿಸಿಕೊಳ್ಳುತ್ತವೆ"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ಪರದೆ ಪಿನ್ನಿಂಗ್"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ಹುಡುಕಾಟ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ಪ್ರಾರಂಭಿಸಲು ಸಾದ್ಯವಿಲ್ಲ."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 191411626f94..f00bc0176dc0 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> 경고"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"여기에 최근 화면이 표시됩니다."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"애플리케이션 정보"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"화면 고정"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>을(를) 시작할 수 없습니다."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"충전됨"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 44babae35e97..fc2281567f7f 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -300,8 +300,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> эскертүү"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Акыркы экрандарыңыз бул жерден көрүнөт"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Колдонмо жөнүндө маалымат"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"экран кадоо"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"издөө"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> баштай алган жок."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Кубатталды"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 5cba7f3af3af..79a225dc0912 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"ຄຳ​ເຕືອນ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Your recent screens appear here"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"​ຂໍ້​ມູນ​ແອັບ​ພ​ລິ​ເຄ​ຊັນ"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ການ​ປັກ​ໝຸດ​ໜ້າ​ຈໍ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"ບໍ່​ສາ​ມາດ​ເລີ່ມ <xliff:g id="APP">%s</xliff:g> ໄດ້."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ສາກເຕັມແລ້ວ."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 342b98542319..376d78eff041 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> įspėjimas"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Čia rodomi naujausi ekranai"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Programos informacija"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekrano prisegimas"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nepavyko paleisti <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Įkrautas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 960f52c2698e..fe88b1089748 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> brīdinājums"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Jūsu pēdējie ekrāni tiek rādīti šeit."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informācija par lietojumprogrammu"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Piespraust ekrānu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nevarēja palaist lietotni <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulators uzlādēts"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 46cb4a6dc4c8..67d6f6630615 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупредување за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Вашите неодамнешни екрани се појавуваат тука"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Информации за апликацијата"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"прикачување екран"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"пребарај"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> не може да се вклучи."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Наполнета"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 30423ff48f89..ec22c9149b2b 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> മുന്നറിയിപ്പ്"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"നിങ്ങളുടെ പുതിയ സ്ക്രീനുകൾ ഇവിടെ ദൃശ്യമാകുന്നു"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"അപ്ലിക്കേഷൻ വിവരം"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"സ്ക്രീൻ പിൻ ചെയ്യൽ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"തിരയുക"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കാനായില്ല."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ചാർജ്ജുചെയ്‌തു"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 9da46d815b46..27b218447c9c 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Amaran <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Skrin terbaru anda terpapar di sini"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Maklumat Aplikasi"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"penyematan skrin"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Tidak dapat memulakan <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Sudah dicas"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 22b59437c1c3..da01a12abc24 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -31,7 +31,7 @@
</plurals>
<string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen varslinger"</string>
<string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktiviteter"</string>
- <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varslinger"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varsler"</string>
<string name="battery_low_title" msgid="6456385927409742437">"Batterikapasiteten er lav"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår"</string>
<string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår. Batterisparing er på."</string>
@@ -48,7 +48,7 @@
<string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Roter skjerm automatisk"</string>
<string name="status_bar_settings_mute_label" msgid="554682549917429396">"DEMPET"</string>
<string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
- <string name="status_bar_settings_notifications" msgid="397146176280905137">"Varslinger"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Varsler"</string>
<string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tilknyttet"</string>
<string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Konfigurer inndatametoder"</string>
<string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fysisk tastatur"</string>
@@ -148,7 +148,7 @@
<string name="accessibility_airplane_mode" msgid="834748999790763092">"Flymodus."</string>
<string name="accessibility_battery_level" msgid="7451474187113371965">"Batteri – <xliff:g id="NUMBER">%d</xliff:g> prosent."</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"Systeminnstillinger."</string>
- <string name="accessibility_notifications_button" msgid="4498000369779421892">"Varslinger."</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"Varsler."</string>
<string name="accessibility_remove_notification" msgid="3603099514902182350">"Fjern varsling"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS er aktivert."</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Henting av GPS-signal."</string>
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advarsel for <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"De sist brukte skjermene dine vises her"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformasjon"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"én-appsmodus"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Kunne ikke starte <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Oppladet"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 4987619e4a6f..2663231c1ec1 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Waarschuwing voor <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Uw recente schermen worden hier weergegeven"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"App-informatie"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"scherm vastzetten"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Kan <xliff:g id="APP">%s</xliff:g> niet starten."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opgeladen"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 9b58984e32ca..fc79990d3586 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -247,7 +247,7 @@
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Brak połączenia"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Brak sieci"</string>
- <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wyłącz Wi-Fi"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi wyłączone"</string>
<string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Brak dostępnych zapisanych sieci"</string>
<string name="quick_settings_cast_title" msgid="1893629685050355115">"Przesyłaj ekran"</string>
<string name="quick_settings_casting" msgid="6601710681033353316">"Przesyłam"</string>
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Ostrzeżenie: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Tutaj pojawią się ostatnie ekrany"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacje o aplikacji"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"przypinanie ekranu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Nie udało się uruchomić aplikacji <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Naładowana"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b7c37b82757c..bc345b169ebc 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Os ecrãs recentes aparecem aqui"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações da aplicação"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixação no ecrã"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Não foi possível iniciar o <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index ffa73b2009e2..481a6dd6bfef 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertizare: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Ecranele dvs. recente apar aici"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informații despre aplicație"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fixare pe ecran"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> nu a putut porni."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"S-a încărcat"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9f82006cec79..858b787edeb2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Здесь будут показаны недавние приложения"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Сведения о приложении"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"Заблокировать в приложении"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Не удалось запустить приложение \"<xliff:g id="APP">%s</xliff:g>\""</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Батарея заряжена"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 315286875306..b0a6b47e15c4 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> අවවාද කිරීම"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"මෙහි ඔබගේ මෑතක තිර පෙන්නුම් කරයි"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"යෙදුම් තොරතුරු"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"තිර ඇමිණීම"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"සෙවීම"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කළ නොහැක."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"අරෝපිතයි"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 74faa1dc8c60..b6437a2ca436 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Opozorilo – <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Vaši nedavni zasloni so prikazani tu"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Podatki o aplikaciji"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pripenjanje zaslona"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Aplikacije <xliff:g id="APP">%s</xliff:g> ni bilo mogoče zagnati."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulator napolnjen"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 630f9ce774f6..d47cf4884d88 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Упозорење за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Недавни екрани се појављују овде"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Информације о апликацији"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"качење екрана"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Покретање апликације <xliff:g id="APP">%s</xliff:g> није успело."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Напуњена је"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index a58dc68d31d6..ca0cfc6c0507 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Varning <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Dina senaste skärmar visas här"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformation"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"fästa skärmen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Det gick inte att starta appen <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laddat"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index d46d5b656dae..58e0c411d7ca 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Onyo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Skrini zako za hivi majuzi huonekana hapa"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Maelezo ya Programu"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"kudumisha programu moja"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Haikuweza kuanzisha <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Betri imejaa"</string>
diff --git a/packages/SystemUI/res/values-sw360dp/dimens.xml b/packages/SystemUI/res/values-sw360dp/dimens.xml
new file mode 100644
index 000000000000..dfd97435a288
--- /dev/null
+++ b/packages/SystemUI/res/values-sw360dp/dimens.xml
@@ -0,0 +1,30 @@
+<?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
+ -->
+<resources>
+
+ <!-- The width of the view containing navigation buttons -->
+ <dimen name="navigation_key_width">80dip</dimen>
+
+ <!-- The width of the view containing the menu/ime navigation bar icons -->
+ <dimen name="navigation_extra_key_width">40dip</dimen>
+
+ <!-- The padding on the side of the navigation bar. Must be greater than or equal to
+ navigation_extra_key_width -->
+ <dimen name="navigation_side_padding">40dip</dimen>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw400dp/dimens.xml b/packages/SystemUI/res/values-sw400dp/dimens.xml
new file mode 100644
index 000000000000..80e82c4fd594
--- /dev/null
+++ b/packages/SystemUI/res/values-sw400dp/dimens.xml
@@ -0,0 +1,27 @@
+<?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
+ -->
+<resources>
+
+ <!-- The width of the view containing navigation buttons -->
+ <dimen name="navigation_key_width">80dip</dimen>
+
+ <!-- The padding on the side of the navigation bar. Must be greater than or equal to
+ navigation_extra_key_width -->
+ <dimen name="navigation_side_padding">50dp</dimen>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 850a964e823a..847529c5b748 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> எச்சரிக்கை"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"சமீபத்திய திரைகள் இங்கு தோன்றும்"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"பயன்பாட்டு தகவல்"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"திரையை பின் செய்தல்"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"தேடு"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g>ஐத் தொடங்க முடியவில்லை."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"சார்ஜ் செய்யப்பட்டது"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 269743bb3af4..e295be22d383 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> uyarısı"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Son ekranlarınız burada görünür"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Uygulama Bilgileri"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekran sabitleme"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> başlatılamadı."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ödeme alındı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 6e31484a0e66..6798df19ef74 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Застереження: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Ваші останні екрани відображаються тут"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Інформація про додаток"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"закріпити екран"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"Не вдалося запустити <xliff:g id="APP">%s</xliff:g>."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заряджено"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index e3c174e209a1..6b05ac52feb3 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> وارننگ"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"آپ کی حالیہ اسکرینز یہاں ظاہر ہوتی ہیں"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"ایپلیکیشن کی معلومات"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"اسکرین کو پن کرنا"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"تلاش کریں"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> کو شروع نہیں کیا جا سکا۔"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"چارج ہوگئی"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 3430cf917ab7..c561400cd747 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -275,8 +275,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Ogohlantirish: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"Siz yaqinda ishlatgan ilova ekranlari bu yerda ko‘rinadi"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Ilova haqida ma’lumot"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"ekranni qadab qo‘yish"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"qidirish"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"“<xliff:g id="APP">%s</xliff:g>” ilovasini ishga tushirib bo‘lmadi."</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Batareya quvvati to‘ldi"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index b511baff19c0..8895799b2c10 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -277,8 +277,7 @@
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g>警告"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"您最近浏览过的屏幕会显示在此处"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"应用信息"</string>
- <!-- no translation found for recents_lock_to_app_button_label (6942899049072506044) -->
- <skip />
+ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"固定屏幕"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"无法启动<xliff:g id="APP">%s</xliff:g>。"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"充电完成"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 4f867a0e422a..4da54e30b906 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -224,13 +224,16 @@
<integer name="doze_pickup_vibration_threshold">2000</integer>
<!-- Doze: pulse parameter - how long does it take to fade in? -->
- <integer name="doze_pulse_duration_in">1000</integer>
+ <integer name="doze_pulse_duration_in">900</integer>
+
+ <!-- Doze: pulse parameter - delay for fading so the screen can wake up before -->
+ <integer name="doze_pulse_delay_in">200</integer>
<!-- Doze: pulse parameter - once faded in, how long does it stay visible? -->
<integer name="doze_pulse_duration_visible">3000</integer>
<!-- Doze: pulse parameter - how long does it take to fade out? -->
- <integer name="doze_pulse_duration_out">1000</integer>
+ <integer name="doze_pulse_duration_out">600</integer>
<!-- Doze: alpha to apply to small icons when dozing -->
<integer name="doze_small_icon_alpha">222</integer><!-- 87% of 0xff -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 07573e075436..6e6f3025545f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -103,11 +103,15 @@
<!-- The padding on the global screenshot background image -->
<dimen name="global_screenshot_bg_padding">20dp</dimen>
- <!-- The width of the view containing non-menu status bar icons -->
- <dimen name="navigation_key_width">80dip</dimen>
+ <!-- The width of the view containing navigation buttons -->
+ <dimen name="navigation_key_width">70dp</dimen>
<!-- The width of the view containing the menu/ime navigation bar icons -->
- <dimen name="navigation_extra_key_width">40dip</dimen>
+ <dimen name="navigation_extra_key_width">36dp</dimen>
+
+ <!-- The padding on the side of the navigation bar. Must be greater than or equal to
+ navigation_extra_key_width -->
+ <dimen name="navigation_side_padding">36dp</dimen>
<!-- Default distance beyond which snaps to the matching target -->
<dimen name="navbar_search_snap_margin">40dip</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 0f8fe1cdc9cb..d42ac612be9f 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -351,6 +351,9 @@ public class ExpandHelper implements Gefingerpoken {
mVelocityTracker.addMovement(event);
break;
case MotionEvent.ACTION_MOVE:
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
mVelocityTracker.addMovement(event);
break;
default:
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 0d393bf706fa..f206e5633819 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -311,11 +311,14 @@ public class SwipeHelper implements Gefingerpoken {
final View animView = mCallback.getChildContentView(view);
final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
float newPos;
+ boolean isLayoutRtl = view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
if (velocity < 0
|| (velocity == 0 && getTranslation(animView) < 0)
// if we use the Menu to dismiss an item in landscape, animate up
- || (velocity == 0 && getTranslation(animView) == 0 && mSwipeDirection == Y)) {
+ || (velocity == 0 && getTranslation(animView) == 0 && mSwipeDirection == Y)
+ // if the language is rtl we prefer swiping to the left
+ || (velocity == 0 && getTranslation(animView) == 0 && isLayoutRtl)) {
newPos = -getSize(animView);
} else {
newPos = getSize(animView);
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index f5df1a9ed2bd..4391bfc88246 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -66,6 +66,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
private static final String ACTION_SHOW_BATTERY_SETTINGS = "PNW.batterySettings";
private static final String ACTION_START_SAVER = "PNW.startSaver";
private static final String ACTION_STOP_SAVER = "PNW.stopSaver";
+ private static final String ACTION_DISMISSED_WARNING = "PNW.dismissedWarning";
private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -180,6 +181,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
.setContentTitle(mContext.getString(R.string.battery_low_title))
.setContentText(mContext.getString(textRes, percentage))
.setOnlyAlertOnce(true)
+ .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
.setPriority(Notification.PRIORITY_MAX)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setColor(mContext.getResources().getColor(
@@ -374,6 +376,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
filter.addAction(ACTION_SHOW_BATTERY_SETTINGS);
filter.addAction(ACTION_START_SAVER);
filter.addAction(ACTION_STOP_SAVER);
+ filter.addAction(ACTION_DISMISSED_WARNING);
mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, mHandler);
}
@@ -391,6 +394,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
dismissSaverNotification();
dismissLowBatteryNotification();
setSaverMode(false);
+ } else if (action.equals(ACTION_DISMISSED_WARNING)) {
+ dismissLowBatteryWarning();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index fdebdd3b8828..54a84141b341 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -542,7 +542,10 @@ public class QSPanel extends ViewGroup {
@Override
public void onAnimationEnd(Animator animation) {
- setGridContentVisibility(false);
+ // Only hide content if still in detail state.
+ if (mDetailRecord != null) {
+ setGridContentVisibility(false);
+ }
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index e4faa6a3f85b..02b93780667a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -508,7 +508,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
if (mAppearAnimator != null) {
mAppearAnimator.cancel();
}
- mAnimationTranslationY = translationDirection * mActualHeight;
+ mAnimationTranslationY = translationDirection * getActualHeight();
if (mAppearAnimationFraction == -1.0f) {
// not initialized yet, we start anew
if (isAppearing) {
@@ -601,14 +601,15 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
float top;
float bottom;
+ final int actualHeight = getActualHeight();
if (mAnimationTranslationY > 0.0f) {
- bottom = mActualHeight - heightFraction * mAnimationTranslationY * 0.1f
+ bottom = actualHeight - heightFraction * mAnimationTranslationY * 0.1f
- translateYTotalAmount;
top = bottom * heightFraction;
} else {
- top = heightFraction * (mActualHeight + mAnimationTranslationY) * 0.1f -
+ top = heightFraction * (actualHeight + mAnimationTranslationY) * 0.1f -
translateYTotalAmount;
- bottom = mActualHeight * (1 - heightFraction) + top * heightFraction;
+ bottom = actualHeight * (1 - heightFraction) + top * heightFraction;
}
mAppearAnimationRect.set(left, top, right, bottom);
setOutlineRect(left, top + mAppearAnimationTranslation, right,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 1b4bdf839aee..09d0b5d46e70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -59,6 +59,7 @@ import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.Display;
@@ -113,6 +114,9 @@ public abstract class BaseStatusBar extends SystemUI implements
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final boolean MULTIUSER_DEBUG = false;
+ // STOPSHIP disable once we resolve b/18102199
+ private static final boolean NOTIFICATION_CLICK_DEBUG = true;
+
protected static final int MSG_SHOW_RECENT_APPS = 1019;
protected static final int MSG_HIDE_RECENT_APPS = 1020;
protected static final int MSG_TOGGLE_RECENTS_APPS = 1021;
@@ -325,6 +329,9 @@ public abstract class BaseStatusBar extends SystemUI implements
ViewGroup actionGroup = (ViewGroup) parent;
index = actionGroup.indexOfChild(view);
}
+ if (NOTIFICATION_CLICK_DEBUG) {
+ Log.d(TAG, "Clicked on button " + index + " for " + key);
+ }
try {
mBarService.onNotificationActionClick(key, index);
} catch (RemoteException e) {
@@ -1515,6 +1522,9 @@ public abstract class BaseStatusBar extends SystemUI implements
}
public void onClick(final View v) {
+ if (NOTIFICATION_CLICK_DEBUG) {
+ Log.d(TAG, "Clicked on content of " + mNotificationKey);
+ }
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
final boolean afterKeyguardGone = mIntent.isActivity()
&& PreviewInflater.wouldLaunchResolverActivity(mContext, mIntent.getIntent(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
index 897dbf224176..479c2fb8e2aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
@@ -36,4 +36,11 @@ public class DismissView extends StackScrollerDecorView {
public void setOnButtonClickListener(OnClickListener listener) {
mContent.setOnClickListener(listener);
}
+
+ public boolean isOnEmptySpace(float touchX, float touchY) {
+ return touchX < mContent.getX()
+ || touchX > mContent.getX() + mContent.getWidth()
+ || touchY < mContent.getY()
+ || touchY > mContent.getY() + mContent.getHeight();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 556c423080b9..a4e5e7443c06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -23,10 +23,8 @@ import android.graphics.drawable.Drawable;
import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.accessibility.AccessibilityEvent;
-
import android.widget.ImageView;
import com.android.systemui.R;
@@ -156,9 +154,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
}
public void resetHeight() {
+ super.resetHeight();
mMaxExpandHeight = 0;
mWasReset = true;
- mActualHeight = 0;
onHeightReset();
requestLayout();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index f85d32b3770c..a18fff247397 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -41,7 +41,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
outline.setRect(0,
mClipTopAmount,
getWidth(),
- Math.max(mActualHeight, mClipTopAmount));
+ Math.max(getActualHeight(), mClipTopAmount));
} else {
outline.setRect(mOutlineRect);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index c8f756e906c0..edfbe868c481 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -36,7 +36,7 @@ public abstract class ExpandableView extends FrameLayout {
private final int mMaxNotificationHeight;
private OnHeightChangedListener mOnHeightChangedListener;
- protected int mActualHeight;
+ private int mActualHeight;
protected int mClipTopAmount;
private boolean mActualHeightInitialized;
private ArrayList<View> mMatchParentViews = new ArrayList<View>();
@@ -103,6 +103,11 @@ public abstract class ExpandableView extends FrameLayout {
}
}
+ protected void resetHeight() {
+ mActualHeight = 0;
+ mActualHeightInitialized = false;
+ }
+
protected int getInitialHeight() {
return getHeight();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index 5db680a1b379..0fc46e9c701b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -23,9 +23,7 @@ import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
-import android.view.MotionEvent;
import android.view.View;
-import com.android.systemui.R;
/**
* A view that can be used for both the dimmed and normal background of an notification.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 502490f82aea..9b11f9bcd5d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -27,11 +27,11 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewTreeObserver;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
-
import com.android.systemui.R;
/**
@@ -60,6 +60,16 @@ public class NotificationContentView extends FrameLayout {
private boolean mDark;
private final Paint mFadePaint = new Paint();
+ private boolean mAnimate;
+ private ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
+ = new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ mAnimate = true;
+ getViewTreeObserver().removeOnPreDrawListener(this);
+ return true;
+ }
+ };
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -73,6 +83,12 @@ public class NotificationContentView extends FrameLayout {
updateClipping();
}
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ updateVisibility();
+ }
+
public void reset() {
if (mContractedChild != null) {
mContractedChild.animate().cancel();
@@ -117,9 +133,31 @@ public class NotificationContentView extends FrameLayout {
selectLayout(false /* animate */, true /* force */);
}
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ updateVisibility();
+ }
+
+ private void updateVisibility() {
+ setVisible(isShown());
+ }
+
+ private void setVisible(final boolean isVisible) {
+ if (isVisible) {
+
+ // We only animate if we are drawn at least once, otherwise the view might animate when
+ // it's shown the first time
+ getViewTreeObserver().addOnPreDrawListener(mEnableAnimationPredrawListener);
+ } else {
+ getViewTreeObserver().removeOnPreDrawListener(mEnableAnimationPredrawListener);
+ mAnimate = false;
+ }
+ }
+
public void setActualHeight(int actualHeight) {
mActualHeight = actualHeight;
- selectLayout(true /* animate */, false /* force */);
+ selectLayout(mAnimate /* animate */, false /* force */);
updateClipping();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index 682c01cadddd..6cb5bccf39fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -159,7 +159,7 @@ public class DemoStatusIcons extends LinearLayout implements DemoMode {
}
}
StatusBarIcon icon = new StatusBarIcon(iconPkg, UserHandle.CURRENT, iconId, 0, 0, "Demo");
- StatusBarIconView v = new StatusBarIconView(getContext(), null);
+ StatusBarIconView v = new StatusBarIconView(getContext(), null, null);
v.setTag(slot);
v.set(icon);
addView(v, 0, new LinearLayout.LayoutParams(mIconSize, mIconSize));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index b566bbc7096e..6fd67580226f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -48,6 +48,7 @@ public class DozeParameters {
pw.print(" getDisplayStateSupported(): "); pw.println(getDisplayStateSupported());
pw.print(" getPulseDuration(): "); pw.println(getPulseDuration());
pw.print(" getPulseInDuration(): "); pw.println(getPulseInDuration());
+ pw.print(" getPulseInDelay(): "); pw.println(getPulseInDelay());
pw.print(" getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration());
pw.print(" getPulseOutDuration(): "); pw.println(getPulseOutDuration());
pw.print(" getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion());
@@ -72,6 +73,10 @@ public class DozeParameters {
return getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in);
}
+ public int getPulseInDelay() {
+ return getInt("doze.pulse.delay.in", R.integer.doze_pulse_delay_in);
+ }
+
public int getPulseVisibleDuration() {
return getInt("doze.pulse.duration.visible", R.integer.doze_pulse_duration_visible);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 598a35c4acc7..fddbee2ee400 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -39,6 +39,8 @@ import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -72,6 +74,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private static final Intent INSECURE_CAMERA_INTENT =
new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
+ private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
+ private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
private KeyguardAffordanceView mCameraImageView;
private KeyguardAffordanceView mPhoneImageView;
@@ -92,7 +96,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private PhoneStatusBar mPhoneStatusBar;
private final TrustDrawable mTrustDrawable;
-
+ private final Interpolator mLinearOutSlowInInterpolator;
private int mLastUnlockIconRes = 0;
public KeyguardBottomAreaView(Context context) {
@@ -111,6 +115,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mTrustDrawable = new TrustDrawable(mContext);
+ mLinearOutSlowInInterpolator =
+ AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in);
}
private AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() {
@@ -450,6 +456,35 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
}
+ public void startFinishDozeAnimation() {
+ long delay = 0;
+ if (mPhoneImageView.getVisibility() == View.VISIBLE) {
+ startFinishDozeAnimationElement(mPhoneImageView, delay);
+ delay += DOZE_ANIMATION_STAGGER_DELAY;
+ }
+ startFinishDozeAnimationElement(mLockIcon, delay);
+ delay += DOZE_ANIMATION_STAGGER_DELAY;
+ if (mCameraImageView.getVisibility() == View.VISIBLE) {
+ startFinishDozeAnimationElement(mCameraImageView, delay);
+ }
+ mIndicationText.setAlpha(0f);
+ mIndicationText.animate()
+ .alpha(1f)
+ .setInterpolator(mLinearOutSlowInInterpolator)
+ .setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
+ }
+
+ private void startFinishDozeAnimationElement(View element, long delay) {
+ element.setAlpha(0f);
+ element.setTranslationY(element.getHeight() / 2);
+ element.animate()
+ .alpha(1f)
+ .translationY(0f)
+ .setInterpolator(mLinearOutSlowInInterpolator)
+ .setStartDelay(delay)
+ .setDuration(DOZE_ANIMATION_ELEMENT_DURATION);
+ }
+
private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
post(new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 88e71e2cee74..9bb52e71ddd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -33,12 +33,14 @@ import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
+import android.view.Gravity;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.systemui.R;
@@ -503,15 +505,31 @@ public class NavigationBarView extends LinearLayout {
// We swap all children of the 90 and 270 degree layouts, since they are vertical
View rotation90 = mRotatedViews[Surface.ROTATION_90];
swapChildrenOrderIfVertical(rotation90.findViewById(R.id.nav_buttons));
+ adjustExtraKeyGravity(rotation90, isLayoutRtl);
View rotation270 = mRotatedViews[Surface.ROTATION_270];
if (rotation90 != rotation270) {
swapChildrenOrderIfVertical(rotation270.findViewById(R.id.nav_buttons));
+ adjustExtraKeyGravity(rotation270, isLayoutRtl);
}
mIsLayoutRtl = isLayoutRtl;
}
}
+ private void adjustExtraKeyGravity(View navBar, boolean isLayoutRtl) {
+ View menu = navBar.findViewById(R.id.menu);
+ View imeSwitcher = navBar.findViewById(R.id.ime_switcher);
+ if (menu != null) {
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) menu.getLayoutParams();
+ lp.gravity = isLayoutRtl ? Gravity.BOTTOM : Gravity.TOP;
+ menu.setLayoutParams(lp);
+ }
+ if (imeSwitcher != null) {
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) imeSwitcher.getLayoutParams();
+ lp.gravity = isLayoutRtl ? Gravity.BOTTOM : Gravity.TOP;
+ imeSwitcher.setLayoutParams(lp);
+ }
+ }
/**
* Swaps the children order of a LinearLayout if it's orientation is Vertical
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 bc2196ae40bf..d9e44c30c7a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -52,7 +52,7 @@ import com.android.systemui.statusbar.stack.StackStateAnimator;
public class NotificationPanelView extends PanelView implements
ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
- KeyguardAffordanceHelper.Callback {
+ KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener {
// Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is
// changed.
@@ -64,7 +64,7 @@ public class NotificationPanelView extends PanelView implements
private static final int DOZE_BACKGROUND_COLOR = 0xff000000;
private static final int TAG_KEY_ANIM = R.id.scrim;
- private static final long DOZE_BACKGROUND_ANIM_DURATION = ScrimController.ANIMATION_DURATION;
+ public static final long DOZE_ANIMATION_DURATION = 700;
private KeyguardAffordanceHelper mAfforanceHelper;
private StatusBarHeaderView mHeader;
@@ -132,6 +132,7 @@ public class NotificationPanelView extends PanelView implements
private Interpolator mFastOutSlowInInterpolator;
private Interpolator mFastOutLinearInterpolator;
+ private Interpolator mDozeAnimationInterpolator;
private ObjectAnimator mClockAnimator;
private int mClockAnimationTarget = -1;
private int mTopPaddingAdjustment;
@@ -167,6 +168,8 @@ public class NotificationPanelView extends PanelView implements
private boolean mQsTouchAboveFalsingThreshold;
private int mQsFalsingThreshold;
+ private float mKeyguardStatusBarAnimateAlpha = 1f;
+
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -194,11 +197,14 @@ public class NotificationPanelView extends PanelView implements
findViewById(R.id.notification_stack_scroller);
mNotificationStackScroller.setOnHeightChangedListener(this);
mNotificationStackScroller.setOverscrollTopChangedListener(this);
+ mNotificationStackScroller.setOnEmptySpaceClickListener(this);
mNotificationStackScroller.setScrollView(mScrollView);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
android.R.interpolator.fast_out_slow_in);
mFastOutLinearInterpolator = AnimationUtils.loadInterpolator(getContext(),
android.R.interpolator.fast_out_linear_in);
+ mDozeAnimationInterpolator = AnimationUtils.loadInterpolator(getContext(),
+ android.R.interpolator.linear_out_slow_in);
mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
@@ -521,13 +527,15 @@ public class NotificationPanelView extends PanelView implements
mIntercepting = false;
break;
}
+ return super.onInterceptTouchEvent(event);
+ }
- // Allow closing the whole panel when in SHADE state.
- if (mStatusBarState == StatusBarState.SHADE) {
- return super.onInterceptTouchEvent(event);
- } else {
- return !mQsExpanded && super.onInterceptTouchEvent(event);
- }
+ @Override
+ protected boolean isInContentBounds(float x, float y) {
+ float yTransformed = y - mNotificationStackScroller.getY();
+ float stackScrollerX = mNotificationStackScroller.getX();
+ return mNotificationStackScroller.isInContentBounds(yTransformed) && stackScrollerX < x
+ && x < stackScrollerX + mNotificationStackScroller.getWidth();
}
private void resetDownStates(MotionEvent event) {
@@ -631,10 +639,9 @@ public class NotificationPanelView extends PanelView implements
}
private boolean isInQsArea(float x, float y) {
- return mStatusBarState != StatusBarState.SHADE ||
- (x >= mScrollView.getLeft() && x <= mScrollView.getRight()) &&
- (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
- || y <= mQsContainer.getY() + mQsContainer.getHeight());
+ return (x >= mScrollView.getLeft() && x <= mScrollView.getRight()) &&
+ (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
+ || y <= mQsContainer.getY() + mQsContainer.getHeight());
}
private void handleQsDown(MotionEvent event) {
@@ -909,6 +916,8 @@ public class NotificationPanelView extends PanelView implements
@Override
public void run() {
mKeyguardStatusBar.setVisibility(View.INVISIBLE);
+ mKeyguardStatusBar.setAlpha(1f);
+ mKeyguardStatusBarAnimateAlpha = 1f;
}
};
@@ -918,10 +927,31 @@ public class NotificationPanelView extends PanelView implements
.setStartDelay(mStatusBar.getKeyguardFadingAwayDelay())
.setDuration(mStatusBar.getKeyguardFadingAwayDuration()/2)
.setInterpolator(PhoneStatusBar.ALPHA_OUT)
+ .setUpdateListener(mStatusBarAnimateAlphaListener)
.withEndAction(mAnimateKeyguardStatusBarInvisibleEndRunnable)
.start();
}
+ private final ValueAnimator.AnimatorUpdateListener mStatusBarAnimateAlphaListener =
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mKeyguardStatusBarAnimateAlpha = mKeyguardStatusBar.getAlpha();
+ }
+ };
+
+ private void animateKeyguardStatusBarIn() {
+ mKeyguardStatusBar.setVisibility(View.VISIBLE);
+ mKeyguardStatusBar.setAlpha(0f);
+ mKeyguardStatusBar.animate()
+ .alpha(1f)
+ .setStartDelay(0)
+ .setDuration(DOZE_ANIMATION_DURATION)
+ .setInterpolator(mDozeAnimationInterpolator)
+ .setUpdateListener(mStatusBarAnimateAlphaListener)
+ .start();
+ }
+
private final Runnable mAnimateKeyguardBottomAreaInvisibleEndRunnable = new Runnable() {
@Override
public void run() {
@@ -1082,9 +1112,26 @@ public class NotificationPanelView extends PanelView implements
}
private float calculateQsTopPadding() {
- // We can only do the smoother transition on Keyguard when we also are not collapsing from a
- // scrolled quick settings.
- if (mKeyguardShowing && mScrollYOverride == -1) {
+ if (mKeyguardShowing
+ && (mTwoFingerQsExpand || mIsExpanding && mQsExpandedWhenExpandingStarted)) {
+
+ // Either QS pushes the notifications down when fully expanded, or QS is fully above the
+ // notifications (mostly on tablets). maxNotifications denotes the normal top padding
+ // on Keyguard, maxQs denotes the top padding from the quick settings panel. We need to
+ // take the maximum and linearly interpolate with the panel expansion for a nice motion.
+ int maxNotifications = mClockPositionResult.stackScrollerPadding
+ - mClockPositionResult.stackScrollerPaddingAdjustment
+ - mNotificationTopPadding;
+ int maxQs = getTempQsMaxExpansion();
+ int max = mStatusBarState == StatusBarState.KEYGUARD
+ ? Math.max(maxNotifications, maxQs)
+ : maxQs;
+ return (int) interpolate(getExpandedFraction(),
+ mQsMinExpansionHeight, max);
+ } else if (mKeyguardShowing && mScrollYOverride == -1) {
+
+ // We can only do the smoother transition on Keyguard when we also are not collapsing
+ // from a scrolled quick settings.
return interpolate(getQsExpansionFraction(),
mNotificationStackScroller.getIntrinsicPadding() - mNotificationTopPadding,
mQsMaxExpansionHeight);
@@ -1096,7 +1143,9 @@ public class NotificationPanelView extends PanelView implements
private void requestScrollerTopPaddingUpdate(boolean animate) {
mNotificationStackScroller.updateTopPadding(calculateQsTopPadding(),
mScrollView.getScrollY(),
- mAnimateNextTopPaddingChange || animate);
+ mAnimateNextTopPaddingChange || animate,
+ mKeyguardShowing
+ && (mTwoFingerQsExpand || mIsExpanding && mQsExpandedWhenExpandingStarted));
mAnimateNextTopPaddingChange = false;
}
@@ -1226,18 +1275,27 @@ public class NotificationPanelView extends PanelView implements
@Override
protected void onHeightUpdated(float expandedHeight) {
- if (!mQsExpanded) {
+ if (!mQsExpanded || mTwoFingerQsExpand || mIsExpanding && mQsExpandedWhenExpandingStarted) {
positionClockAndNotifications();
}
if (mTwoFingerQsExpand || mQsExpanded && !mQsTracking && mQsExpansionAnimator == null
&& !mQsExpansionFromOverscroll) {
- float panelHeightQsCollapsed = mNotificationStackScroller.getIntrinsicPadding()
- + mNotificationStackScroller.getMinStackHeight()
- + mNotificationStackScroller.getNotificationTopPadding();
- float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
- float t = (expandedHeight - panelHeightQsCollapsed)
- / (panelHeightQsExpanded - panelHeightQsCollapsed);
+ float t;
+ if (mKeyguardShowing) {
+ // On Keyguard, interpolate the QS expansion linearly to the panel expansion
+ t = expandedHeight / getMaxPanelHeight();
+ } else {
+
+ // In Shade, interpolate linearly such that QS is closed whenever panel height is
+ // minimum QS expansion + minStackHeight
+ float panelHeightQsCollapsed = mNotificationStackScroller.getIntrinsicPadding()
+ + mNotificationStackScroller.getMinStackHeight()
+ + mNotificationStackScroller.getNotificationTopPadding();
+ float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
+ t = (expandedHeight - panelHeightQsCollapsed)
+ / (panelHeightQsExpanded - panelHeightQsCollapsed);
+ }
setQsExpansion(mQsMinExpansionHeight
+ t * (getTempQsMaxExpansion() - mQsMinExpansionHeight));
}
@@ -1271,8 +1329,10 @@ public class NotificationPanelView extends PanelView implements
float notificationHeight = mNotificationStackScroller.getHeight()
- mNotificationStackScroller.getEmptyBottomMargin()
- mNotificationStackScroller.getTopPadding();
- float totalHeight = mQsMaxExpansionHeight + notificationHeight
- + mNotificationStackScroller.getNotificationTopPadding();
+ float totalHeight = Math.max(
+ mQsMaxExpansionHeight + mNotificationStackScroller.getNotificationTopPadding(),
+ mClockPositionResult.stackScrollerPadding - mTopPaddingAdjustment)
+ + notificationHeight;
if (totalHeight > mNotificationStackScroller.getHeight()) {
float fullyCollapsedHeight = mQsMaxExpansionHeight
+ mNotificationStackScroller.getMinStackHeight()
@@ -1387,7 +1447,8 @@ public class NotificationPanelView extends PanelView implements
alphaNotifications = MathUtils.constrain(alphaNotifications, 0, 1);
alphaNotifications = (float) Math.pow(alphaNotifications, 0.75);
float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
- mKeyguardStatusBar.setAlpha(Math.min(alphaNotifications, alphaQsExpansion));
+ mKeyguardStatusBar.setAlpha(Math.min(alphaNotifications, alphaQsExpansion)
+ * mKeyguardStatusBarAnimateAlpha);
mKeyguardBottomArea.setAlpha(Math.min(1 - getQsExpansionFraction(), alphaNotifications));
setQsTranslation(mQsExpansionHeight);
}
@@ -1404,7 +1465,7 @@ public class NotificationPanelView extends PanelView implements
super.onExpandingStarted();
mNotificationStackScroller.onExpansionStarted();
mIsExpanding = true;
- mQsExpandedWhenExpandingStarted = mQsExpanded;
+ mQsExpandedWhenExpandingStarted = mQsFullyExpanded;
if (mQsExpanded) {
onQsExpansionStarted();
}
@@ -1458,11 +1519,12 @@ public class NotificationPanelView extends PanelView implements
@Override
protected void onTrackingStarted() {
super.onTrackingStarted();
+ if (mQsFullyExpanded) {
+ mTwoFingerQsExpand = true;
+ }
if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
|| mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
mAfforanceHelper.animateHideLeftRightIcon();
- } else if (mQsExpanded) {
- mTwoFingerQsExpand = true;
}
}
@@ -1736,19 +1798,22 @@ public class NotificationPanelView extends PanelView implements
return (1 - t) * start + t * end;
}
- private void updateKeyguardStatusBarVisibility() {
- mKeyguardStatusBar.setVisibility(mKeyguardShowing && !mDozing ? VISIBLE : INVISIBLE);
- }
-
- public void setDozing(boolean dozing) {
+ public void setDozing(boolean dozing, boolean animate) {
if (dozing == mDozing) return;
mDozing = dozing;
if (mDozing) {
- setBackgroundColorAlpha(this, DOZE_BACKGROUND_COLOR, 0xff, false /*animate*/);
+ setBackgroundColorAlpha(DOZE_BACKGROUND_COLOR, 0xff, false /*animate*/);
+ mKeyguardStatusBar.setVisibility(View.INVISIBLE);
+ mKeyguardBottomArea.setVisibility(View.INVISIBLE);
} else {
- setBackgroundColorAlpha(this, DOZE_BACKGROUND_COLOR, 0, true /*animate*/);
+ setBackgroundColorAlpha(DOZE_BACKGROUND_COLOR, 0, animate);
+ mKeyguardBottomArea.setVisibility(View.VISIBLE);
+ mKeyguardStatusBar.setVisibility(View.VISIBLE);
+ if (animate) {
+ animateKeyguardStatusBarIn();
+ mKeyguardBottomArea.startFinishDozeAnimation();
+ }
}
- updateKeyguardStatusBarVisibility();
}
@Override
@@ -1756,21 +1821,21 @@ public class NotificationPanelView extends PanelView implements
return mDozing;
}
- private static void setBackgroundColorAlpha(final View target, int rgb, int targetAlpha,
+ private void setBackgroundColorAlpha(int rgb, int targetAlpha,
boolean animate) {
- int currentAlpha = getBackgroundAlpha(target);
+ int currentAlpha = getBackgroundAlpha(this);
if (currentAlpha == targetAlpha) {
return;
}
final int r = Color.red(rgb);
final int g = Color.green(rgb);
final int b = Color.blue(rgb);
- Object runningAnim = target.getTag(TAG_KEY_ANIM);
+ Object runningAnim = getTag(TAG_KEY_ANIM);
if (runningAnim instanceof ValueAnimator) {
((ValueAnimator) runningAnim).cancel();
}
if (!animate) {
- target.setBackgroundColor(Color.argb(targetAlpha, r, g, b));
+ setBackgroundColor(Color.argb(targetAlpha, r, g, b));
return;
}
ValueAnimator anim = ValueAnimator.ofInt(currentAlpha, targetAlpha);
@@ -1778,18 +1843,19 @@ public class NotificationPanelView extends PanelView implements
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();
- target.setBackgroundColor(Color.argb(value, r, g, b));
+ setBackgroundColor(Color.argb(value, r, g, b));
}
});
- anim.setDuration(DOZE_BACKGROUND_ANIM_DURATION);
+ anim.setInterpolator(mDozeAnimationInterpolator);
+ anim.setDuration(DOZE_ANIMATION_DURATION);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- target.setTag(TAG_KEY_ANIM, null);
+ setTag(TAG_KEY_ANIM, null);
}
});
anim.start();
- target.setTag(TAG_KEY_ANIM, anim);
+ setTag(TAG_KEY_ANIM, anim);
}
private static int getBackgroundAlpha(View view) {
@@ -1834,4 +1900,9 @@ public class NotificationPanelView extends PanelView implements
public void onScreenTurnedOn() {
mKeyguardStatusView.refreshTime();
}
+
+ @Override
+ public void onEmptySpaceClicked(float x, float y) {
+ onEmptySpaceClick(x);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 0ddda8a3ab12..c706ef095cfa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -70,6 +70,7 @@ public abstract class PanelView extends FrameLayout {
private boolean mOverExpandedBeforeFling;
private boolean mTouchAboveFalsingThreshold;
private int mUnlockFalsingThreshold;
+ private boolean mTouchStartedInEmptyArea;
private ValueAnimator mHeightAnimator;
private ObjectAnimator mPeekAnimator;
@@ -284,7 +285,7 @@ public abstract class PanelView extends FrameLayout {
|| mInitialOffsetOnTouch == 0f)) {
mTouchSlopExceeded = true;
if (waitForTouchSlop && !mTracking) {
- if (!mJustPeeked) {
+ if (!mJustPeeked && mInitialOffsetOnTouch != 0f) {
mInitialOffsetOnTouch = mExpandedHeight;
mInitialTouchX = x;
mInitialTouchY = y;
@@ -409,6 +410,7 @@ public abstract class PanelView extends FrameLayout {
}
mInitialTouchY = y;
mInitialTouchX = x;
+ mTouchStartedInEmptyArea = !isInContentBounds(x, y);
mTouchSlopExceeded = false;
mJustPeeked = false;
mPanelClosedOnDown = mExpandedHeight == 0.0f;
@@ -432,7 +434,7 @@ public abstract class PanelView extends FrameLayout {
case MotionEvent.ACTION_MOVE:
final float h = y - mInitialTouchY;
trackMovement(event);
- if (scrolledToBottom) {
+ if (scrolledToBottom || mTouchStartedInEmptyArea) {
if (h < -mTouchSlop && h < -Math.abs(x - mInitialTouchX)) {
cancelHeightAnimator();
mInitialOffsetOnTouch = mExpandedHeight;
@@ -452,6 +454,11 @@ public abstract class PanelView extends FrameLayout {
return false;
}
+ /**
+ * @return Whether a pair of coordinates are inside the visible view content bounds.
+ */
+ protected abstract boolean isInContentBounds(float x, float y);
+
private void cancelHeightAnimator() {
if (mHeightAnimator != null) {
mHeightAnimator.cancel();
@@ -632,10 +639,10 @@ public abstract class PanelView extends FrameLayout {
}
mExpandedHeight = Math.max(0, mExpandedHeight);
- onHeightUpdated(mExpandedHeight);
mExpandedFraction = Math.min(1f, fhWithoutOverExpansion == 0
? 0
: mExpandedHeight / fhWithoutOverExpansion);
+ onHeightUpdated(mExpandedHeight);
notifyBarPanelExpansionChanged();
}
@@ -903,7 +910,7 @@ public abstract class PanelView extends FrameLayout {
*
* @return whether the panel will be expanded after the action performed by this method
*/
- private boolean onEmptySpaceClick(float x) {
+ protected boolean onEmptySpaceClick(float x) {
if (mHintAnimationRunning) {
return true;
}
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 9a33a3697198..eb487547f967 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3681,15 +3681,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mState != StatusBarState.KEYGUARD && !mNotificationPanel.isDozing()) {
return;
}
- mNotificationPanel.setDozing(mDozing);
+ mNotificationPanel.setDozing(mDozing, mScrimController.isPulsing() /*animate*/);
if (mDozing) {
- mKeyguardBottomArea.setVisibility(View.INVISIBLE);
mStackScroller.setDark(true, false /*animate*/);
} else {
- mKeyguardBottomArea.setVisibility(View.VISIBLE);
mStackScroller.setDark(false, false /*animate*/);
}
- mScrimController.setDozing(mDozing);
+ mScrimController.setDozing(mDozing, mScrimController.isPulsing() /*animate*/);
}
public void updateStackScrollerState(boolean goingToFullShade) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 54adbf482589..10d65943b9f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -28,6 +28,7 @@ import android.view.ViewTreeObserver;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
import com.android.systemui.R;
import com.android.systemui.doze.DozeHost;
@@ -70,9 +71,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
private Runnable mOnAnimationFinished;
private boolean mAnimationStarted;
private boolean mDozing;
+ private boolean mPulsingOut;
private DozeHost.PulseCallback mPulseCallback;
private final Interpolator mInterpolator = new DecelerateInterpolator();
private final Interpolator mLinearOutSlowInInterpolator;
+ private final Interpolator mPulseInInterpolator = PhoneStatusBar.ALPHA_OUT;
+ private final Interpolator mPulseOutInterpolator = PhoneStatusBar.ALPHA_IN;
private BackDropView mBackDropView;
private boolean mScrimSrcEnabled;
@@ -130,14 +134,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
scheduleUpdate();
}
- public void setDozing(boolean dozing) {
+ public void setDozing(boolean dozing, boolean animate) {
if (mDozing == dozing) return;
mDozing = dozing;
if (!mDozing) {
cancelPulsing();
- mAnimateChange = true;
- } else {
- mAnimateChange = false;
+ mAnimateChange = animate;
}
scheduleUpdate();
}
@@ -181,6 +183,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
}
private void pulseFinished() {
+ mPulsingOut = false;
if (mPulseCallback != null) {
mPulseCallback.onPulseFinished();
mPulseCallback = null;
@@ -220,8 +223,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
} else if (mBouncerShowing) {
setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA);
setScrimBehindColor(0f);
+ } else if (mDozing && isPulsing() && !mPulsingOut) {
+ setScrimInFrontColor(0);
+ setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD);
} else if (mDozing) {
setScrimInFrontColor(1);
+ setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD);
} else {
float fraction = Math.max(0, Math.min(mFraction, 1));
setScrimInFrontColor(0f);
@@ -276,7 +283,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
private void startScrimAnimation(final ScrimView scrim, int targetColor) {
int current = Color.alpha(scrim.getScrimColor());
int target = Color.alpha(targetColor);
- if (current == targetColor) {
+ if (current == target) {
return;
}
ValueAnimator anim = ValueAnimator.ofInt(current, target);
@@ -287,9 +294,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
scrim.setScrimColor(Color.argb(value, 0, 0, 0));
}
});
- anim.setInterpolator(mAnimateKeyguardFadingOut
- ? mLinearOutSlowInInterpolator
- : mInterpolator);
+ anim.setInterpolator(getInterpolator());
anim.setStartDelay(mAnimationDelay);
anim.setDuration(mDurationOverride != -1 ? mDurationOverride : ANIMATION_DURATION);
anim.addListener(new AnimatorListenerAdapter() {
@@ -307,6 +312,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
mAnimationStarted = true;
}
+ private Interpolator getInterpolator() {
+ if (mAnimateKeyguardFadingOut) {
+ return mLinearOutSlowInInterpolator;
+ } else if (isPulsing() && !mPulsingOut) {
+ return mPulseInInterpolator;
+ } else if (isPulsing()) {
+ return mPulseOutInterpolator;
+ } else {
+ return mInterpolator;
+ }
+ }
+
@Override
public boolean onPreDraw() {
mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
@@ -332,10 +349,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
if (!mDozing) return;
DozeLog.tracePulseStart();
mDurationOverride = mDozeParameters.getPulseInDuration();
- mAnimationDelay = 0;
+ mAnimationDelay = mDozeParameters.getPulseInDelay();
mAnimateChange = true;
mOnAnimationFinished = mPulseInFinished;
- setScrimColor(mScrimInFront, 0);
+ scheduleUpdate();
// Signal that the pulse is ready to turn the screen on and draw.
pulseStarted();
@@ -357,10 +374,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
if (!mDozing) return;
mDurationOverride = mDozeParameters.getPulseOutDuration();
- mAnimationDelay = 0;
mAnimateChange = true;
mOnAnimationFinished = mPulseOutFinished;
- setScrimColor(mScrimInFront, 1);
+ mPulsingOut = true;
+ scheduleUpdate();
}
};
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 4a204061144f..87ce565d5da0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -40,6 +40,7 @@ import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.SpeedBumpView;
+import com.android.systemui.statusbar.StackScrollerDecorView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.policy.ScrollAdapter;
@@ -70,6 +71,12 @@ public class NotificationStackScrollLayout extends ViewGroup
private SwipeHelper mSwipeHelper;
private boolean mSwipingInProgress;
private int mCurrentStackHeight = Integer.MAX_VALUE;
+
+ /**
+ * mCurrentStackHeight is the actual stack height, mLastSetStackHeight is the stack height set
+ * externally from {@link #setStackHeight}
+ */
+ private float mLastSetStackHeight;
private int mOwnScrollY;
private int mMaxLayoutHeight;
@@ -84,6 +91,9 @@ public class NotificationStackScrollLayout extends ViewGroup
private int mLastMotionY;
private int mDownX;
private int mActivePointerId;
+ private boolean mTouchIsClick;
+ private float mInitialTouchX;
+ private float mInitialTouchY;
private int mSidePaddings;
private Paint mDebugPaint;
@@ -133,6 +143,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private OnChildLocationsChangedListener mListener;
private OnOverscrollTopChangedListener mOverscrollTopChangedListener;
private ExpandableView.OnHeightChangedListener mOnHeightChangedListener;
+ private OnEmptySpaceClickListener mOnEmptySpaceClickListener;
private boolean mNeedsAnimation;
private boolean mTopPaddingNeedsAnimation;
private boolean mDimmedNeedsAnimation;
@@ -367,6 +378,9 @@ public class NotificationStackScrollLayout extends ViewGroup
if (childViewState == null) {
return ViewState.LOCATION_UNKNOWN;
}
+ if (childViewState.gone) {
+ return ViewState.LOCATION_GONE;
+ }
return childViewState.location;
}
@@ -445,6 +459,7 @@ public class NotificationStackScrollLayout extends ViewGroup
* @param height the new height of the stack
*/
public void setStackHeight(float height) {
+ mLastSetStackHeight = height;
setIsExpanded(height > 0.0f);
int newStackHeight = (int) height;
int minStackHeight = getMinStackHeight();
@@ -581,7 +596,9 @@ public class NotificationStackScrollLayout extends ViewGroup
final int count = getChildCount();
for (int childIdx = 0; childIdx < count; childIdx++) {
ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
- if (slidingChild.getVisibility() == GONE) {
+ if (slidingChild.getVisibility() == GONE
+ || slidingChild instanceof StackScrollerDecorView
+ || slidingChild == mSpeedBumpView) {
continue;
}
float childTop = slidingChild.getTranslationY();
@@ -687,6 +704,7 @@ public class NotificationStackScrollLayout extends ViewGroup
transformTouchEvent(ev, this, mScrollView);
return mScrollView.onTouchEvent(ev);
}
+ handleEmptySpaceClick(ev);
boolean expandWantsIt = false;
if (!mSwipingInProgress && !mOnlyScrollingInThisMotion && isScrollingEnabled()) {
if (isCancelOrUp) {
@@ -1338,7 +1356,19 @@ public class NotificationStackScrollLayout extends ViewGroup
&& initialVelocity > 0;
}
- public void updateTopPadding(float qsHeight, int scrollY, boolean animate) {
+ /**
+ * Updates the top padding of the notifications, taking {@link #getIntrinsicPadding()} into
+ * account.
+ *
+ * @param qsHeight the top padding imposed by the quick settings panel
+ * @param scrollY how much the notifications are scrolled inside the QS/notifications scroll
+ * container
+ * @param animate whether to animate the change
+ * @param ignoreIntrinsicPadding if true, {@link #getIntrinsicPadding()} is ignored and
+ * {@code qsHeight} is the final top padding
+ */
+ public void updateTopPadding(float qsHeight, int scrollY, boolean animate,
+ boolean ignoreIntrinsicPadding) {
float start = qsHeight - scrollY + mNotificationTopPadding;
float stackHeight = getHeight() - start;
int minStackHeight = getMinStackHeight();
@@ -1346,13 +1376,13 @@ public class NotificationStackScrollLayout extends ViewGroup
float overflow = minStackHeight - stackHeight;
stackHeight = minStackHeight;
start = getHeight() - stackHeight;
- setTranslationY(overflow);
mTopPaddingOverflow = overflow;
} else {
- setTranslationY(0);
mTopPaddingOverflow = 0;
}
- setTopPadding(clampPadding((int) start), animate);
+ setTopPadding(ignoreIntrinsicPadding ? (int) start : clampPadding((int) start),
+ animate);
+ setStackHeight(mLastSetStackHeight);
}
public int getNotificationTopPadding() {
@@ -1430,6 +1460,7 @@ public class NotificationStackScrollLayout extends ViewGroup
transformTouchEvent(ev, mScrollView, this);
}
initDownStates(ev);
+ handleEmptySpaceClick(ev);
boolean expandWantsIt = false;
if (!mSwipingInProgress && !mOnlyScrollingInThisMotion && isScrollingEnabled()) {
expandWantsIt = mExpandHelper.onInterceptTouchEvent(ev);
@@ -1448,11 +1479,31 @@ public class NotificationStackScrollLayout extends ViewGroup
return swipeWantsIt || scrollWantsIt || expandWantsIt || super.onInterceptTouchEvent(ev);
}
+ private void handleEmptySpaceClick(MotionEvent ev) {
+ switch (ev.getActionMasked()) {
+ case MotionEvent.ACTION_MOVE:
+ if (mTouchIsClick && (Math.abs(ev.getY() - mInitialTouchY) > mTouchSlop
+ || Math.abs(ev.getX() - mInitialTouchX) > mTouchSlop )) {
+ mTouchIsClick = false;
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD && mTouchIsClick &&
+ isBelowLastNotification(mInitialTouchX, mInitialTouchY)) {
+ mOnEmptySpaceClickListener.onEmptySpaceClicked(mInitialTouchX, mInitialTouchY);
+ }
+ break;
+ }
+ }
+
private void initDownStates(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mExpandedInThisMotion = false;
mOnlyScrollingInThisMotion = !mScroller.isFinished();
mDisallowScrollingInThisMotion = false;
+ mTouchIsClick = true;
+ mInitialTouchX = ev.getX();
+ mInitialTouchY = ev.getY();
}
}
@@ -1886,7 +1937,14 @@ public class NotificationStackScrollLayout extends ViewGroup
* @return Whether the specified motion event is actually happening over the content.
*/
private boolean isInContentBounds(MotionEvent event) {
- return event.getY() < getHeight() - getEmptyBottomMargin();
+ return isInContentBounds(event.getY());
+ }
+
+ /**
+ * @return Whether a y coordinate is inside the content.
+ */
+ public boolean isInContentBounds(float y) {
+ return y < getHeight() - getEmptyBottomMargin();
}
private void setIsBeingDragged(boolean isDragged) {
@@ -1995,6 +2053,10 @@ public class NotificationStackScrollLayout extends ViewGroup
this.mOnHeightChangedListener = mOnHeightChangedListener;
}
+ public void setOnEmptySpaceClickListener(OnEmptySpaceClickListener listener) {
+ mOnEmptySpaceClickListener = listener;
+ }
+
public void onChildAnimationFinished() {
requestChildrenUpdate();
}
@@ -2245,6 +2307,24 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ private boolean isBelowLastNotification(float touchX, float touchY) {
+ ExpandableView lastChildNotGone = (ExpandableView) getLastChildNotGone();
+ if (lastChildNotGone == null) {
+ return touchY > mIntrinsicPadding;
+ }
+ if (lastChildNotGone != mDismissView && lastChildNotGone != mEmptyShadeView) {
+ return touchY > lastChildNotGone.getY() + lastChildNotGone.getActualHeight();
+ } else if (lastChildNotGone == mEmptyShadeView) {
+ return touchY > mEmptyShadeView.getY();
+ } else {
+ float dismissY = mDismissView.getY();
+ boolean belowDismissView = touchY > dismissY + mDismissView.getActualHeight();
+ return belowDismissView || (touchY > dismissY
+ && mDismissView.isOnEmptySpace(touchX - mDismissView.getX(),
+ touchY - dismissY));
+ }
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
@@ -2253,6 +2333,13 @@ public class NotificationStackScrollLayout extends ViewGroup
}
/**
+ * A listener that is notified when the empty space below the notifications is clicked on
+ */
+ public interface OnEmptySpaceClickListener {
+ public void onEmptySpaceClicked(float x, float y);
+ }
+
+ /**
* A listener that gets notified when the overscroll at the top has changed.
*/
public interface OnOverscrollTopChangedListener {
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 853628eaf6b7..ddc425102b2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -200,15 +200,25 @@ public class StackScrollAlgorithm {
// apply clipping and shadow
float newNotificationEnd = newYTranslation + newHeight;
- // In the unlocked shade we have to clip a little bit higher because of the rounded
- // corners of the notifications.
- float clippingCorrection = state.dimmed ? 0 : mRoundedRectCornerRadius * state.scale;
-
- // When the previous notification is swiped, we don't clip the content to the
- // bottom of it.
- float clipHeight = previousNotificationIsSwiped
- ? newHeight
- : newNotificationEnd - (previousNotificationEnd - clippingCorrection);
+ float clipHeight;
+ if (previousNotificationIsSwiped) {
+ // When the previous notification is swiped, we don't clip the content to the
+ // bottom of it.
+ clipHeight = newHeight;
+ } else {
+ clipHeight = newNotificationEnd - previousNotificationEnd;
+ clipHeight = Math.max(0.0f, clipHeight);
+ if (clipHeight != 0.0f) {
+
+ // In the unlocked shade we have to clip a little bit higher because of the rounded
+ // corners of the notifications, but only if we are not fully overlapped by
+ // the top card.
+ float clippingCorrection = state.dimmed
+ ? 0
+ : mRoundedRectCornerRadius * state.scale;
+ clipHeight += clippingCorrection;
+ }
+ }
updateChildClippingAndBackground(state, newHeight, clipHeight,
newHeight - (previousNotificationStart - newYTranslation));
@@ -669,7 +679,11 @@ public class StackScrollAlgorithm {
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
if (i < algorithmState.itemsInTopStack) {
float stackIndex = algorithmState.itemsInTopStack - i;
- stackIndex = Math.min(stackIndex, MAX_ITEMS_IN_TOP_STACK + 2);
+
+ // Ensure that the topmost item is a little bit higher than the rest when fully
+ // scrolled, to avoid drawing errors when swiping it out
+ float max = MAX_ITEMS_IN_TOP_STACK + (i == 0 ? 2.5f : 2);
+ stackIndex = Math.min(stackIndex, max);
if (i == 0 && algorithmState.itemsInTopStack < 2.0f) {
// We only have the top item and an additional item in the top stack,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 0967ecd06a52..461137001b11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -119,9 +119,7 @@ public class StackScrollState {
}
// apply alpha
- if (!becomesInvisible) {
- child.setAlpha(newAlpha);
- }
+ child.setAlpha(newAlpha);
}
// apply visibility
@@ -236,6 +234,8 @@ public class StackScrollState {
public static final int LOCATION_MAIN_AREA = 0x08;
public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x10;
public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x20;
+ /** The view isn't layouted at all. */
+ public static final int LOCATION_GONE = 0x40;
float alpha;
float yTranslation;
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 433357ecb934..674642b3c437 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -477,6 +477,7 @@ public class StackStateAnimator {
if (newEndValue == 0 && !mWasCancelled) {
child.setVisibility(View.INVISIBLE);
}
+ // remove the tag when the animation is finished
child.setTag(TAG_ANIMATOR_ALPHA, null);
child.setTag(TAG_START_ALPHA, null);
child.setTag(TAG_END_ALPHA, null);
@@ -498,13 +499,7 @@ public class StackStateAnimator {
animator.setStartDelay(delay);
}
animator.addListener(getGlobalAnimationFinishedListener());
- // remove the tag when the animation is finished
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- }
- });
startAnimator(animator);
child.setTag(TAG_ANIMATOR_ALPHA, animator);
child.setTag(TAG_START_ALPHA, child.getAlpha());
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 1ed61fd22e97..4714826dee62 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -1332,6 +1332,22 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
@Override
+ public final void setElevation(float elevation) {
+ mElevation = elevation;
+ if (mDecor != null) {
+ mDecor.setElevation(elevation);
+ }
+ }
+
+ @Override
+ public final void setClipToOutline(boolean clipToOutline) {
+ mClipToOutline = clipToOutline;
+ if (mDecor != null) {
+ mDecor.setClipToOutline(clipToOutline);
+ }
+ }
+
+ @Override
public final void setBackgroundDrawable(Drawable drawable) {
if (drawable != mBackgroundDrawable || mBackgroundResource != 0) {
mBackgroundResource = 0;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 558cf56f14d6..1195ac8b41f8 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -136,8 +136,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final String TAG = "WindowManager";
static final boolean DEBUG = false;
static final boolean localLOGV = false;
- static final boolean DEBUG_LAYOUT = false;
static final boolean DEBUG_INPUT = false;
+ static final boolean DEBUG_KEYGUARD = false;
+ static final boolean DEBUG_LAYOUT = false;
static final boolean DEBUG_STARTING_WINDOW = false;
static final boolean DEBUG_WAKEUP = false;
static final boolean SHOW_STARTING_ANIMATIONS = true;
@@ -158,6 +159,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
+ static final int MULTI_PRESS_POWER_NOTHING = 0;
+ static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
+ static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
+
// These need to match the documentation/constant in
// core/res/res/values/config.xml
static final int LONG_PRESS_HOME_NOTHING = 0;
@@ -300,12 +305,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
};
GlobalActions mGlobalActions;
- volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
- boolean mPendingPowerKeyUpCanceled;
Handler mHandler;
WindowState mLastInputMethodWindow = null;
WindowState mLastInputMethodTargetWindow = null;
+ // FIXME This state is shared between the input reader and handler thread.
+ // Technically it's broken and buggy but it has been like this for many years
+ // and we have not yet seen any problems. Someday we'll rewrite this logic
+ // so that only one thread is involved in handling input policy. Unfortunately
+ // it's on a critical path for power management so we can't just post the work to the
+ // handler thread. We'll need to resolve this someday by teaching the input dispatcher
+ // to hold wakelocks during dispatch and eliminating the critical path.
+ volatile boolean mPowerKeyHandled;
+ volatile int mPowerKeyPressCounter;
+ volatile boolean mEndCallKeyHandled;
+
boolean mRecentsVisible;
int mRecentAppsHeldModifiers;
boolean mLanguageSwitchKeyPressed;
@@ -345,8 +359,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mLidKeyboardAccessibility;
int mLidNavigationAccessibility;
boolean mLidControlsSleep;
- int mShortPressOnPowerBehavior = -1;
- int mLongPressOnPowerBehavior = -1;
+ int mShortPressOnPowerBehavior;
+ int mLongPressOnPowerBehavior;
+ int mDoublePressOnPowerBehavior;
+ int mTriplePressOnPowerBehavior;
boolean mAwake;
boolean mScreenOnEarly;
boolean mScreenOnFully;
@@ -517,12 +533,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Increase the chord delay when taking a screenshot from the keyguard
private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
private boolean mScreenshotChordEnabled;
- private boolean mVolumeDownKeyTriggered;
- private long mVolumeDownKeyTime;
- private boolean mVolumeDownKeyConsumedByScreenshotChord;
- private boolean mVolumeUpKeyTriggered;
- private boolean mPowerKeyTriggered;
- private long mPowerKeyTime;
+ private boolean mScreenshotChordVolumeDownKeyTriggered;
+ private long mScreenshotChordVolumeDownKeyTime;
+ private boolean mScreenshotChordVolumeDownKeyConsumed;
+ private boolean mScreenshotChordVolumeUpKeyTriggered;
+ private boolean mScreenshotChordPowerKeyTriggered;
+ private long mScreenshotChordPowerKeyTime;
/* The number of steps between min and max brightness */
private static final int BRIGHTNESS_STEPS = 10;
@@ -530,6 +546,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
SettingsObserver mSettingsObserver;
ShortcutManager mShortcutManager;
PowerManager.WakeLock mBroadcastWakeLock;
+ PowerManager.WakeLock mPowerKeyWakeLock;
boolean mHavePendingMediaKeyRepeatWithWakeLock;
private int mCurrentUserId;
@@ -555,6 +572,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
private static final int MSG_HIDE_BOOT_MESSAGE = 11;
private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
+ private static final int MSG_POWER_DELAYED_PRESS = 13;
+ private static final int MSG_POWER_LONG_PRESS = 14;
private class PolicyHandler extends Handler {
@Override
@@ -596,6 +615,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
launchVoiceAssistWithWakeLock(msg.arg1 != 0);
break;
+ case MSG_POWER_DELAYED_PRESS:
+ powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
+ finishPowerKeyPress();
+ break;
+ case MSG_POWER_LONG_PRESS:
+ powerLongPress();
+ break;
}
}
}
@@ -789,38 +815,239 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- private void interceptPowerKeyDown(boolean handled) {
- mPowerKeyHandled = handled;
+ private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
+ // Hold a wake lock until the power key is released.
+ if (!mPowerKeyWakeLock.isHeld()) {
+ mPowerKeyWakeLock.acquire();
+ }
+
+ // Cancel multi-press detection timeout.
+ if (mPowerKeyPressCounter != 0) {
+ mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
+ }
+
+ // Detect user pressing the power button in panic when an application has
+ // taken over the whole screen.
+ boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
+ event.getDownTime(), isImmersiveMode(mLastSystemUiFlags));
+ if (panic) {
+ mHandler.post(mRequestTransientNav);
+ }
+
+ // Latch power key state to detect screenshot chord.
+ if (interactive && !mScreenshotChordPowerKeyTriggered
+ && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
+ mScreenshotChordPowerKeyTriggered = true;
+ mScreenshotChordPowerKeyTime = event.getDownTime();
+ interceptScreenshotChord();
+ }
+
+ // Stop ringing or end call if configured to do so when power is pressed.
+ TelecomManager telecomManager = getTelecommService();
+ boolean hungUp = false;
+ if (telecomManager != null) {
+ if (telecomManager.isRinging()) {
+ // Pressing Power while there's a ringing incoming
+ // call should silence the ringer.
+ telecomManager.silenceRinger();
+ } else if ((mIncallPowerBehavior
+ & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
+ && telecomManager.isInCall() && interactive) {
+ // Otherwise, if "Power button ends call" is enabled,
+ // the Power button will hang up any current active call.
+ hungUp = telecomManager.endCall();
+ }
+ }
+
+ // If the power key has still not yet been handled, then detect short
+ // press, long press, or multi press and decide what to do.
+ mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
+ || mScreenshotChordVolumeUpKeyTriggered;
+ if (!mPowerKeyHandled) {
+ if (interactive) {
+ // When interactive, we're already awake.
+ // Wait for a long press or for the button to be released to decide what to do.
+ if (hasLongPressOnPowerBehavior()) {
+ Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg,
+ ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
+ }
+ } else {
+ // When non-interactive, we ordinarily wake up immediately and
+ // consume the key. However on some devices we need to support multi-press
+ // without waking so we will delay handling for later in that case
+ // (at the cost of increased latency).
+ final int maxCount = getMaxMultiPressPowerCount();
+ if (maxCount <= 1) {
+ // No other actions. We can wake immediately.
+ wakeUpFromPowerKey(event.getDownTime());
+ mPowerKeyHandled = true;
+ }
+ }
+ }
+ }
+
+ private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
+ final boolean handled = canceled || mPowerKeyHandled;
+ mScreenshotChordPowerKeyTriggered = false;
+ cancelPendingScreenshotChordAction();
+ cancelPendingPowerKeyAction();
+
if (!handled) {
- mHandler.postDelayed(mPowerLongPress,
- ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
+ // Figure out how to handle the key now that it has been released.
+ mPowerKeyPressCounter += 1;
+
+ final int maxCount = getMaxMultiPressPowerCount();
+ final long eventTime = event.getDownTime();
+ if (mPowerKeyPressCounter < maxCount) {
+ // This could be a multi-press. Wait a little bit longer to confirm.
+ // Continue holding the wake lock.
+ Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
+ interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
+ return;
+ }
+
+ // No other actions. Handle it immediately.
+ powerPress(eventTime, interactive, mPowerKeyPressCounter);
}
+
+ // Done. Reset our state.
+ finishPowerKeyPress();
}
- private boolean interceptPowerKeyUp(boolean canceled) {
- if (!mPowerKeyHandled) {
- mHandler.removeCallbacks(mPowerLongPress);
- return !canceled;
+ private void finishPowerKeyPress() {
+ mPowerKeyPressCounter = 0;
+ if (mPowerKeyWakeLock.isHeld()) {
+ mPowerKeyWakeLock.release();
}
- return false;
}
private void cancelPendingPowerKeyAction() {
if (!mPowerKeyHandled) {
- mHandler.removeCallbacks(mPowerLongPress);
+ mPowerKeyHandled = true;
+ mHandler.removeMessages(MSG_POWER_LONG_PRESS);
+ }
+ }
+
+ private void powerPress(long eventTime, boolean interactive, int count) {
+ if (mScreenOnEarly && !mScreenOnFully) {
+ Slog.i(TAG, "Suppressed redundant power key press while "
+ + "already in the process of turning the screen on.");
+ return;
+ }
+
+ if (count == 2) {
+ powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
+ } else if (count == 3) {
+ powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
+ } else if (!interactive) {
+ wakeUpFromPowerKey(eventTime);
+ } else {
+ switch (mShortPressOnPowerBehavior) {
+ case SHORT_PRESS_POWER_NOTHING:
+ break;
+ case SHORT_PRESS_POWER_GO_TO_SLEEP:
+ mPowerManager.goToSleep(eventTime,
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
+ break;
+ case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
+ mPowerManager.goToSleep(eventTime,
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
+ PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+ break;
+ case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
+ mPowerManager.goToSleep(eventTime,
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
+ PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+ launchHomeFromHotKey();
+ break;
+ }
+ }
+ }
+
+ private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
+ switch (behavior) {
+ case MULTI_PRESS_POWER_NOTHING:
+ break;
+ case MULTI_PRESS_POWER_THEATER_MODE:
+ if (isTheaterModeEnabled()) {
+ Slog.i(TAG, "Toggling theater mode off.");
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.THEATER_MODE_ON, 0);
+ if (!interactive) {
+ wakeUpFromPowerKey(eventTime);
+ }
+ } else {
+ Slog.i(TAG, "Toggling theater mode on.");
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.THEATER_MODE_ON, 1);
+ if (interactive) {
+ mPowerManager.goToSleep(eventTime,
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
+ }
+ }
+ break;
+ case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
+ mPowerManager.boostScreenBrightness(eventTime);
+ break;
+ }
+ }
+
+ private int getMaxMultiPressPowerCount() {
+ if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
+ return 3;
}
- if (mPowerKeyTriggered) {
- mPendingPowerKeyUpCanceled = true;
+ if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
+ return 2;
}
+ return 1;
+ }
+
+ private void powerLongPress() {
+ final int behavior = getResolvedLongPressOnPowerBehavior();
+ switch (behavior) {
+ case LONG_PRESS_POWER_NOTHING:
+ break;
+ case LONG_PRESS_POWER_GLOBAL_ACTIONS:
+ mPowerKeyHandled = true;
+ if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
+ performAuditoryFeedbackForAccessibilityIfNeed();
+ }
+ showGlobalActionsInternal();
+ break;
+ case LONG_PRESS_POWER_SHUT_OFF:
+ case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
+ mPowerKeyHandled = true;
+ performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+ sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
+ mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
+ break;
+ }
+ }
+
+ private int getResolvedLongPressOnPowerBehavior() {
+ if (FactoryTest.isLongPressOnPowerOffEnabled()) {
+ return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
+ }
+ return mLongPressOnPowerBehavior;
+ }
+
+ private boolean hasLongPressOnPowerBehavior() {
+ return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
}
private void interceptScreenshotChord() {
if (mScreenshotChordEnabled
- && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
+ && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
+ && !mScreenshotChordVolumeUpKeyTriggered) {
final long now = SystemClock.uptimeMillis();
- if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
- && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
- mVolumeDownKeyConsumedByScreenshotChord = true;
+ if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
+ && now <= mScreenshotChordPowerKeyTime
+ + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
+ mScreenshotChordVolumeDownKeyConsumed = true;
cancelPendingPowerKeyAction();
mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
@@ -841,64 +1068,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHandler.removeCallbacks(mScreenshotRunnable);
}
- private void powerShortPress(long eventTime) {
- if (mShortPressOnPowerBehavior < 0) {
- mShortPressOnPowerBehavior = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_shortPressOnPowerBehavior);
- }
-
- switch (mShortPressOnPowerBehavior) {
- case SHORT_PRESS_POWER_NOTHING:
- break;
- case SHORT_PRESS_POWER_GO_TO_SLEEP:
- mPowerManager.goToSleep(eventTime,
- PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
- break;
- case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
- mPowerManager.goToSleep(eventTime,
- PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
- PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
- break;
- case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
- mPowerManager.goToSleep(eventTime,
- PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
- PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
- launchHomeFromHotKey();
- break;
- }
- }
-
- private final Runnable mPowerLongPress = new Runnable() {
+ private final Runnable mEndCallLongPress = new Runnable() {
@Override
public void run() {
- // The context isn't read
- if (mLongPressOnPowerBehavior < 0) {
- mLongPressOnPowerBehavior = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_longPressOnPowerBehavior);
- }
- int resolvedBehavior = mLongPressOnPowerBehavior;
- if (FactoryTest.isLongPressOnPowerOffEnabled()) {
- resolvedBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
- }
-
- switch (resolvedBehavior) {
- case LONG_PRESS_POWER_NOTHING:
- break;
- case LONG_PRESS_POWER_GLOBAL_ACTIONS:
- mPowerKeyHandled = true;
- if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
- performAuditoryFeedbackForAccessibilityIfNeed();
- }
- showGlobalActionsInternal();
- break;
- case LONG_PRESS_POWER_SHUT_OFF:
- case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
- mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
- mWindowManagerFuncs.shutdown(resolvedBehavior == LONG_PRESS_POWER_SHUT_OFF);
- break;
+ mEndCallKeyHandled = true;
+ if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
+ performAuditoryFeedbackForAccessibilityIfNeed();
}
+ showGlobalActionsInternal();
}
};
@@ -939,6 +1116,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
}
+ private void handleShortPressOnHome() {
+ // If there's a dream running then use home to escape the dream
+ // but don't actually go home.
+ if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
+ mDreamManagerInternal.stopDream(false /*immediate*/);
+ return;
+ }
+
+ // Go home!
+ launchHomeFromHotKey();
+ }
+
private void handleLongPressOnHome() {
if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
mHomeConsumed = true;
@@ -964,7 +1153,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void run() {
if (mHomeDoubleTapPending) {
mHomeDoubleTapPending = false;
- launchHomeFromHotKey();
+ handleShortPressOnHome();
}
}
};
@@ -1007,6 +1196,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"PhoneWindowManager.mBroadcastWakeLock");
+ mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ "PhoneWindowManager.mPowerKeyWakeLock");
mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
mSupportAutoRotation = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_supportAutoRotation);
@@ -1045,6 +1236,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
+ mShortPressOnPowerBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_shortPressOnPowerBehavior);
+ mLongPressOnPowerBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_longPressOnPowerBehavior);
+ mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_doublePressOnPowerBehavior);
+ mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_triplePressOnPowerBehavior);
+
readConfigurationDependentBehaviors();
mAccessibilityManager = (AccessibilityManager) context.getSystemService(
@@ -2188,17 +2388,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// but we're not sure, then tell the dispatcher to wait a little while and
// try again later before dispatching.
if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
- if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
+ if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
final long now = SystemClock.uptimeMillis();
- final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
+ final long timeoutTime = mScreenshotChordVolumeDownKeyTime
+ + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
if (now < timeoutTime) {
return timeoutTime - now;
}
}
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
- && mVolumeDownKeyConsumedByScreenshotChord) {
+ && mScreenshotChordVolumeDownKeyConsumed) {
if (!down) {
- mVolumeDownKeyConsumedByScreenshotChord = false;
+ mScreenshotChordVolumeDownKeyConsumed = false;
}
return -1;
}
@@ -2241,15 +2442,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return -1;
}
- // If there's a dream running then use home to escape the dream
- // but don't actually go home.
- if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
- mDreamManagerInternal.stopDream(false /*immediate*/);
- return -1;
- }
-
- // Go home!
- launchHomeFromHotKey();
+ handleShortPressOnHome();
return -1;
}
@@ -2523,7 +2716,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return -1;
}
- if (mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
+ if (isValidGlobalKey(keyCode)
+ && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
return -1;
}
@@ -4289,10 +4483,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// If the key would be handled globally, just return the result, don't worry about special
// key processing.
- if (mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
+ if (isValidGlobalKey(keyCode)
+ && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
if (isWakeKey) {
- wakeUp(event.getEventTime(), keyCode == KeyEvent.KEYCODE_POWER
- ? mAllowTheaterModeWakeFromPowerKey : mAllowTheaterModeWakeFromKey);
+ wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
}
return result;
}
@@ -4308,28 +4502,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_VOLUME_MUTE: {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (down) {
- if (interactive && !mVolumeDownKeyTriggered
+ if (interactive && !mScreenshotChordVolumeDownKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
- mVolumeDownKeyTriggered = true;
- mVolumeDownKeyTime = event.getDownTime();
- mVolumeDownKeyConsumedByScreenshotChord = false;
+ mScreenshotChordVolumeDownKeyTriggered = true;
+ mScreenshotChordVolumeDownKeyTime = event.getDownTime();
+ mScreenshotChordVolumeDownKeyConsumed = false;
cancelPendingPowerKeyAction();
interceptScreenshotChord();
}
} else {
- mVolumeDownKeyTriggered = false;
+ mScreenshotChordVolumeDownKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
if (down) {
- if (interactive && !mVolumeUpKeyTriggered
+ if (interactive && !mScreenshotChordVolumeUpKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
- mVolumeUpKeyTriggered = true;
+ mScreenshotChordVolumeUpKeyTriggered = true;
cancelPendingPowerKeyAction();
cancelPendingScreenshotChordAction();
}
} else {
- mVolumeUpKeyTriggered = false;
+ mScreenshotChordVolumeUpKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
}
@@ -4386,20 +4580,29 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (telecomManager != null) {
hungUp = telecomManager.endCall();
}
- interceptPowerKeyDown(!interactive || hungUp);
+ if (interactive && !hungUp) {
+ mEndCallKeyHandled = false;
+ mHandler.postDelayed(mEndCallLongPress,
+ ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
+ } else {
+ mEndCallKeyHandled = true;
+ }
} else {
- if (interceptPowerKeyUp(canceled)) {
- if ((mEndcallBehavior
- & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
- if (goHome()) {
- break;
+ if (!mEndCallKeyHandled) {
+ mHandler.removeCallbacks(mEndCallLongPress);
+ if (!canceled) {
+ if ((mEndcallBehavior
+ & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
+ if (goHome()) {
+ break;
+ }
+ }
+ if ((mEndcallBehavior
+ & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
+ mPowerManager.goToSleep(event.getEventTime(),
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
+ isWakeKey = false;
}
- }
- if ((mEndcallBehavior
- & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
- mPowerManager.goToSleep(event.getEventTime(),
- PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
- isWakeKey = false;
}
}
}
@@ -4408,49 +4611,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
+ isWakeKey = false; // wake-up will be handled separately
if (down) {
- boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
- event.getDownTime(), isImmersiveMode(mLastSystemUiFlags));
- if (panic) {
- mHandler.post(mRequestTransientNav);
- }
- if (interactive && !mPowerKeyTriggered
- && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
- mPowerKeyTriggered = true;
- mPowerKeyTime = event.getDownTime();
- interceptScreenshotChord();
- }
-
- TelecomManager telecomManager = getTelecommService();
- boolean hungUp = false;
- if (telecomManager != null) {
- if (telecomManager.isRinging()) {
- // Pressing Power while there's a ringing incoming
- // call should silence the ringer.
- telecomManager.silenceRinger();
- } else if ((mIncallPowerBehavior
- & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
- && telecomManager.isInCall() && interactive) {
- // Otherwise, if "Power button ends call" is enabled,
- // the Power button will hang up any current active call.
- hungUp = telecomManager.endCall();
- }
- }
- interceptPowerKeyDown(!interactive || hungUp
- || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
+ interceptPowerKeyDown(event, interactive);
} else {
- mPowerKeyTriggered = false;
- cancelPendingScreenshotChordAction();
- if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
- if (mScreenOnEarly && !mScreenOnFully) {
- Slog.i(TAG, "Suppressed redundant power key press while "
- + "already in the process of turning the screen on.");
- } else {
- powerShortPress(event.getEventTime());
- }
- isWakeKey = false;
- }
- mPendingPowerKeyUpCanceled = false;
+ interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
@@ -4541,14 +4706,29 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if (isWakeKey) {
- wakeUp(event.getEventTime(), keyCode == KeyEvent.KEYCODE_POWER
- ? mAllowTheaterModeWakeFromPowerKey : mAllowTheaterModeWakeFromKey);
+ wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
}
return result;
}
/**
+ * Returns true if the key can have global actions attached to it.
+ * We reserve all power management keys for the system since they require
+ * very careful handling.
+ */
+ private static boolean isValidGlobalKey(int keyCode) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_POWER:
+ case KeyEvent.KEYCODE_WAKEUP:
+ case KeyEvent.KEYCODE_SLEEP:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ /**
* When the screen is off we ignore some keys that might otherwise typically
* be considered wake keys. We filter them out here.
*
@@ -4765,6 +4945,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private void wakeUpFromPowerKey(long eventTime) {
+ wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey);
+ }
+
private void wakeUp(long wakeTime, boolean wakeInTheaterMode) {
if (!wakeInTheaterMode && isTheaterModeEnabled()) {
return;
@@ -4981,6 +5165,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void dismissKeyguardLw() {
if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -5012,6 +5197,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
if (mKeyguardDelegate != null) {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
}
}
@@ -5352,7 +5538,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return true;
}
};
- mBootMsgDialog.setTitle(R.string.android_upgrading_title);
+ if (mContext.getPackageManager().isUpgrade()) {
+ mBootMsgDialog.setTitle(R.string.android_upgrading_title);
+ } else {
+ mBootMsgDialog.setTitle(R.string.android_start_title);
+ }
mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mBootMsgDialog.setIndeterminate(true);
mBootMsgDialog.getWindow().setType(
@@ -5979,6 +6169,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(prefix);
pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
+ pw.print(prefix);
+ pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
+ pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 1623eac6ac9e..edea274c155f 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -774,7 +774,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (defIm == null && mMethodList.size() > 0) {
defIm = InputMethodUtils.getMostApplicableDefaultIME(
mSettings.getEnabledInputMethodListLocked());
- Slog.i(TAG, "No default found, using " + defIm.getId());
+ if (defIm != null) {
+ Slog.i(TAG, "Default found, using " + defIm.getId());
+ } else {
+ Slog.i(TAG, "No default found");
+ }
}
if (defIm != null) {
setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index d03a15458b69..0f033d71bbc9 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -940,6 +940,17 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
@Override
+ public void setInterfaceIpv6NdOffload(String iface, boolean enable) {
+ mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+ try {
+ mConnector.execute(
+ "interface", "ipv6ndoffload", iface, (enable ? "enable" : "disable"));
+ } catch (NativeDaemonConnectorException e) {
+ throw e.rethrowAsParcelableException();
+ }
+ }
+
+ @Override
public void addRoute(int netId, RouteInfo route) {
modifyRoute("add", "" + netId, route);
}
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index d4c436f6c8f5..5add88eaa63c 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.PackageMonitor;
import com.android.internal.textservice.ISpellCheckerService;
import com.android.internal.textservice.ISpellCheckerSession;
@@ -28,14 +29,18 @@ import org.xmlpull.v1.XmlPullParserException;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.IUserSwitchObserver;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -43,6 +48,7 @@ import android.os.IRemoteCallback;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.service.textservice.SpellCheckerService;
import android.text.TextUtils;
@@ -84,6 +90,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
public TextServicesManagerService(Context context) {
mSystemReady = false;
mContext = context;
+
+ final IntentFilter broadcastFilter = new IntentFilter();
+ broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
+ broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiver(new TextServicesBroadcastReceiver(), broadcastFilter);
+
int userId = UserHandle.USER_OWNER;
try {
ActivityManagerNative.getDefault().registerUserSwitchObserver(
@@ -119,6 +131,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
private void switchUserLocked(int userId) {
mSettings.setCurrentUserId(userId);
+ updateCurrentProfileIds();
unbindServiceLocked();
buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings);
SpellCheckerInfo sci = getCurrentSpellChecker(null);
@@ -133,6 +146,16 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
}
+ void updateCurrentProfileIds() {
+ List<UserInfo> profiles =
+ UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
+ int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
+ for (int i = 0; i < currentProfileIds.length; i++) {
+ currentProfileIds[i] = profiles.get(i).id;
+ }
+ mSettings.setCurrentProfileIds(currentProfileIds);
+ }
+
private class TextServicesMonitor extends PackageMonitor {
private boolean isChangingPackagesOfCurrentUser() {
final int userId = getChangingUserId();
@@ -171,6 +194,19 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
}
+ class TextServicesBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_USER_ADDED.equals(action)
+ || Intent.ACTION_USER_REMOVED.equals(action)) {
+ updateCurrentProfileIds();
+ return;
+ }
+ Slog.w(TAG, "Unexpected intent " + intent);
+ }
+ }
+
private static void buildSpellCheckerMapLocked(Context context,
ArrayList<SpellCheckerInfo> list, HashMap<String, SpellCheckerInfo> map,
TextServicesSettings settings) {
@@ -223,7 +259,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
+ "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
+ " calling userId = " + userId + ", foreground user id = "
- + mSettings.getCurrentUserId());
+ + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid());
try {
final String[] packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
for (int i = 0; i < packageNames.length; ++i) {
@@ -237,10 +273,40 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
if (uid == Process.SYSTEM_UID || userId == mSettings.getCurrentUserId()) {
return true;
- } else {
- Slog.w(TAG, "--- IPC called from background users. Ignore. \n" + getStackTrace());
- return false;
}
+
+ // Permits current profile to use TSFM as long as the current text service is the system's
+ // one. This is a tentative solution and should be replaced with fully functional multiuser
+ // support.
+ // TODO: Implement multiuser support in TSMS.
+ final boolean isCurrentProfile = mSettings.isCurrentProfile(userId);
+ if (DBG) {
+ Slog.d(TAG, "--- userId = "+ userId + " isCurrentProfile = " + isCurrentProfile);
+ }
+ if (mSettings.isCurrentProfile(userId)) {
+ final SpellCheckerInfo spellCheckerInfo = getCurrentSpellCheckerWithoutVerification();
+ if (spellCheckerInfo != null) {
+ final ServiceInfo serviceInfo = spellCheckerInfo.getServiceInfo();
+ final boolean isSystemSpellChecker =
+ (serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ if (DBG) {
+ Slog.d(TAG, "--- current spell checker = "+ spellCheckerInfo.getPackageName()
+ + " isSystem = " + isSystemSpellChecker);
+ }
+ if (isSystemSpellChecker) {
+ return true;
+ }
+ }
+ }
+
+ // Unlike InputMethodManagerService#calledFromValidUser, INTERACT_ACROSS_USERS_FULL isn't
+ // taken into account here. Anyway this method is supposed to be removed once multiuser
+ // support is implemented.
+ if (DBG) {
+ Slog.d(TAG, "--- IPC from userId:" + userId + " is being ignored. \n"
+ + getStackTrace());
+ }
+ return false;
}
private boolean bindCurrentSpellCheckerService(
@@ -292,6 +358,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
if (!calledFromValidUser()) {
return null;
}
+ return getCurrentSpellCheckerWithoutVerification();
+ }
+
+ private SpellCheckerInfo getCurrentSpellCheckerWithoutVerification() {
synchronized (mSpellCheckerMap) {
final String curSpellCheckerId = mSettings.getSelectedSpellChecker();
if (DBG) {
@@ -914,6 +984,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
private static class TextServicesSettings {
private final ContentResolver mResolver;
private int mCurrentUserId;
+ @GuardedBy("mLock")
+ private int[] mCurrentProfileIds = new int[0];
+ private Object mLock = new Object();
+
public TextServicesSettings(ContentResolver resolver, int userId) {
mResolver = resolver;
mCurrentUserId = userId;
@@ -928,6 +1002,22 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
mCurrentUserId = userId;
}
+ public void setCurrentProfileIds(int[] currentProfileIds) {
+ synchronized (mLock) {
+ mCurrentProfileIds = currentProfileIds;
+ }
+ }
+
+ public boolean isCurrentProfile(int userId) {
+ synchronized (mLock) {
+ if (userId == mCurrentUserId) return true;
+ for (int i = 0; i < mCurrentProfileIds.length; i++) {
+ if (userId == mCurrentProfileIds[i]) return true;
+ }
+ return false;
+ }
+ }
+
public int getCurrentUserId() {
return mCurrentUserId;
}
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 89e3f49ef7ff..8e46c4dfb223 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -415,15 +415,9 @@ public class Watchdog extends Thread {
dumpKernelStackTraces();
}
- // Trigger the kernel to dump all blocked threads to the kernel log
- try {
- FileWriter sysrq_trigger = new FileWriter("/proc/sysrq-trigger");
- sysrq_trigger.write("w");
- sysrq_trigger.close();
- } catch (IOException e) {
- Slog.e(TAG, "Failed to write to /proc/sysrq-trigger");
- Slog.e(TAG, e.getMessage());
- }
+ // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log
+ doSysRq('w');
+ doSysRq('l');
// Try to add the error to the dropbox, but assuming that the ActivityManager
// itself may be deadlocked. (which has happened, causing this statement to
@@ -488,6 +482,16 @@ public class Watchdog extends Thread {
}
}
+ private void doSysRq(char c) {
+ try {
+ FileWriter sysrq_trigger = new FileWriter("/proc/sysrq-trigger");
+ sysrq_trigger.write(c);
+ sysrq_trigger.close();
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to write to /proc/sysrq-trigger", e);
+ }
+ }
+
private File dumpKernelStackTraces() {
String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
if (tracesPath == null || tracesPath.length() == 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9f1ce0b44501..9179cc494f35 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1606,197 +1606,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final ArrayList<ProcessMemInfo> memInfos = (ArrayList<ProcessMemInfo>)msg.obj;
Thread thread = new Thread() {
@Override public void run() {
- final SparseArray<ProcessMemInfo> infoMap
- = new SparseArray<ProcessMemInfo>(memInfos.size());
- for (int i=0, N=memInfos.size(); i<N; i++) {
- ProcessMemInfo mi = memInfos.get(i);
- infoMap.put(mi.pid, mi);
- }
- updateCpuStatsNow();
- synchronized (mProcessCpuTracker) {
- final int N = mProcessCpuTracker.countStats();
- for (int i=0; i<N; i++) {
- ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
- if (st.vsize > 0) {
- long pss = Debug.getPss(st.pid, null);
- if (pss > 0) {
- if (infoMap.indexOfKey(st.pid) < 0) {
- ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid,
- ProcessList.NATIVE_ADJ, -1, "native", null);
- mi.pss = pss;
- memInfos.add(mi);
- }
- }
- }
- }
- }
-
- long totalPss = 0;
- for (int i=0, N=memInfos.size(); i<N; i++) {
- ProcessMemInfo mi = memInfos.get(i);
- if (mi.pss == 0) {
- mi.pss = Debug.getPss(mi.pid, null);
- }
- totalPss += mi.pss;
- }
- Collections.sort(memInfos, new Comparator<ProcessMemInfo>() {
- @Override public int compare(ProcessMemInfo lhs, ProcessMemInfo rhs) {
- if (lhs.oomAdj != rhs.oomAdj) {
- return lhs.oomAdj < rhs.oomAdj ? -1 : 1;
- }
- if (lhs.pss != rhs.pss) {
- return lhs.pss < rhs.pss ? 1 : -1;
- }
- return 0;
- }
- });
-
- StringBuilder tag = new StringBuilder(128);
- StringBuilder stack = new StringBuilder(128);
- tag.append("Low on memory -- ");
- appendMemBucket(tag, totalPss, "total", false);
- appendMemBucket(stack, totalPss, "total", true);
-
- StringBuilder logBuilder = new StringBuilder(1024);
- logBuilder.append("Low on memory:\n");
-
- boolean firstLine = true;
- int lastOomAdj = Integer.MIN_VALUE;
- for (int i=0, N=memInfos.size(); i<N; i++) {
- ProcessMemInfo mi = memInfos.get(i);
-
- if (mi.oomAdj != ProcessList.NATIVE_ADJ
- && (mi.oomAdj < ProcessList.SERVICE_ADJ
- || mi.oomAdj == ProcessList.HOME_APP_ADJ
- || mi.oomAdj == ProcessList.PREVIOUS_APP_ADJ)) {
- if (lastOomAdj != mi.oomAdj) {
- lastOomAdj = mi.oomAdj;
- if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) {
- tag.append(" / ");
- }
- if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ) {
- if (firstLine) {
- stack.append(":");
- firstLine = false;
- }
- stack.append("\n\t at ");
- } else {
- stack.append("$");
- }
- } else {
- tag.append(" ");
- stack.append("$");
- }
- if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) {
- appendMemBucket(tag, mi.pss, mi.name, false);
- }
- appendMemBucket(stack, mi.pss, mi.name, true);
- if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ
- && ((i+1) >= N || memInfos.get(i+1).oomAdj != lastOomAdj)) {
- stack.append("(");
- for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
- if (DUMP_MEM_OOM_ADJ[k] == mi.oomAdj) {
- stack.append(DUMP_MEM_OOM_LABEL[k]);
- stack.append(":");
- stack.append(DUMP_MEM_OOM_ADJ[k]);
- }
- }
- stack.append(")");
- }
- }
-
- logBuilder.append(" ");
- logBuilder.append(ProcessList.makeOomAdjString(mi.oomAdj));
- logBuilder.append(' ');
- logBuilder.append(ProcessList.makeProcStateString(mi.procState));
- logBuilder.append(' ');
- ProcessList.appendRamKb(logBuilder, mi.pss);
- logBuilder.append(" kB: ");
- logBuilder.append(mi.name);
- logBuilder.append(" (");
- logBuilder.append(mi.pid);
- logBuilder.append(") ");
- logBuilder.append(mi.adjType);
- logBuilder.append('\n');
- if (mi.adjReason != null) {
- logBuilder.append(" ");
- logBuilder.append(mi.adjReason);
- logBuilder.append('\n');
- }
- }
-
- logBuilder.append(" ");
- ProcessList.appendRamKb(logBuilder, totalPss);
- logBuilder.append(" kB: TOTAL\n");
-
- long[] infos = new long[Debug.MEMINFO_COUNT];
- Debug.getMemInfo(infos);
- logBuilder.append(" MemInfo: ");
- logBuilder.append(infos[Debug.MEMINFO_SLAB]).append(" kB slab, ");
- logBuilder.append(infos[Debug.MEMINFO_SHMEM]).append(" kB shmem, ");
- logBuilder.append(infos[Debug.MEMINFO_VM_ALLOC_USED]).append(" kB vm alloc, ");
- logBuilder.append(infos[Debug.MEMINFO_PAGE_TABLES]).append(" kB page tables ");
- logBuilder.append(infos[Debug.MEMINFO_KERNEL_STACK]).append(" kB kernel stack\n");
- logBuilder.append(" ");
- logBuilder.append(infos[Debug.MEMINFO_BUFFERS]).append(" kB buffers, ");
- logBuilder.append(infos[Debug.MEMINFO_CACHED]).append(" kB cached, ");
- logBuilder.append(infos[Debug.MEMINFO_MAPPED]).append(" kB mapped, ");
- logBuilder.append(infos[Debug.MEMINFO_FREE]).append(" kB free\n");
- if (infos[Debug.MEMINFO_ZRAM_TOTAL] != 0) {
- logBuilder.append(" ZRAM: ");
- logBuilder.append(infos[Debug.MEMINFO_ZRAM_TOTAL]);
- logBuilder.append(" kB RAM, ");
- logBuilder.append(infos[Debug.MEMINFO_SWAP_TOTAL]);
- logBuilder.append(" kB swap total, ");
- logBuilder.append(infos[Debug.MEMINFO_SWAP_FREE]);
- logBuilder.append(" kB swap free\n");
- }
- Slog.i(TAG, logBuilder.toString());
-
- StringBuilder dropBuilder = new StringBuilder(1024);
- /*
- StringWriter oomSw = new StringWriter();
- PrintWriter oomPw = new FastPrintWriter(oomSw, false, 256);
- StringWriter catSw = new StringWriter();
- PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
- String[] emptyArgs = new String[] { };
- dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw);
- oomPw.flush();
- String oomString = oomSw.toString();
- */
- dropBuilder.append(stack);
- dropBuilder.append('\n');
- dropBuilder.append('\n');
- dropBuilder.append(logBuilder);
- dropBuilder.append('\n');
- /*
- dropBuilder.append(oomString);
- dropBuilder.append('\n');
- */
- StringWriter catSw = new StringWriter();
- synchronized (ActivityManagerService.this) {
- PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
- String[] emptyArgs = new String[] { };
- catPw.println();
- dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
- catPw.println();
- mServices.dumpServicesLocked(null, catPw, emptyArgs, 0,
- false, false, null);
- catPw.println();
- dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
- catPw.flush();
- }
- dropBuilder.append(catSw.toString());
- addErrorToDropBox("lowmem", null, "system_server", null,
- null, tag.toString(), dropBuilder.toString(), null, null);
- //Slog.i(TAG, "Sent to dropbox:");
- //Slog.i(TAG, dropBuilder.toString());
- synchronized (ActivityManagerService.this) {
- long now = SystemClock.uptimeMillis();
- if (mLastMemUsageReportTime < now) {
- mLastMemUsageReportTime = now;
- }
- }
+ reportMemUsage(memInfos);
}
};
thread.start();
@@ -13927,6 +13737,35 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ private static final int KSM_SHARED = 0;
+ private static final int KSM_SHARING = 1;
+ private static final int KSM_UNSHARED = 2;
+ private static final int KSM_VOLATILE = 3;
+
+ private final long[] getKsmInfo() {
+ long[] longOut = new long[4];
+ final int[] SINGLE_LONG_FORMAT = new int[] {
+ Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG
+ };
+ long[] longTmp = new long[1];
+ Process.readProcFile("/sys/kernel/mm/ksm/pages_shared",
+ SINGLE_LONG_FORMAT, null, longTmp, null);
+ longOut[KSM_SHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
+ longTmp[0] = 0;
+ Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing",
+ SINGLE_LONG_FORMAT, null, longTmp, null);
+ longOut[KSM_SHARING] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
+ longTmp[0] = 0;
+ Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared",
+ SINGLE_LONG_FORMAT, null, longTmp, null);
+ longOut[KSM_UNSHARED] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
+ longTmp[0] = 0;
+ Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile",
+ SINGLE_LONG_FORMAT, null, longTmp, null);
+ longOut[KSM_VOLATILE] = longTmp[0] * ProcessList.PAGE_SIZE / 1024;
+ return longOut;
+ }
+
final void dumpApplicationMemoryUsage(FileDescriptor fd,
PrintWriter pw, String prefix, String[] args, boolean brief, PrintWriter categoryPw) {
boolean dumpDetails = false;
@@ -14272,7 +14111,7 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.print(" Free RAM: "); pw.print(cachedPss + memInfo.getCachedSizeKb()
+ memInfo.getFreeSizeKb()); pw.print(" kB (");
pw.print(cachedPss); pw.print(" cached pss + ");
- pw.print(memInfo.getCachedSizeKb()); pw.print(" cached + ");
+ pw.print(memInfo.getCachedSizeKb()); pw.print(" cached kernel + ");
pw.print(memInfo.getFreeSizeKb()); pw.println(" free)");
} else {
pw.print("ram,"); pw.print(memInfo.getTotalSizeKb()); pw.print(",");
@@ -14306,32 +14145,16 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.println(memInfo.getSwapFreeSizeKb());
}
}
- final int[] SINGLE_LONG_FORMAT = new int[] {
- Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG
- };
- long[] longOut = new long[1];
- Process.readProcFile("/sys/kernel/mm/ksm/pages_shared",
- SINGLE_LONG_FORMAT, null, longOut, null);
- long shared = longOut[0] * ProcessList.PAGE_SIZE / 1024;
- longOut[0] = 0;
- Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing",
- SINGLE_LONG_FORMAT, null, longOut, null);
- long sharing = longOut[0] * ProcessList.PAGE_SIZE / 1024;
- longOut[0] = 0;
- Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared",
- SINGLE_LONG_FORMAT, null, longOut, null);
- long unshared = longOut[0] * ProcessList.PAGE_SIZE / 1024;
- longOut[0] = 0;
- Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile",
- SINGLE_LONG_FORMAT, null, longOut, null);
- long voltile = longOut[0] * ProcessList.PAGE_SIZE / 1024;
+ final long[] ksm = getKsmInfo();
if (!isCompact) {
- if (sharing != 0 || shared != 0 || unshared != 0 || voltile != 0) {
- pw.print(" KSM: "); pw.print(sharing);
+ if (ksm[KSM_SHARING] != 0 || ksm[KSM_SHARED] != 0 || ksm[KSM_UNSHARED] != 0
+ || ksm[KSM_VOLATILE] != 0) {
+ pw.print(" KSM: "); pw.print(ksm[KSM_SHARING]);
pw.print(" kB saved from shared ");
- pw.print(shared); pw.println(" kB");
- pw.print(" "); pw.print(unshared); pw.print(" kB unshared; ");
- pw.print(voltile); pw.println(" kB volatile");
+ pw.print(ksm[KSM_SHARED]); pw.println(" kB");
+ pw.print(" "); pw.print(ksm[KSM_UNSHARED]);
+ pw.print(" kB unshared; ");
+ pw.print(ksm[KSM_VOLATILE]); pw.println(" kB volatile");
}
pw.print(" Tuning: ");
pw.print(ActivityManager.staticGetMemoryClass());
@@ -14351,9 +14174,9 @@ public final class ActivityManagerService extends ActivityManagerNative
}
pw.println();
} else {
- pw.print("ksm,"); pw.print(sharing); pw.print(",");
- pw.print(shared); pw.print(","); pw.print(unshared); pw.print(",");
- pw.println(voltile);
+ pw.print("ksm,"); pw.print(ksm[KSM_SHARING]); pw.print(",");
+ pw.print(ksm[KSM_SHARED]); pw.print(","); pw.print(ksm[KSM_UNSHARED]);
+ pw.print(","); pw.println(ksm[KSM_VOLATILE]);
pw.print("tuning,");
pw.print(ActivityManager.staticGetMemoryClass());
pw.print(',');
@@ -14372,6 +14195,265 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ private void appendBasicMemEntry(StringBuilder sb, int oomAdj, int procState, long pss,
+ String name) {
+ sb.append(" ");
+ sb.append(ProcessList.makeOomAdjString(oomAdj));
+ sb.append(' ');
+ sb.append(ProcessList.makeProcStateString(procState));
+ sb.append(' ');
+ ProcessList.appendRamKb(sb, pss);
+ sb.append(" kB: ");
+ sb.append(name);
+ }
+
+ private void appendMemInfo(StringBuilder sb, ProcessMemInfo mi) {
+ appendBasicMemEntry(sb, mi.oomAdj, mi.procState, mi.pss, mi.name);
+ sb.append(" (");
+ sb.append(mi.pid);
+ sb.append(") ");
+ sb.append(mi.adjType);
+ sb.append('\n');
+ if (mi.adjReason != null) {
+ sb.append(" ");
+ sb.append(mi.adjReason);
+ sb.append('\n');
+ }
+ }
+
+ void reportMemUsage(ArrayList<ProcessMemInfo> memInfos) {
+ final SparseArray<ProcessMemInfo> infoMap = new SparseArray<>(memInfos.size());
+ for (int i=0, N=memInfos.size(); i<N; i++) {
+ ProcessMemInfo mi = memInfos.get(i);
+ infoMap.put(mi.pid, mi);
+ }
+ updateCpuStatsNow();
+ synchronized (mProcessCpuTracker) {
+ final int N = mProcessCpuTracker.countStats();
+ for (int i=0; i<N; i++) {
+ ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
+ if (st.vsize > 0) {
+ long pss = Debug.getPss(st.pid, null);
+ if (pss > 0) {
+ if (infoMap.indexOfKey(st.pid) < 0) {
+ ProcessMemInfo mi = new ProcessMemInfo(st.name, st.pid,
+ ProcessList.NATIVE_ADJ, -1, "native", null);
+ mi.pss = pss;
+ memInfos.add(mi);
+ }
+ }
+ }
+ }
+ }
+
+ long totalPss = 0;
+ for (int i=0, N=memInfos.size(); i<N; i++) {
+ ProcessMemInfo mi = memInfos.get(i);
+ if (mi.pss == 0) {
+ mi.pss = Debug.getPss(mi.pid, null);
+ }
+ totalPss += mi.pss;
+ }
+ Collections.sort(memInfos, new Comparator<ProcessMemInfo>() {
+ @Override public int compare(ProcessMemInfo lhs, ProcessMemInfo rhs) {
+ if (lhs.oomAdj != rhs.oomAdj) {
+ return lhs.oomAdj < rhs.oomAdj ? -1 : 1;
+ }
+ if (lhs.pss != rhs.pss) {
+ return lhs.pss < rhs.pss ? 1 : -1;
+ }
+ return 0;
+ }
+ });
+
+ StringBuilder tag = new StringBuilder(128);
+ StringBuilder stack = new StringBuilder(128);
+ tag.append("Low on memory -- ");
+ appendMemBucket(tag, totalPss, "total", false);
+ appendMemBucket(stack, totalPss, "total", true);
+
+ StringBuilder fullNativeBuilder = new StringBuilder(1024);
+ StringBuilder shortNativeBuilder = new StringBuilder(1024);
+ StringBuilder fullJavaBuilder = new StringBuilder(1024);
+
+ boolean firstLine = true;
+ int lastOomAdj = Integer.MIN_VALUE;
+ long extraNativeRam = 0;
+ long cachedPss = 0;
+ for (int i=0, N=memInfos.size(); i<N; i++) {
+ ProcessMemInfo mi = memInfos.get(i);
+
+ if (mi.oomAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
+ cachedPss += mi.pss;
+ }
+
+ if (mi.oomAdj != ProcessList.NATIVE_ADJ
+ && (mi.oomAdj < ProcessList.SERVICE_ADJ
+ || mi.oomAdj == ProcessList.HOME_APP_ADJ
+ || mi.oomAdj == ProcessList.PREVIOUS_APP_ADJ)) {
+ if (lastOomAdj != mi.oomAdj) {
+ lastOomAdj = mi.oomAdj;
+ if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) {
+ tag.append(" / ");
+ }
+ if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ) {
+ if (firstLine) {
+ stack.append(":");
+ firstLine = false;
+ }
+ stack.append("\n\t at ");
+ } else {
+ stack.append("$");
+ }
+ } else {
+ tag.append(" ");
+ stack.append("$");
+ }
+ if (mi.oomAdj <= ProcessList.FOREGROUND_APP_ADJ) {
+ appendMemBucket(tag, mi.pss, mi.name, false);
+ }
+ appendMemBucket(stack, mi.pss, mi.name, true);
+ if (mi.oomAdj >= ProcessList.FOREGROUND_APP_ADJ
+ && ((i+1) >= N || memInfos.get(i+1).oomAdj != lastOomAdj)) {
+ stack.append("(");
+ for (int k=0; k<DUMP_MEM_OOM_ADJ.length; k++) {
+ if (DUMP_MEM_OOM_ADJ[k] == mi.oomAdj) {
+ stack.append(DUMP_MEM_OOM_LABEL[k]);
+ stack.append(":");
+ stack.append(DUMP_MEM_OOM_ADJ[k]);
+ }
+ }
+ stack.append(")");
+ }
+ }
+
+ appendMemInfo(fullNativeBuilder, mi);
+ if (mi.oomAdj == ProcessList.NATIVE_ADJ) {
+ // The short form only has native processes that are >= 1MB.
+ if (mi.pss >= 1000) {
+ appendMemInfo(shortNativeBuilder, mi);
+ } else {
+ extraNativeRam += mi.pss;
+ }
+ } else {
+ // Short form has all other details, but if we have collected RAM
+ // from smaller native processes let's dump a summary of that.
+ if (extraNativeRam > 0) {
+ appendBasicMemEntry(shortNativeBuilder, ProcessList.NATIVE_ADJ,
+ -1, extraNativeRam, "(Other native)");
+ shortNativeBuilder.append('\n');
+ extraNativeRam = 0;
+ }
+ appendMemInfo(fullJavaBuilder, mi);
+ }
+ }
+
+ fullJavaBuilder.append(" ");
+ ProcessList.appendRamKb(fullJavaBuilder, totalPss);
+ fullJavaBuilder.append(" kB: TOTAL\n");
+
+ MemInfoReader memInfo = new MemInfoReader();
+ memInfo.readMemInfo();
+ final long[] infos = memInfo.getRawInfo();
+
+ StringBuilder memInfoBuilder = new StringBuilder(1024);
+ Debug.getMemInfo(infos);
+ memInfoBuilder.append(" MemInfo: ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_SLAB]).append(" kB slab, ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_SHMEM]).append(" kB shmem, ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_VM_ALLOC_USED]).append(" kB vm alloc, ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_PAGE_TABLES]).append(" kB page tables ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_KERNEL_STACK]).append(" kB kernel stack\n");
+ memInfoBuilder.append(" ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_BUFFERS]).append(" kB buffers, ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_CACHED]).append(" kB cached, ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_MAPPED]).append(" kB mapped, ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_FREE]).append(" kB free\n");
+ if (infos[Debug.MEMINFO_ZRAM_TOTAL] != 0) {
+ memInfoBuilder.append(" ZRAM: ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_ZRAM_TOTAL]);
+ memInfoBuilder.append(" kB RAM, ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_SWAP_TOTAL]);
+ memInfoBuilder.append(" kB swap total, ");
+ memInfoBuilder.append(infos[Debug.MEMINFO_SWAP_FREE]);
+ memInfoBuilder.append(" kB swap free\n");
+ }
+ final long[] ksm = getKsmInfo();
+ if (ksm[KSM_SHARING] != 0 || ksm[KSM_SHARED] != 0 || ksm[KSM_UNSHARED] != 0
+ || ksm[KSM_VOLATILE] != 0) {
+ memInfoBuilder.append(" KSM: "); memInfoBuilder.append(ksm[KSM_SHARING]);
+ memInfoBuilder.append(" kB saved from shared ");
+ memInfoBuilder.append(ksm[KSM_SHARED]); memInfoBuilder.append(" kB\n");
+ memInfoBuilder.append(" "); memInfoBuilder.append(ksm[KSM_UNSHARED]);
+ memInfoBuilder.append(" kB unshared; ");
+ memInfoBuilder.append(ksm[KSM_VOLATILE]); memInfoBuilder.append(" kB volatile\n");
+ }
+ memInfoBuilder.append(" Free RAM: ");
+ memInfoBuilder.append(cachedPss + memInfo.getCachedSizeKb()
+ + memInfo.getFreeSizeKb());
+ memInfoBuilder.append(" kB\n");
+ memInfoBuilder.append(" Used RAM: ");
+ memInfoBuilder.append(totalPss - cachedPss + memInfo.getKernelUsedSizeKb());
+ memInfoBuilder.append(" kB\n");
+ memInfoBuilder.append(" Lost RAM: ");
+ memInfoBuilder.append(memInfo.getTotalSizeKb()
+ - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
+ - memInfo.getKernelUsedSizeKb());
+ memInfoBuilder.append(" kB\n");
+ Slog.i(TAG, "Low on memory:");
+ Slog.i(TAG, shortNativeBuilder.toString());
+ Slog.i(TAG, fullJavaBuilder.toString());
+ Slog.i(TAG, memInfoBuilder.toString());
+
+ StringBuilder dropBuilder = new StringBuilder(1024);
+ /*
+ StringWriter oomSw = new StringWriter();
+ PrintWriter oomPw = new FastPrintWriter(oomSw, false, 256);
+ StringWriter catSw = new StringWriter();
+ PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
+ String[] emptyArgs = new String[] { };
+ dumpApplicationMemoryUsage(null, oomPw, " ", emptyArgs, true, catPw);
+ oomPw.flush();
+ String oomString = oomSw.toString();
+ */
+ dropBuilder.append("Low on memory:");
+ dropBuilder.append(stack);
+ dropBuilder.append('\n');
+ dropBuilder.append(fullNativeBuilder);
+ dropBuilder.append(fullJavaBuilder);
+ dropBuilder.append('\n');
+ dropBuilder.append(memInfoBuilder);
+ dropBuilder.append('\n');
+ /*
+ dropBuilder.append(oomString);
+ dropBuilder.append('\n');
+ */
+ StringWriter catSw = new StringWriter();
+ synchronized (ActivityManagerService.this) {
+ PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
+ String[] emptyArgs = new String[] { };
+ catPw.println();
+ dumpProcessesLocked(null, catPw, emptyArgs, 0, false, null);
+ catPw.println();
+ mServices.dumpServicesLocked(null, catPw, emptyArgs, 0,
+ false, false, null);
+ catPw.println();
+ dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
+ catPw.flush();
+ }
+ dropBuilder.append(catSw.toString());
+ addErrorToDropBox("lowmem", null, "system_server", null,
+ null, tag.toString(), dropBuilder.toString(), null, null);
+ //Slog.i(TAG, "Sent to dropbox:");
+ //Slog.i(TAG, dropBuilder.toString());
+ synchronized (ActivityManagerService.this) {
+ long now = SystemClock.uptimeMillis();
+ if (mLastMemUsageReportTime < now) {
+ mLastMemUsageReportTime = now;
+ }
+ }
+ }
+
/**
* Searches array of arguments for the specified string
* @param args array of argument strings
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c1bf9556d5f7..eaff6be64ed7 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -444,10 +444,6 @@ public final class ActivityStackSupervisor implements DisplayListener {
return mService.startHomeActivityLocked(mCurrentUser);
}
- void keyguardWaitingForActivityDrawn() {
- mWindowManager.keyguardWaitingForActivityDrawn();
- }
-
TaskRecord anyTaskForIdLocked(int id) {
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
diff --git a/services/core/java/com/android/server/am/UserSwitchingDialog.java b/services/core/java/com/android/server/am/UserSwitchingDialog.java
index dfc8df580a15..36263ece1f47 100644
--- a/services/core/java/com/android/server/am/UserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/UserSwitchingDialog.java
@@ -17,17 +17,11 @@
package com.android.server.am;
import android.app.AlertDialog;
-import android.app.Service;
-import android.content.ActivityNotFoundException;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
import android.content.res.Resources;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.TextView;
@@ -39,11 +33,10 @@ import com.android.internal.R;
* in the background rather than just freeze the screen and not know if the user-switch affordance
* was being handled.
*/
-final class UserSwitchingDialog extends AlertDialog {
+final class UserSwitchingDialog extends AlertDialog
+ implements ViewTreeObserver.OnWindowShownListener {
private static final String TAG = "ActivityManagerUserSwitchingDialog";
- private static final int MSG_START_USER = 1;
-
private final ActivityManagerService mService;
private final int mUserId;
@@ -74,19 +67,21 @@ final class UserSwitchingDialog extends AlertDialog {
@Override
public void show() {
+ // Slog.v(TAG, "show called");
super.show();
- // TODO: Instead of just an arbitrary delay, wait for a signal that the window was fully
- // displayed by the window manager
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_USER), 250);
+ final View decorView = getWindow().getDecorView();
+ if (decorView != null) {
+ decorView.getViewTreeObserver().addOnWindowShownListener(this);
+ }
}
- private final Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_START_USER:
- mService.startUserInForeground(mUserId, UserSwitchingDialog.this);
- break;
- }
+ @Override
+ public void onWindowShown() {
+ // Slog.v(TAG, "onWindowShown called");
+ mService.startUserInForeground(mUserId, this);
+ final View decorView = getWindow().getDecorView();
+ if (decorView != null) {
+ decorView.getViewTreeObserver().removeOnWindowShownListener(this);
}
- };
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index c7a2ce1d9a39..576556b30648 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -17,6 +17,7 @@
package com.android.server.connectivity;
import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_WIFI;
import java.net.Inet4Address;
@@ -53,7 +54,7 @@ public class Nat464Xlat extends BaseNetworkObserver {
// ConnectivityService Handler for LinkProperties updates.
private final Handler mHandler;
- // The network we're running on.
+ // The network we're running on, and its type.
private final NetworkAgentInfo mNetwork;
// Internal state variables.
@@ -90,8 +91,9 @@ public class Nat464Xlat extends BaseNetworkObserver {
final boolean connected = nai.networkInfo.isConnected();
final boolean hasIPv4Address =
(nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false;
- // Only support clat on mobile for now.
- return netType == TYPE_MOBILE && connected && !hasIPv4Address;
+ // Only support clat on mobile and wifi for now, because these are the only IPv6-only
+ // networks we can connect to.
+ return connected && !hasIPv4Address && (netType == TYPE_MOBILE || netType == TYPE_WIFI);
}
/**
@@ -211,23 +213,41 @@ public class Nat464Xlat extends BaseNetworkObserver {
return stacked;
}
+ private LinkAddress getLinkAddress(String iface) {
+ try {
+ InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
+ return config.getLinkAddress();
+ } catch(RemoteException|IllegalStateException e) {
+ Slog.e(TAG, "Error getting link properties: " + e);
+ return null;
+ }
+ }
+
+ private void maybeSetIpv6NdOffload(String iface, boolean on) {
+ if (mNetwork.networkInfo.getType() != TYPE_WIFI) {
+ return;
+ }
+ try {
+ Slog.d(TAG, (on ? "En" : "Dis") + "abling ND offload on " + iface);
+ mNMService.setInterfaceIpv6NdOffload(iface, on);
+ } catch(RemoteException|IllegalStateException e) {
+ Slog.w(TAG, "Changing IPv6 ND offload on " + iface + "failed: " + e);
+ }
+ }
+
@Override
public void interfaceAdded(String iface) {
// Called by the InterfaceObserver on its own thread, so can race with stop().
if (isStarted() && mIface.equals(iface)) {
Slog.i(TAG, "interface " + iface + " added, mIsRunning " + mIsRunning + "->true");
- LinkAddress clatAddress;
- try {
- InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
- clatAddress = config.getLinkAddress();
- } catch(RemoteException e) {
- Slog.e(TAG, "Error getting link properties: " + e);
- return;
- }
-
if (!mIsRunning) {
+ LinkAddress clatAddress = getLinkAddress(iface);
+ if (clatAddress == null) {
+ return;
+ }
mIsRunning = true;
+ maybeSetIpv6NdOffload(mBaseIface, false);
LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
lp.addStackedLink(makeLinkProperties(clatAddress));
Slog.i(TAG, "Adding stacked link " + mIface + " on top of " + mBaseIface);
@@ -255,6 +275,7 @@ public class Nat464Xlat extends BaseNetworkObserver {
} catch (RemoteException|IllegalStateException e) {
// Well, we tried.
}
+ maybeSetIpv6NdOffload(mBaseIface, true);
LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
lp.removeStackedLink(mIface);
clear();
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 07fe7ba79582..7d1da01b8ca6 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -265,14 +265,9 @@ public class PacManager {
}
Intent intent = new Intent();
intent.setClassName(PAC_PACKAGE, PAC_SERVICE);
- // Already bound no need to bind again.
if ((mProxyConnection != null) && (mConnection != null)) {
- if (mLastPort != -1) {
- sendPacBroadcast(new ProxyInfo(mPacUrl, mLastPort));
- } else {
- Log.e(TAG, "Received invalid port from Local Proxy,"
- + " PAC will not be operational");
- }
+ // Already bound no need to bind again, just download the new file.
+ IoThread.getHandler().post(mPacDownloader);
return;
}
mConnection = new ServiceConnection() {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 2d5b99eb6c26..1d8003b9b721 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -570,8 +570,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
state = mPowerState.getScreenState();
// Use zero brightness when screen is off.
+ // Use full brightness when screen brightness is boosted.
if (state == Display.STATE_OFF) {
brightness = PowerManager.BRIGHTNESS_OFF;
+ } else if (mPowerRequest.boostScreenBrightness) {
+ brightness = PowerManager.BRIGHTNESS_ON;
}
// Use default brightness when dozing unless overridden.
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 0198e46b786e..c2cb4b1da1f0 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -473,14 +473,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
checkSmsSuplInit(intent);
} else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
checkWapSuplInit(intent);
- } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
- int networkState;
- if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false)) {
- networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
- } else {
- networkState = LocationProvider.AVAILABLE;
- }
-
+ } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE)) {
// retrieve NetworkInfo result for this UID
NetworkInfo info =
intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
@@ -488,6 +481,15 @@ public class GpsLocationProvider implements LocationProviderInterface {
mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
info = connManager.getNetworkInfo(info.getType());
+ int networkState;
+ if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false) ||
+ !info.isConnected()) {
+ networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
+ } else {
+ networkState = LocationProvider.AVAILABLE;
+ }
+
+
updateNetworkState(networkState, info);
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
|| Intent.ACTION_SCREEN_OFF.equals(action)
@@ -715,7 +717,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
intentFilter = new IntentFilter();
intentFilter.addAction(ALARM_WAKEUP);
intentFilter.addAction(ALARM_TIMEOUT);
- intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE);
intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e9d19aae8baa..42a855165c20 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -41,6 +41,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -657,7 +658,7 @@ public class NotificationManagerService extends SystemService {
}
};
- private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ private final BroadcastReceiver mPackageIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -673,6 +674,8 @@ public class NotificationManagerService extends SystemService {
|| (packageChanged=action.equals(Intent.ACTION_PACKAGE_CHANGED))
|| (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART))
|| action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
+ int changeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+ UserHandle.USER_ALL);
String pkgList[] = null;
boolean queryReplace = queryRemove &&
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
@@ -693,8 +696,10 @@ public class NotificationManagerService extends SystemService {
if (packageChanged) {
// We cancel notifications for packages which have just been disabled
try {
- final int enabled = getContext().getPackageManager()
- .getApplicationEnabledSetting(pkgName);
+ final IPackageManager pm = AppGlobals.getPackageManager();
+ final int enabled = pm.getApplicationEnabledSetting(pkgName,
+ changeUserId != UserHandle.USER_ALL ? changeUserId :
+ UserHandle.USER_OWNER);
if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|| enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
cancelNotifications = false;
@@ -705,6 +710,8 @@ public class NotificationManagerService extends SystemService {
if (DBG) {
Slog.i(TAG, "Exception trying to look up app enabled setting", e);
}
+ } catch (RemoteException e) {
+ // Failed to talk to PackageManagerService Should never happen!
}
}
pkgList = new String[]{pkgName};
@@ -714,13 +721,22 @@ public class NotificationManagerService extends SystemService {
for (String pkgName : pkgList) {
if (cancelNotifications) {
cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, 0, 0, !queryRestart,
- UserHandle.USER_ALL, REASON_PACKAGE_CHANGED, null);
+ changeUserId, REASON_PACKAGE_CHANGED, null);
}
}
}
mListeners.onPackagesChanged(queryReplace, pkgList);
mConditionProviders.onPackagesChanged(queryReplace, pkgList);
- } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+ }
+ }
+ };
+
+ private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+
+ if (action.equals(Intent.ACTION_SCREEN_ON)) {
// Keep track of screen on/off state, but do not turn off the notification light
// until user passes through the lock screen or views the notification.
mScreenOn = true;
@@ -903,6 +919,7 @@ public class NotificationManagerService extends SystemService {
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_USER_ADDED);
getContext().registerReceiver(mIntentReceiver, filter);
+
IntentFilter pkgFilter = new IntentFilter();
pkgFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
pkgFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -910,9 +927,12 @@ public class NotificationManagerService extends SystemService {
pkgFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
pkgFilter.addDataScheme("package");
- getContext().registerReceiver(mIntentReceiver, pkgFilter);
+ getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL, pkgFilter, null,
+ null);
+
IntentFilter sdFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- getContext().registerReceiver(mIntentReceiver, sdFilter);
+ getContext().registerReceiverAsUser(mPackageIntentReceiver, UserHandle.ALL, sdFilter, null,
+ null);
mSettingsObserver = new SettingsObserver(mHandler);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index de6e82be0625..f9a85dfd4929 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -333,6 +333,7 @@ public class PackageManagerService extends IPackageManager.Stub {
final DisplayMetrics mMetrics;
final int mDefParseFlags;
final String[] mSeparateProcesses;
+ final boolean mIsUpgrade;
// This is where all application persistent data goes.
final File mAppDataDir;
@@ -1760,7 +1761,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// If this is first boot after an OTA, and a normal boot, then
// we need to clear code cache directories.
- if (!Build.FINGERPRINT.equals(mSettings.mFingerprint) && !onlyCore) {
+ mIsUpgrade = !Build.FINGERPRINT.equals(mSettings.mFingerprint);
+ if (mIsUpgrade && !onlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
for (String pkgName : mSettings.mPackages.keySet()) {
deleteCodeCacheDirsLI(pkgName);
@@ -1800,6 +1802,11 @@ public class PackageManagerService extends IPackageManager.Stub {
return mOnlyCore;
}
+ @Override
+ public boolean isUpgrade() {
+ return mIsUpgrade;
+ }
+
private String getRequiredVerifierLPr() {
final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
@@ -3259,7 +3266,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions");
}
- mSettings.writePackageRestrictionsLPr(userId);
+ scheduleWritePackageRestrictionsLocked(userId);
}
}
}
@@ -11559,7 +11566,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+ userId + ":");
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
pir.addFilter(new PreferredActivity(filter, match, set, activity, always));
- mSettings.writePackageRestrictionsLPr(userId);
+ scheduleWritePackageRestrictionsLocked(userId);
}
}
@@ -11675,8 +11682,7 @@ public class PackageManagerService extends IPackageManager.Stub {
int user = UserHandle.getCallingUserId();
if (clearPackagePreferredActivitiesLPw(packageName, user)) {
- mSettings.writePackageRestrictionsLPr(user);
- scheduleWriteSettingsLocked();
+ scheduleWritePackageRestrictionsLocked(user);
}
}
}
@@ -11726,8 +11732,7 @@ public class PackageManagerService extends IPackageManager.Stub {
int user = UserHandle.getCallingUserId();
clearPackagePreferredActivitiesLPw(null, user);
mSettings.readDefaultPreferredAppsLPw(this, user);
- mSettings.writePackageRestrictionsLPr(user);
- scheduleWriteSettingsLocked();
+ scheduleWritePackageRestrictionsLocked(user);
}
}
@@ -11779,7 +11784,7 @@ public class PackageManagerService extends IPackageManager.Stub {
filter.dump(new LogPrinter(Log.INFO, TAG), " ");
mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter(
new PersistentPreferredActivity(filter, activity));
- mSettings.writePackageRestrictionsLPr(userId);
+ scheduleWritePackageRestrictionsLocked(userId);
}
}
@@ -11821,7 +11826,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (changed) {
- mSettings.writePackageRestrictionsLPr(userId);
+ scheduleWritePackageRestrictionsLocked(userId);
}
}
}
@@ -11842,7 +11847,7 @@ public class PackageManagerService extends IPackageManager.Stub {
CrossProfileIntentFilter filter = new CrossProfileIntentFilter(intentFilter,
ownerPackage, UserHandle.getUserId(callingUid), targetUserId, flags);
mSettings.editCrossProfileIntentResolverLPw(sourceUserId).addFilter(filter);
- mSettings.writePackageRestrictionsLPr(sourceUserId);
+ scheduleWritePackageRestrictionsLocked(sourceUserId);
}
}
@@ -11866,7 +11871,7 @@ public class PackageManagerService extends IPackageManager.Stub {
resolver.removeFilter(filter);
}
}
- mSettings.writePackageRestrictionsLPr(sourceUserId);
+ scheduleWritePackageRestrictionsLocked(sourceUserId);
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 5e95dfeed1ee..8682f5cfe536 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -88,6 +88,8 @@ public final class PowerManagerService extends SystemService
private static final int MSG_USER_ACTIVITY_TIMEOUT = 1;
// Message: Sent when the device enters or exits a dreaming or dozing state.
private static final int MSG_SANDMAN = 2;
+ // Message: Sent when the screen brightness boost expires.
+ private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3;
// Dirty bit: mWakeLocks changed
private static final int DIRTY_WAKE_LOCKS = 1 << 0;
@@ -111,6 +113,8 @@ public final class PowerManagerService extends SystemService
private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9;
// Dirty bit: dock state changed
private static final int DIRTY_DOCK_STATE = 1 << 10;
+ // Dirty bit: brightness boost changed
+ private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11;
// Wakefulness: The device is asleep and can only be awoken by a call to wakeUp().
// The screen should be off or in the process of being turned off by the display controller.
@@ -149,6 +153,11 @@ public final class PowerManagerService extends SystemService
private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000;
private static final int DEFAULT_SLEEP_TIMEOUT = -1;
+ // Screen brightness boost timeout.
+ // Hardcoded for now until we decide what the right policy should be.
+ // This should perhaps be a setting.
+ private static final int SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 5 * 1000;
+
// Power hints defined in hardware/libhardware/include/hardware/power.h.
private static final int POWER_HINT_INTERACTION = 2;
private static final int POWER_HINT_LOW_POWER = 5;
@@ -215,6 +224,10 @@ public final class PowerManagerService extends SystemService
// Timestamp of last interactive power hint.
private long mLastInteractivePowerHintTime;
+ // Timestamp of the last screen brightness boost.
+ private long mLastScreenBrightnessBoostTime;
+ private boolean mScreenBrightnessBoostInProgress;
+
// A bitfield that summarizes the effect of the user activity timer.
private int mUserActivitySummary;
@@ -1812,9 +1825,13 @@ public final class PowerManagerService extends SystemService
final boolean oldDisplayReady = mDisplayReady;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
- | DIRTY_SETTINGS)) != 0) {
+ | DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
+ // Handle screen brightness boost timeout.
+ updateScreenBrightnessBoostLocked();
+
+ // Determine appropriate screen brightness and auto-brightness adjustments.
int screenBrightness = mScreenBrightnessSettingDefault;
float screenAutoBrightnessAdjustment = 0.0f;
boolean autoBrightness = (mScreenBrightnessModeSetting ==
@@ -1842,14 +1859,15 @@ public final class PowerManagerService extends SystemService
mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
screenAutoBrightnessAdjustment = Math.max(Math.min(
screenAutoBrightnessAdjustment, 1.0f), -1.0f);
+
+ // Update display power request.
mDisplayPowerRequest.screenBrightness = screenBrightness;
mDisplayPowerRequest.screenAutoBrightnessAdjustment =
screenAutoBrightnessAdjustment;
mDisplayPowerRequest.useAutoBrightness = autoBrightness;
-
mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
-
mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
+ mDisplayPowerRequest.boostScreenBrightness = mScreenBrightnessBoostInProgress;
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
@@ -1861,21 +1879,40 @@ public final class PowerManagerService extends SystemService
}
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
- mRequestWaitForNegativeProximity);
+ mRequestWaitForNegativeProximity) && !mScreenBrightnessBoostInProgress;
mRequestWaitForNegativeProximity = false;
if (DEBUG_SPEW) {
- Slog.d(TAG, "updateScreenStateLocked: mDisplayReady=" + mDisplayReady
+ Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady
+ ", policy=" + mDisplayPowerRequest.policy
+ ", mWakefulness=" + mWakefulness
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
- + ", mBootCompleted=" + mBootCompleted);
+ + ", mBootCompleted=" + mBootCompleted
+ + ", mScreenBrightnessBoostInProgress="
+ + mScreenBrightnessBoostInProgress);
}
}
return mDisplayReady && !oldDisplayReady;
}
+ private void updateScreenBrightnessBoostLocked() {
+ if (mScreenBrightnessBoostInProgress) {
+ mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
+ if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
+ final long boostTimeout = mLastScreenBrightnessBoostTime +
+ SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
+ if (boostTimeout > SystemClock.uptimeMillis()) {
+ Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageAtTime(msg, boostTimeout);
+ return;
+ }
+ }
+ mScreenBrightnessBoostInProgress = false;
+ }
+ }
+
private static boolean isValidBrightness(int value) {
return value >= 0 && value <= 255;
}
@@ -2223,6 +2260,41 @@ public final class PowerManagerService extends SystemService
light.setFlashing(color, Light.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
}
+ private void boostScreenBrightnessInternal(long eventTime, int uid) {
+ synchronized (mLock) {
+ if (!mSystemReady || mWakefulness == WAKEFULNESS_ASLEEP
+ || eventTime < mLastScreenBrightnessBoostTime) {
+ return;
+ }
+
+ Slog.i(TAG, "Brightness boost activated (uid " + uid +")...");
+ mLastScreenBrightnessBoostTime = eventTime;
+ mScreenBrightnessBoostInProgress = true;
+ mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;
+
+ userActivityNoUpdateLocked(eventTime,
+ PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, uid);
+ updatePowerStateLocked();
+ }
+ }
+
+ /**
+ * Called when a screen brightness boost timeout has occurred.
+ *
+ * This function must have no other side-effects besides setting the dirty
+ * bit and calling update power state.
+ */
+ private void handleScreenBrightnessBoostTimeout() { // runs on handler thread
+ synchronized (mLock) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "handleScreenBrightnessBoostTimeout");
+ }
+
+ mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;
+ updatePowerStateLocked();
+ }
+ }
+
private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) {
synchronized (mLock) {
if (mScreenBrightnessOverrideFromWindowManager != brightness) {
@@ -2366,6 +2438,10 @@ public final class PowerManagerService extends SystemService
+ TimeUtils.formatUptime(mLastUserActivityTimeNoChangeLights));
pw.println(" mLastInteractivePowerHintTime="
+ TimeUtils.formatUptime(mLastInteractivePowerHintTime));
+ pw.println(" mLastScreenBrightnessBoostTime="
+ + TimeUtils.formatUptime(mLastScreenBrightnessBoostTime));
+ pw.println(" mScreenBrightnessBoostInProgress="
+ + mScreenBrightnessBoostInProgress);
pw.println(" mDisplayReady=" + mDisplayReady);
pw.println(" mHoldingWakeLockSuspendBlocker=" + mHoldingWakeLockSuspendBlocker);
pw.println(" mHoldingDisplaySuspendBlocker=" + mHoldingDisplaySuspendBlocker);
@@ -2562,6 +2638,9 @@ public final class PowerManagerService extends SystemService
case MSG_SANDMAN:
handleSandman();
break;
+ case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
+ handleScreenBrightnessBoostTimeout();
+ break;
}
}
}
@@ -3143,6 +3222,24 @@ public final class PowerManagerService extends SystemService
}
@Override // Binder call
+ public void boostScreenBrightness(long eventTime) {
+ if (eventTime > SystemClock.uptimeMillis()) {
+ throw new IllegalArgumentException("event time must not be in the future");
+ }
+
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+
+ final int uid = Binder.getCallingUid();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ boostScreenBrightnessInternal(eventTime, uid);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 69d31914fdb0..61ea1e8d061f 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -20,6 +20,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static com.android.server.wm.WindowManagerService.DEBUG_KEYGUARD;
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
@@ -29,7 +30,6 @@ import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPA
import android.content.Context;
import android.os.Debug;
import android.os.SystemClock;
-import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -233,12 +233,17 @@ public class WindowAnimator {
final WindowStateAnimator winAnimator = win.mWinAnimator;
if ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
if (!winAnimator.mAnimating) {
+ if (DEBUG_KEYGUARD) Slog.d(TAG,
+ "updateWindowsLocked: creating delay animation");
+
// Create a new animation to delay until keyguard is gone on its own.
winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
winAnimator.mAnimationIsEntrance = false;
}
} else {
+ if (DEBUG_KEYGUARD) Slog.d(TAG,
+ "updateWindowsLocked: StatusBar is no longer keyguard");
mKeyguardGoingAway = false;
winAnimator.clearAnimation();
}
@@ -282,7 +287,7 @@ public class WindowAnimator {
if (mPolicy.isForceHiding(win.mAttrs)) {
if (!wasAnimating && nowAnimating) {
- if (WindowManagerService.DEBUG_ANIM ||
+ if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_ANIM ||
WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
"Animation started that could impact force hide: " + win);
mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
@@ -310,7 +315,7 @@ public class WindowAnimator {
mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
}
}
- if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
+ if (DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
"Force hide " + forceHidingToString()
+ " hasSurface=" + win.mHasSurface
+ " policyVis=" + win.mPolicyVisibility
@@ -327,12 +332,12 @@ public class WindowAnimator {
&& (!winAnimator.isAnimating() || hideWhenLocked))
|| ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
changed = win.hideLw(false, false);
- if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
- "Now policy hidden: " + win);
+ if ((DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY)
+ && changed) Slog.v(TAG, "Now policy hidden: " + win);
} else {
changed = win.showLw(false, false);
- if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
- "Now policy shown: " + win);
+ if ((DEBUG_KEYGUARD || WindowManagerService.DEBUG_VISIBILITY)
+ && changed) Slog.v(TAG, "Now policy shown: " + win);
if (changed) {
if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
&& win.isVisibleNow() /*w.isReadyForDisplay()*/) {
@@ -404,6 +409,11 @@ public class WindowAnimator {
if (!mKeyguardGoingAwayDisableWindowAnimations) {
a = mPolicy.createForceHideEnterAnimation(wallpaperInUnForceHiding,
mKeyguardGoingAwayToNotificationShade);
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: created anim=" + a
+ + " for win=" + unForceHiding.get(i));
+ } else {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: skipping anim for win="
+ + unForceHiding.get(i));
}
if (a != null) {
final WindowStateAnimator winAnimator = unForceHiding.get(i);
@@ -422,6 +432,7 @@ public class WindowAnimator {
// Wallpaper is going away in un-force-hide motion, animate it as well.
if (!wallpaperInUnForceHiding && wallpaper != null
&& !mKeyguardGoingAwayDisableWindowAnimations) {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away");
Animation a = mPolicy.createForceHideWallpaperExitAnimation(
mKeyguardGoingAwayToNotificationShade);
if (a != null) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0e55c1cecff6..a48d39f41b61 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -166,6 +166,7 @@ public class WindowManagerService extends IWindowManager.Stub
static final boolean DEBUG_FOCUS = false;
static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
static final boolean DEBUG_ANIM = false;
+ static final boolean DEBUG_KEYGUARD = false;
static final boolean DEBUG_LAYOUT = false;
static final boolean DEBUG_RESIZE = false;
static final boolean DEBUG_LAYERS = false;
@@ -2487,7 +2488,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- win.mWinAnimator.mEnterAnimationPending = true;
+ final WindowStateAnimator winAnimator = win.mWinAnimator;
+ winAnimator.mEnterAnimationPending = true;
+ winAnimator.mEnteringAnimation = true;
if (displayContent.isDefaultDisplay) {
mPolicy.getContentInsetHintLw(attrs, outContentInsets);
@@ -3099,6 +3102,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (oldVisibility == View.GONE) {
winAnimator.mEnterAnimationPending = true;
}
+ winAnimator.mEnteringAnimation = true;
if (toBeDisplayed) {
if (win.isDrawnLw() && okToDisplay()) {
winAnimator.applyEnterAnimationLocked();
@@ -3167,6 +3171,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
} else {
winAnimator.mEnterAnimationPending = false;
+ winAnimator.mEnteringAnimation = false;
if (winAnimator.mSurfaceControl != null) {
if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
+ ": mExiting=" + win.mExiting);
@@ -5359,6 +5364,8 @@ public class WindowManagerService extends IWindowManager.Stub
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
}
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardGoingAway: disableWinAnim="
+ + disableWindowAnimations + " kgToNotifShade=" + keyguardGoingToNotificationShade);
synchronized (mWindowMap) {
mAnimator.mKeyguardGoingAway = true;
mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade;
@@ -5368,12 +5375,15 @@ public class WindowManagerService extends IWindowManager.Stub
}
public void keyguardWaitingForActivityDrawn() {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "keyguardWaitingForActivityDrawn");
synchronized (mWindowMap) {
mKeyguardWaitingForActivityDrawn = true;
}
}
public void notifyActivityDrawnForKeyguard() {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "notifyActivityDrawnForKeyguard: waiting="
+ + mKeyguardWaitingForActivityDrawn);
synchronized (mWindowMap) {
if (mKeyguardWaitingForActivityDrawn) {
mPolicy.notifyActivityDrawnForKeyguardLw();
@@ -6049,6 +6059,10 @@ public class WindowManagerService extends IWindowManager.Stub
while (true) {
if (retryCount++ > 0) {
+ // Reset max/min layers on retries so we don't accidentally take a screenshot of a
+ // layer based on the previous try.
+ maxLayer = 0;
+ minLayer = Integer.MAX_VALUE;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
@@ -6071,7 +6085,17 @@ public class WindowManagerService extends IWindowManager.Stub
continue;
}
} else if (ws.mIsWallpaper) {
- // Fall through.
+ if (appWin == null) {
+ // We have not ran across the target window yet, so it is probably
+ // behind the wallpaper. This can happen when the keyguard is up and
+ // all windows are moved behind the wallpaper. We don't want to
+ // include the wallpaper layer in the screenshot as it will coverup
+ // the layer of the target window.
+ continue;
+ }
+ // Fall through. The target window is in front of the wallpaper. For this
+ // case we want to include the wallpaper layer in the screenshot because
+ // the target window might have some transparent areas.
} else if (appToken != null) {
if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
// This app window is of no interest if it is not associated with the
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e5cf7644ffb9..f9efc809162d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -29,6 +29,7 @@ import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import android.app.AppOpsManager;
@@ -902,7 +903,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
*/
boolean isVisibleNow() {
return mHasSurface && mPolicyVisibility && !mAttachedHidden
- && !mRootToken.hidden && !mExiting && !mDestroying;
+ && (!mRootToken.hidden || mAttrs.type == TYPE_APPLICATION_STARTING)
+ && !mExiting && !mDestroying;
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0c727f33172e..fc3f2c275d2f 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -40,6 +40,7 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Debug;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
import android.view.Display;
@@ -141,6 +142,11 @@ class WindowStateAnimator {
// an enter animation.
boolean mEnterAnimationPending;
+ /** Used to indicate that this window is undergoing an enter animation. Used for system
+ * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the
+ * window is first added or shown, cleared when the callback has been made. */
+ boolean mEnteringAnimation;
+
boolean keyguardGoingAwayAnimation;
/** This is set when there is no Surface */
@@ -428,6 +434,14 @@ class WindowStateAnimator {
mWin.mChildWindows.get(i).mWinAnimator.finishExit();
}
+ if (mEnteringAnimation && mWin.mAppToken == null) {
+ try {
+ mEnteringAnimation = false;
+ mWin.mClient.dispatchWindowShown();
+ } catch (RemoteException e) {
+ }
+ }
+
if (!mWin.mExiting) {
return;
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index cfa44363551e..11da380766f8 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -39,6 +39,7 @@ class UsageStatsDatabase {
private static final String TAG = "UsageStatsDatabase";
private static final boolean DEBUG = UsageStatsService.DEBUG;
+ private static final String BAK_SUFFIX = ".bak";
private final Object mLock = new Object();
private final File[] mIntervalDirs;
@@ -95,11 +96,71 @@ class UsageStatsDatabase {
}
}
+ public interface CheckinAction {
+ boolean checkin(IntervalStats stats);
+ }
+
+ /**
+ * Calls {@link CheckinAction#checkin(IntervalStats)} on the given {@link CheckinAction}
+ * for all {@link IntervalStats} that haven't been checked-in.
+ * If any of the calls to {@link CheckinAction#checkin(IntervalStats)} returns false or throws
+ * an exception, the check-in will be aborted.
+ *
+ * @param checkinAction The callback to run when checking-in {@link IntervalStats}.
+ * @return true if the check-in succeeded.
+ */
+ public boolean checkinDailyFiles(CheckinAction checkinAction) {
+ synchronized (mLock) {
+ final TimeSparseArray<AtomicFile> files =
+ mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY];
+ final int fileCount = files.size();
+ int start = 0;
+ while (start < fileCount - 1) {
+ if (!files.valueAt(start).getBaseFile().getName().endsWith("-c")) {
+ break;
+ }
+ }
+
+ if (start == fileCount - 1) {
+ return true;
+ }
+
+ try {
+ IntervalStats stats = new IntervalStats();
+ for (int i = start; i < fileCount - 1; i++) {
+ UsageStatsXml.read(files.valueAt(i), stats);
+ if (!checkinAction.checkin(stats)) {
+ return false;
+ }
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to check-in", e);
+ return false;
+ }
+
+ // We have successfully checked-in the stats, so rename the files so that they
+ // are marked as checked-in.
+ for (int i = start; i < fileCount - 1; i++) {
+ final AtomicFile file = files.valueAt(i);
+ final File checkedInFile = new File(file.getBaseFile().getParent(),
+ file.getBaseFile().getName() + "-c");
+ if (!file.getBaseFile().renameTo(checkedInFile)) {
+ // We must return success, as we've already marked some files as checked-in.
+ // It's better to repeat ourselves than to lose data.
+ Slog.e(TAG, "Failed to mark file " + file.getBaseFile().getPath()
+ + " as checked-in");
+ return true;
+ }
+ }
+ }
+ return true;
+ }
+
private void indexFilesLocked() {
final FilenameFilter backupFileFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
- return !name.endsWith(".bak");
+ return !name.endsWith(BAK_SUFFIX);
}
};
@@ -383,10 +444,10 @@ class UsageStatsDatabase {
if (files != null) {
for (File f : files) {
String path = f.getPath();
- if (path.endsWith(".bak")) {
- f = new File(path.substring(0, path.length() - 4));
+ if (path.endsWith(BAK_SUFFIX)) {
+ f = new File(path.substring(0, path.length() - BAK_SUFFIX.length()));
}
- long beginTime = Long.parseLong(f.getName());
+ long beginTime = UsageStatsXml.parseBeginTime(f);
if (beginTime < expiryTime) {
new AtomicFile(f).delete();
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 7ff246a1bdbc..485b2a208911 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -33,7 +33,6 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.os.Binder;
-import android.os.Debug;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
@@ -48,9 +47,12 @@ import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.SystemService;
import java.io.File;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
@@ -177,7 +179,7 @@ public class UsageStatsService extends SystemService implements
long currentTimeMillis) {
UserUsageStatsService service = mUserState.get(userId);
if (service == null) {
- service = new UserUsageStatsService(userId,
+ service = new UserUsageStatsService(getContext(), userId,
new File(mUsageStatsDir, Integer.toString(userId)), this);
service.init(currentTimeMillis);
mUserState.put(userId, service);
@@ -320,6 +322,30 @@ public class UsageStatsService extends SystemService implements
mHandler.removeMessages(MSG_FLUSH_TO_DISK);
}
+ /**
+ * Called by the Binder stub.
+ */
+ void dump(String[] args, PrintWriter pw) {
+ synchronized (mLock) {
+ IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " ");
+ ArraySet<String> argSet = new ArraySet<>();
+ argSet.addAll(Arrays.asList(args));
+
+ final int userCount = mUserState.size();
+ for (int i = 0; i < userCount; i++) {
+ idpw.printPair("user", mUserState.keyAt(i));
+ idpw.println();
+ idpw.increaseIndent();
+ if (argSet.contains("--checkin")) {
+ mUserState.valueAt(i).checkin(idpw);
+ } else {
+ mUserState.valueAt(i).dump(idpw);
+ }
+ idpw.decreaseIndent();
+ }
+ }
+ }
+
class H extends Handler {
public H(Looper looper) {
super(looper);
@@ -422,6 +448,18 @@ public class UsageStatsService extends SystemService implements
Binder.restoreCallingIdentity(token);
}
}
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump UsageStats from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " without permission " + android.Manifest.permission.DUMP);
+ return;
+ }
+ UsageStatsService.this.dump(args, pw);
+ }
}
/**
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXml.java b/services/usage/java/com/android/server/usage/UsageStatsXml.java
index 9ce6d63341fc..26148cef5e63 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXml.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXml.java
@@ -24,21 +24,26 @@ import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
+import java.io.*;
public class UsageStatsXml {
private static final String TAG = "UsageStatsXml";
private static final int CURRENT_VERSION = 1;
private static final String USAGESTATS_TAG = "usagestats";
private static final String VERSION_ATTR = "version";
+ private static final String CHECKED_IN_SUFFIX = "-c";
public static long parseBeginTime(AtomicFile file) {
- return Long.parseLong(file.getBaseFile().getName());
+ return parseBeginTime(file.getBaseFile());
+ }
+
+ public static long parseBeginTime(File file) {
+ final String name = file.getName();
+ if (name.endsWith(CHECKED_IN_SUFFIX)) {
+ return Long.parseLong(
+ name.substring(0, name.length() - CHECKED_IN_SUFFIX.length()));
+ }
+ return Long.parseLong(name);
}
public static void read(AtomicFile file, IntervalStats statsOut) throws IOException {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 4916ec2c8612..6596781c0964 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -23,9 +23,13 @@ import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.res.Configuration;
import android.os.SystemClock;
+import android.content.Context;
+import android.text.format.DateUtils;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.usage.UsageStatsDatabase.StatCombiner;
import java.io.File;
@@ -43,7 +47,13 @@ class UserUsageStatsService {
private static final String TAG = "UsageStatsService";
private static final boolean DEBUG = UsageStatsService.DEBUG;
private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ private static final int sDateFormatFlags =
+ DateUtils.FORMAT_SHOW_DATE
+ | DateUtils.FORMAT_SHOW_TIME
+ | DateUtils.FORMAT_SHOW_YEAR
+ | DateUtils.FORMAT_NUMERIC_DATE;
+ private final Context mContext;
private final UsageStatsDatabase mDatabase;
private final IntervalStats[] mCurrentStats;
private boolean mStatsChanged = false;
@@ -55,7 +65,8 @@ class UserUsageStatsService {
void onStatsUpdated();
}
- UserUsageStatsService(int userId, File usageStatsDir, StatsUpdatedListener listener) {
+ UserUsageStatsService(Context context, int userId, File usageStatsDir, StatsUpdatedListener listener) {
+ mContext = context;
mDailyExpiryDate = new UnixCalendar(0);
mDatabase = new UsageStatsDatabase(usageStatsDir);
mCurrentStats = new IntervalStats[UsageStatsManager.INTERVAL_COUNT];
@@ -433,6 +444,117 @@ class UserUsageStatsService {
tempCal.getTimeInMillis() + ")");
}
+ //
+ // -- DUMP related methods --
+ //
+
+ void checkin(final IndentingPrintWriter pw) {
+ mDatabase.checkinDailyFiles(new UsageStatsDatabase.CheckinAction() {
+ @Override
+ public boolean checkin(IntervalStats stats) {
+ printIntervalStats(pw, stats, false);
+ return true;
+ }
+ });
+ }
+
+ void dump(IndentingPrintWriter pw) {
+ // This is not a check-in, only dump in-memory stats.
+ for (int interval = 0; interval < mCurrentStats.length; interval++) {
+ pw.print("In-memory ");
+ pw.print(intervalToString(interval));
+ pw.println(" stats");
+ printIntervalStats(pw, mCurrentStats[interval], true);
+ }
+ }
+
+ private String formatDateTime(long dateTime, boolean pretty) {
+ if (pretty) {
+ return "\"" + DateUtils.formatDateTime(mContext, dateTime, sDateFormatFlags) + "\"";
+ }
+ return Long.toString(dateTime);
+ }
+
+ private String formatElapsedTime(long elapsedTime, boolean pretty) {
+ if (pretty) {
+ return "\"" + DateUtils.formatElapsedTime(elapsedTime / 1000) + "\"";
+ }
+ return Long.toString(elapsedTime);
+ }
+
+ void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats, boolean prettyDates) {
+ if (prettyDates) {
+ pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext,
+ stats.beginTime, stats.endTime, sDateFormatFlags) + "\"");
+ } else {
+ pw.printPair("beginTime", stats.beginTime);
+ pw.printPair("endTime", stats.endTime);
+ }
+ pw.println();
+ pw.increaseIndent();
+ pw.println("packages");
+ pw.increaseIndent();
+ final ArrayMap<String, UsageStats> pkgStats = stats.packageStats;
+ final int pkgCount = pkgStats.size();
+ for (int i = 0; i < pkgCount; i++) {
+ final UsageStats usageStats = pkgStats.valueAt(i);
+ pw.printPair("package", usageStats.mPackageName);
+ pw.printPair("totalTime", formatElapsedTime(usageStats.mTotalTimeInForeground, prettyDates));
+ pw.printPair("lastTime", formatDateTime(usageStats.mLastTimeUsed, prettyDates));
+ pw.println();
+ }
+ pw.decreaseIndent();
+
+ pw.println("configurations");
+ pw.increaseIndent();
+ final ArrayMap<Configuration, ConfigurationStats> configStats =
+ stats.configurations;
+ final int configCount = configStats.size();
+ for (int i = 0; i < configCount; i++) {
+ final ConfigurationStats config = configStats.valueAt(i);
+ pw.printPair("config", Configuration.resourceQualifierString(config.mConfiguration));
+ pw.printPair("totalTime", formatElapsedTime(config.mTotalTimeActive, prettyDates));
+ pw.printPair("lastTime", formatDateTime(config.mLastTimeActive, prettyDates));
+ pw.printPair("count", config.mActivationCount);
+ pw.println();
+ }
+ pw.decreaseIndent();
+
+ pw.println("events");
+ pw.increaseIndent();
+ final TimeSparseArray<UsageEvents.Event> events = stats.events;
+ final int eventCount = events != null ? events.size() : 0;
+ for (int i = 0; i < eventCount; i++) {
+ final UsageEvents.Event event = events.valueAt(i);
+ pw.printPair("time", formatDateTime(event.mTimeStamp, prettyDates));
+ pw.printPair("type", eventToString(event.mEventType));
+ pw.printPair("package", event.mPackage);
+ if (event.mClass != null) {
+ pw.printPair("class", event.mClass);
+ }
+ if (event.mConfiguration != null) {
+ pw.printPair("config", Configuration.resourceQualifierString(event.mConfiguration));
+ }
+ pw.println();
+ }
+ pw.decreaseIndent();
+ pw.decreaseIndent();
+ }
+
+ private static String intervalToString(int interval) {
+ switch (interval) {
+ case UsageStatsManager.INTERVAL_DAILY:
+ return "daily";
+ case UsageStatsManager.INTERVAL_WEEKLY:
+ return "weekly";
+ case UsageStatsManager.INTERVAL_MONTHLY:
+ return "monthly";
+ case UsageStatsManager.INTERVAL_YEARLY:
+ return "yearly";
+ default:
+ return "?";
+ }
+ }
private static String eventToString(int eventType) {
switch (eventType) {
diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java
index d0e286042461..43da38f3648c 100644
--- a/telecomm/java/android/telecom/AudioState.java
+++ b/telecomm/java/android/telecom/AudioState.java
@@ -22,7 +22,8 @@ import android.os.Parcelable;
import java.util.Locale;
/**
- * Encapsulates all audio states during a call.
+ * Encapsulates the telecom audio state, including the current audio routing, supported audio
+ * routing and mute.
*/
public final class AudioState implements Parcelable {
/** Direct the audio stream through the device's earpiece. */
@@ -53,10 +54,10 @@ public final class AudioState implements Parcelable {
/** True if the call is muted, false otherwise. */
public final boolean isMuted;
- /** The route to use for the audio stream. */
+ /** The current audio route being used. */
public final int route;
- /** Bit vector of all routes supported by this call. */
+ /** Bit mask of all routes supported by this call. */
public final int supportedRouteMask;
public AudioState(boolean isMuted, int route, int supportedRouteMask) {
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 15cb786fba1c..003d5cd4876c 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -334,6 +334,19 @@ public abstract class Conference {
}
/**
+ * Retrieves the primary connection associated with the conference. The primary connection is
+ * the connection from which the conference will retrieve its current state.
+ *
+ * @return The primary connection.
+ */
+ public Connection getPrimaryConnection() {
+ if (mUnmodifiableChildConnections == null || mUnmodifiableChildConnections.isEmpty()) {
+ return null;
+ }
+ return mUnmodifiableChildConnections.get(0);
+ }
+
+ /**
* Inform this Conference that the state of its audio output has been changed externally.
*
* @param state The new audio state.
diff --git a/telecomm/java/android/telecom/ConferenceParticipant.aidl b/telecomm/java/android/telecom/ConferenceParticipant.aidl
new file mode 100644
index 000000000000..020c92320fa3
--- /dev/null
+++ b/telecomm/java/android/telecom/ConferenceParticipant.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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 android.telecom;
+
+/**
+ * {@hide}
+ */
+parcelable ConferenceParticipant;
diff --git a/telecomm/java/android/telecom/ConferenceParticipant.java b/telecomm/java/android/telecom/ConferenceParticipant.java
new file mode 100644
index 000000000000..db0f151e2016
--- /dev/null
+++ b/telecomm/java/android/telecom/ConferenceParticipant.java
@@ -0,0 +1,158 @@
+/*
+ * 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 android.telecom;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Parcelable representation of a participant's state in a conference call.
+ * @hide
+ */
+public class ConferenceParticipant implements Parcelable {
+
+ /**
+ * The conference participant's handle (e.g., phone number).
+ */
+ private final Uri mHandle;
+
+ /**
+ * The display name for the participant.
+ */
+ private final String mDisplayName;
+
+ /**
+ * The endpoint Uri which uniquely identifies this conference participant. E.g. for an IMS
+ * conference call, this is the endpoint URI for the participant on the IMS conference server.
+ */
+ private final Uri mEndpoint;
+
+ /**
+ * The state of the participant in the conference.
+ *
+ * @see android.telecom.Connection
+ */
+ private final int mState;
+
+ /**
+ * Creates an instance of {@code ConferenceParticipant}.
+ *
+ * @param handle The conference participant's handle (e.g., phone number).
+ * @param displayName The display name for the participant.
+ * @param endpoint The enpoint Uri which uniquely identifies this conference participant.
+ * @param state The state of the participant in the conference.
+ */
+ public ConferenceParticipant(Uri handle, String displayName, Uri endpoint, int state) {
+ mHandle = handle;
+ mDisplayName = displayName;
+ mEndpoint = endpoint;
+ mState = state;
+ }
+
+ /**
+ * Responsible for creating {@code ConferenceParticipant} objects for deserialized Parcels.
+ */
+ public static final Parcelable.Creator<ConferenceParticipant> CREATOR =
+ new Parcelable.Creator<ConferenceParticipant>() {
+
+ @Override
+ public ConferenceParticipant createFromParcel(Parcel source) {
+ ClassLoader classLoader = ParcelableCall.class.getClassLoader();
+ Uri handle = source.readParcelable(classLoader);
+ String displayName = source.readString();
+ Uri endpoint = source.readParcelable(classLoader);
+ int state = source.readInt();
+ return new ConferenceParticipant(handle, displayName, endpoint, state);
+ }
+
+ @Override
+ public ConferenceParticipant[] newArray(int size) {
+ return new ConferenceParticipant[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Writes the {@code ConferenceParticipant} to a parcel.
+ *
+ * @param dest The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mHandle, 0);
+ dest.writeString(mDisplayName);
+ dest.writeParcelable(mEndpoint, 0);
+ dest.writeInt(mState);
+ }
+
+ /**
+ * Builds a string representation of this instance.
+ *
+ * @return String representing the conference participant.
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[ConferenceParticipant Handle: ");
+ sb.append(mHandle);
+ sb.append(" DisplayName: ");
+ sb.append(mDisplayName);
+ sb.append(" Endpoint: ");
+ sb.append(mEndpoint);
+ sb.append(" State: ");
+ sb.append(mState);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ /**
+ * The conference participant's handle (e.g., phone number).
+ */
+ public Uri getHandle() {
+ return mHandle;
+ }
+
+ /**
+ * The display name for the participant.
+ */
+ public String getDisplayName() {
+ return mDisplayName;
+ }
+
+ /**
+ * The enpoint Uri which uniquely identifies this conference participant. E.g. for an IMS
+ * conference call, this is the endpoint URI for the participant on the IMS conference server.
+ */
+ public Uri getEndpoint() {
+ return mEndpoint;
+ }
+
+ /**
+ * The state of the participant in the conference.
+ *
+ * @see android.telecom.Connection
+ */
+ public int getState() {
+ return mState;
+ }
+}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 2932721f28b6..9bdbba8ea085 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -82,6 +82,9 @@ public abstract class Connection {
public void onConferenceableConnectionsChanged(
Connection c, List<Connection> conferenceableConnections) {}
public void onConferenceChanged(Connection c, Conference conference) {}
+ /** @hide */
+ public void onConferenceParticipantChanged(Connection c, ConferenceParticipant participant)
+ {}
}
/** @hide */
@@ -1117,4 +1120,16 @@ public abstract class Connection {
}
mConferenceableConnections.clear();
}
+
+ /**
+ * Notifies listeners of a change to a conference participant.
+ *
+ * @param conferenceParticipant The participant.
+ * @hide
+ */
+ protected final void updateConferenceParticipant(ConferenceParticipant conferenceParticipant) {
+ for (Listener l : mListeners) {
+ l.onConferenceParticipantChanged(this, conferenceParticipant);
+ }
+ }
}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 649533e66a79..4648d78fb674 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -40,8 +40,37 @@ import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
- * A {@link android.app.Service} that provides telephone connections to processes running on an
- * Android device.
+ * {@code ConnectionService} is an abstract service that should be implemented by any app which can
+ * make phone calls and want those calls to be integrated into the built-in phone app.
+ * Once implemented, the {@code ConnectionService} needs two additional steps before it will be
+ * integrated into the phone app:
+ * <p>
+ * 1. <i>Registration in AndroidManifest.xml</i>
+ * <br/>
+ * <pre>
+ * &lt;service android:name="com.example.package.MyConnectionService"
+ * android:label="@string/some_label_for_my_connection_service"
+ * android:permission="android.permission.BIND_CONNECTION_SERVICE"&gt;
+ * &lt;intent-filter&gt;
+ * &lt;action android:name="android.telecom.ConnectionService" /&gt;
+ * &lt;/intent-filter&gt;
+ * &lt;/service&gt;
+ * </pre>
+ * <p>
+ * 2. <i> Registration of {@link PhoneAccount} with {@link TelecomManager}.</i>
+ * <br/>
+ * See {@link PhoneAccount} and {@link TelecomManager#registerPhoneAccount} for more information.
+ * <p>
+ * Once registered and enabled by the user in the dialer settings, telecom will bind to a
+ * {@code ConnectionService} implementation when it wants that {@code ConnectionService} to place
+ * a call or the service has indicated that is has an incoming call through
+ * {@link TelecomManager#addNewIncomingCall}. The {@code ConnectionService} can then expect a call
+ * to {@link #onCreateIncomingConnection} or {@link #onCreateOutgoingConnection} wherein it
+ * should provide a new instance of a {@link Connection} object. It is through this
+ * {@link Connection} object that telecom receives state updates and the {@code ConnectionService}
+ * receives call-commands such as answer, reject, hold and disconnect.
+ * <p>
+ * When there are no more live calls, telecom will unbind from the {@code ConnectionService}.
*/
public abstract class ConnectionService extends Service {
/**
@@ -746,7 +775,9 @@ public abstract class ConnectionService extends Service {
/**
* Ask some other {@code ConnectionService} to create a {@code RemoteConnection} given an
- * incoming request. This is used to attach to existing incoming calls.
+ * incoming request. This is used by {@code ConnectionService}s that are registered with
+ * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} and want to be able to manage
+ * SIM-based incoming calls.
*
* @param connectionManagerPhoneAccount See description at
* {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
@@ -763,7 +794,9 @@ public abstract class ConnectionService extends Service {
/**
* Ask some other {@code ConnectionService} to create a {@code RemoteConnection} given an
- * outgoing request. This is used to initiate new outgoing calls.
+ * outgoing request. This is used by {@code ConnectionService}s that are registered with
+ * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} and want to be able to use the
+ * SIM-based {@code ConnectionService} to place its outgoing calls.
*
* @param connectionManagerPhoneAccount See description at
* {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
@@ -779,12 +812,19 @@ public abstract class ConnectionService extends Service {
}
/**
- * Adds two {@code RemoteConnection}s to some {@code RemoteConference}.
+ * Indicates to the relevant {@code RemoteConnectionService} that the specified
+ * {@link RemoteConnection}s should be merged into a conference call.
+ * <p>
+ * If the conference request is successful, the method {@link #onRemoteConferenceAdded} will
+ * be invoked.
+ *
+ * @param remoteConnection1 The first of the remote connections to conference.
+ * @param remoteConnection2 The second of the remote connections to conference.
*/
public final void conferenceRemoteConnections(
- RemoteConnection a,
- RemoteConnection b) {
- mRemoteConnectionManager.conferenceRemoteConnections(a, b);
+ RemoteConnection remoteConnection1,
+ RemoteConnection remoteConnection2) {
+ mRemoteConnectionManager.conferenceRemoteConnections(remoteConnection1, remoteConnection2);
}
/**
@@ -822,6 +862,40 @@ public abstract class ConnectionService extends Service {
}
/**
+ * Adds a connection created by the {@link ConnectionService} and informs telecom of the new
+ * connection.
+ *
+ * @param phoneAccountHandle The phone account handle for the connection.
+ * @param connection The connection to add.
+ */
+ public final void addExistingConnection(PhoneAccountHandle phoneAccountHandle,
+ Connection connection) {
+
+ String id = addExistingConnectionInternal(connection);
+ if (id != null) {
+ List<String> emptyList = new ArrayList<>(0);
+
+ ParcelableConnection parcelableConnection = new ParcelableConnection(
+ phoneAccountHandle,
+ connection.getState(),
+ connection.getCallCapabilities(),
+ connection.getAddress(),
+ connection.getAddressPresentation(),
+ connection.getCallerDisplayName(),
+ connection.getCallerDisplayNamePresentation(),
+ connection.getVideoProvider() == null ?
+ null : connection.getVideoProvider().getInterface(),
+ connection.getVideoState(),
+ connection.isRingbackRequested(),
+ connection.getAudioModeIsVoip(),
+ connection.getStatusHints(),
+ connection.getDisconnectCause(),
+ emptyList);
+ mAdapter.addExistingConnection(id, parcelableConnection);
+ }
+ }
+
+ /**
* Returns all the active {@code Connection}s for which this {@code ConnectionService}
* has taken responsibility.
*
@@ -903,9 +977,25 @@ public abstract class ConnectionService extends Service {
*/
public void onConference(Connection connection1, Connection connection2) {}
+ /**
+ * Indicates that a remote conference has been created for existing {@link RemoteConnection}s.
+ * When this method is invoked, this {@link ConnectionService} should create its own
+ * representation of the conference call and send it to telecom using {@link #addConference}.
+ * <p>
+ * This is only relevant to {@link ConnectionService}s which are registered with
+ * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}.
+ *
+ * @param conference The remote conference call.
+ */
public void onRemoteConferenceAdded(RemoteConference conference) {}
/**
+ * Called when an existing connection is added remotely.
+ * @param connection The existing connection which was added.
+ */
+ public void onRemoteExistingConnectionAdded(RemoteConnection connection) {}
+
+ /**
* @hide
*/
public boolean containsConference(Conference conference) {
@@ -917,6 +1007,11 @@ public abstract class ConnectionService extends Service {
onRemoteConferenceAdded(remoteConference);
}
+ /** {@hide} */
+ void addRemoteExistingConnection(RemoteConnection remoteConnection) {
+ onRemoteExistingConnectionAdded(remoteConnection);
+ }
+
private void onAccountsInitialized() {
mAreAccountsInitialized = true;
for (Runnable r : mPreInitializationConnectionRequests) {
@@ -925,6 +1020,18 @@ public abstract class ConnectionService extends Service {
mPreInitializationConnectionRequests.clear();
}
+ /**
+ * Adds an existing connection to the list of connections, identified by a new UUID.
+ *
+ * @param connection The connection.
+ * @return The UUID of the connection (e.g. the call-id).
+ */
+ private String addExistingConnectionInternal(Connection connection) {
+ String id = UUID.randomUUID().toString();
+ addConnection(id, connection);
+ return id;
+ }
+
private void addConnection(String callId, Connection connection) {
mConnectionById.put(callId, connection);
mIdByConnection.put(connection, callId);
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index c67617241f50..e67af8cf906d 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -344,4 +344,20 @@ final class ConnectionServiceAdapter implements DeathRecipient {
}
}
}
+
+ /**
+ * Informs telecom of an existing connection which was added by the {@link ConnectionService}.
+ *
+ * @param callId The unique ID of the call being added.
+ * @param connection The connection.
+ */
+ void addExistingConnection(String callId, ParcelableConnection connection) {
+ Log.v(this, "addExistingConnection: %s", callId);
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ adapter.addExistingConnection(callId, connection);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
}
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 217dbc3ac6f4..519a400f6447 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -57,6 +57,7 @@ final class ConnectionServiceAdapterServant {
private static final int MSG_SET_ADDRESS = 18;
private static final int MSG_SET_CALLER_DISPLAY_NAME = 19;
private static final int MSG_SET_CONFERENCEABLE_CONNECTIONS = 20;
+ private static final int MSG_ADD_EXISTING_CONNECTION = 21;
private final IConnectionServiceAdapter mDelegate;
@@ -199,6 +200,16 @@ final class ConnectionServiceAdapterServant {
}
break;
}
+ case MSG_ADD_EXISTING_CONNECTION: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.addExistingConnection(
+ (String) args.arg1, (ParcelableConnection) args.arg2);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
}
}
};
@@ -345,6 +356,15 @@ final class ConnectionServiceAdapterServant {
args.arg2 = conferenceableConnectionIds;
mHandler.obtainMessage(MSG_SET_CONFERENCEABLE_CONNECTIONS, args).sendToTarget();
}
+
+ @Override
+ public final void addExistingConnection(
+ String connectionId, ParcelableConnection connection) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = connectionId;
+ args.arg2 = connection;
+ mHandler.obtainMessage(MSG_ADD_EXISTING_CONNECTION, args).sendToTarget();
+ }
};
public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 9be01380956a..206046d6db0b 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -25,9 +25,10 @@ import java.util.Objects;
/**
* Describes the cause of a disconnected call. This always includes a code describing the generic
- * cause of the disconnect. Optionally, it may include a localized label and/or localized description
- * to display to the user which is provided by the {@link ConnectionService}. It also may contain a
- * reason for the the disconnect, which is intended for logging and not for display to the user.
+ * cause of the disconnect. Optionally, it may include a label and/or description to display to the
+ * user. It is the responsibility of the {@link ConnectionService} to provide localized versions of
+ * the label and description. It also may contain a reason for the disconnect, which is intended for
+ * logging and not for display to the user.
*/
public final class DisconnectCause implements Parcelable {
@@ -85,6 +86,7 @@ public final class DisconnectCause implements Parcelable {
/**
* Creates a new DisconnectCause.
+ *
* @param label The localized label to show to the user to explain the disconnect.
* @param code The code for the disconnect cause.
* @param description The localized description to show to the user to explain the disconnect.
diff --git a/telecomm/java/android/telecom/GatewayInfo.java b/telecomm/java/android/telecom/GatewayInfo.java
index 583c3e284787..7105602a0bba 100644
--- a/telecomm/java/android/telecom/GatewayInfo.java
+++ b/telecomm/java/android/telecom/GatewayInfo.java
@@ -23,12 +23,16 @@ import android.os.Parcelable;
import android.text.TextUtils;
/**
- * When calls are made, they may contain gateway information for services which route phone calls
- * through their own service/numbers. The data consists of a number to call and the package name of
- * the service. This data is used in two ways:
+ * Encapsulated gateway address information for outgoing call. When calls are made, the system
+ * provides a facility to specify two addresses for the call: one to display as the address being
+ * dialed and a separate (gateway) address to actually dial. Telecom provides this information to
+ * {@link ConnectionService}s when placing the call as an instance of {@code GatewayInfo}.
+ * <p>
+ * The data consists of an address to call, an address to display and the package name of the
+ * service. This data is used in two ways:
* <ol>
- * <li> Call the appropriate routing number
- * <li> Display information about how the call is being routed to the user
+ * <li> Call the appropriate gateway address.
+ * <li> Display information about how the call is being routed to the user.
* </ol>
*/
public class GatewayInfo implements Parcelable {
@@ -46,31 +50,39 @@ public class GatewayInfo implements Parcelable {
}
/**
- * Package name of the gateway provider service. used to place the call with.
+ * Package name of the gateway provider service that provided the gateway information.
+ * This can be used to identify the gateway address source and to load an appropriate icon when
+ * displaying gateway information in the in-call UI.
*/
public String getGatewayProviderPackageName() {
return mGatewayProviderPackageName;
}
/**
- * Gateway provider address to use when actually placing the call.
+ * Returns the gateway address to dial when placing the call.
*/
public Uri getGatewayAddress() {
return mGatewayAddress;
}
/**
- * The actual call address that the user is trying to connect to via the gateway.
+ * Returns the address that the user is trying to connect to via the gateway.
*/
public Uri getOriginalAddress() {
return mOriginalAddress;
}
+ /**
+ * Indicates whether this {@code GatewayInfo} instance contains any data. A returned value of
+ * false indicates that no gateway number is being used for the call.
+ */
public boolean isEmpty() {
return TextUtils.isEmpty(mGatewayProviderPackageName) || mGatewayAddress == null;
}
- /** Implement the Parcelable interface */
+ /**
+ * The Parcelable interface.
+ * */
public static final Parcelable.Creator<GatewayInfo> CREATOR =
new Parcelable.Creator<GatewayInfo> () {
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 768188b81c49..bc4cc8ce4e83 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -23,7 +23,16 @@ import android.os.Parcelable;
import java.util.Objects;
/**
- * The unique identifier for a {@link PhoneAccount}.
+ * The unique identifier for a {@link PhoneAccount}. A {@code PhoneAccountHandle} is made of two
+ * parts:
+ * <ul>
+ * <li>The component name of the associated {@link ConnectionService}.</li>
+ * <li>A string identifier that is unique across {@code PhoneAccountHandle}s with the same
+ * component name.</li>
+ * </ul>
+ *
+ * See {@link PhoneAccount},
+ * {@link TelecomManager#registerPhoneAccount TelecomManager.registerPhoneAccount}.
*/
public class PhoneAccountHandle implements Parcelable {
private ComponentName mComponentName;
diff --git a/telecomm/java/android/telecom/PhoneCapabilities.java b/telecomm/java/android/telecom/PhoneCapabilities.java
index 9c6750301909..3d3c6bd17324 100644
--- a/telecomm/java/android/telecom/PhoneCapabilities.java
+++ b/telecomm/java/android/telecom/PhoneCapabilities.java
@@ -17,8 +17,8 @@
package android.telecom;
/**
- * Defines capabilities a phone call can support, such as conference calling and video telephony.
- * Also defines properties of a phone call, such as whether it is using VoLTE technology.
+ * Defines capabilities for {@link Connection}s and {@link Conference}s such as hold, swap, and
+ * merge.
*/
public final class PhoneCapabilities {
/** Call can currently be put on hold or unheld. */
@@ -28,15 +28,22 @@ public final class PhoneCapabilities {
public static final int SUPPORT_HOLD = 0x00000002;
/**
- * Calls within a conference can be merged. Some connection services create a conference call
- * only after two calls have been merged. However, a conference call can also be added the
- * moment there are more than one call. CDMA calls are implemented in this way because the call
- * actions are more limited when more than one call exists. This flag allows merge to be exposed
- * as a capability on the conference call instead of individual calls.
+ * Calls within a conference can be merged. A {@link ConnectionService} has the option to
+ * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
+ * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
+ * capability allows a merge button to be shown while the conference call is in the foreground
+ * of the in-call UI.
+ * <p>
+ * This is only intended for use by a {@link Conference}.
*/
public static final int MERGE_CONFERENCE = 0x00000004;
- /** Calls withing a conference can be swapped between foreground and background. */
+ /**
+ * Calls within a conference can be swapped between foreground and background.
+ * See {@link #MERGE_CONFERENCE} for additional information.
+ * <p>
+ * This is only intended for use by a {@link Conference}.
+ */
public static final int SWAP_CONFERENCE = 0x00000008;
/** Call currently supports adding another call to this one. */
@@ -49,8 +56,8 @@ public final class PhoneCapabilities {
public static final int MUTE = 0x00000040;
/**
- * Call supports conference call management. This capability only applies to conference calls
- * which can have other calls as children.
+ * Call supports conference call management. This capability only applies to {@link Conference}
+ * calls which can have {@link Connection}s as children.
*/
public static final int MANAGE_CONFERENCE = 0x00000080;
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 9a094df0376d..816e2bf6b418 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -407,6 +407,29 @@ public final class RemoteConnection {
}
/**
+ * @hide
+ */
+ RemoteConnection(String callId, IConnectionService connectionService,
+ ParcelableConnection connection) {
+ mConnectionId = callId;
+ mConnectionService = connectionService;
+ mConnected = true;
+ mState = connection.getState();
+ mDisconnectCause = connection.getDisconnectCause();
+ mRingbackRequested = connection.isRingbackRequested();
+ mCallCapabilities = connection.getCapabilities();
+ mVideoState = connection.getVideoState();
+ mVideoProvider = new RemoteConnection.VideoProvider(connection.getVideoProvider());
+ mIsVoipAudioMode = connection.getIsVoipAudioMode();
+ mStatusHints = connection.getStatusHints();
+ mAddress = connection.getHandle();
+ mAddressPresentation = connection.getHandlePresentation();
+ mCallerDisplayName = connection.getCallerDisplayName();
+ mCallerDisplayNamePresentation = connection.getCallerDisplayNamePresentation();
+ mConference = null;
+ }
+
+ /**
* Create a RemoteConnection which is used for failed connections. Note that using it for any
* "real" purpose will almost certainly fail. Callers should note the failure and act
* accordingly (moving on to another RemoteConnection, for example)
@@ -415,7 +438,7 @@ public final class RemoteConnection {
* @hide
*/
RemoteConnection(DisconnectCause disconnectCause) {
- this("NULL", null, null);
+ mConnectionId = "NULL";
mConnected = false;
mState = Connection.STATE_DISCONNECTED;
mDisconnectCause = disconnectCause;
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index af4ee22ef2af..4bb78c010303 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -41,8 +41,9 @@ import java.util.UUID;
*/
final class RemoteConnectionService {
+ // Note: Casting null to avoid ambiguous constructor reference.
private static final RemoteConnection NULL_CONNECTION =
- new RemoteConnection("NULL", null, null);
+ new RemoteConnection("NULL", null, (ConnectionRequest) null);
private static final RemoteConference NULL_CONFERENCE =
new RemoteConference("NULL", null);
@@ -286,6 +287,15 @@ final class RemoteConnectionService {
.setConferenceableConnections(conferenceable);
}
}
+
+ @Override
+ public void addExistingConnection(String callId, ParcelableConnection connection) {
+ // TODO: add contents of this method
+ RemoteConnection remoteConnction = new RemoteConnection(callId,
+ mOutgoingConnectionServiceRpc, connection);
+
+ mOurConnectionServiceImpl.addRemoteExistingConnection(remoteConnction);
+ }
};
private final ConnectionServiceAdapterServant mServant =
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index bc51a705619b..4eac5ac4a570 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -31,7 +31,17 @@ import java.util.Collections;
import java.util.List;
/**
- * Provides access to Telecom-related functionality.
+ * Provides access to information about active calls and registration/call-management functionality.
+ * Apps can use methods in this class to determine the current call state. Apps can also register new
+ * {@link PhoneAccount}s and get a listing of existing {@link PhoneAccount}s.
+ * <p>
+ * Apps do not instantiate this class directly; instead, they retrieve a reference to an instance
+ * through {@link Context#getSystemService Context.getSystemService(Context.TELECOM_SERVICE)}.
+ * <p>
+ * Note that access to some telecom information is permission-protected. Your app cannot access the
+ * protected information or gain access to protected functionality unless it has the appropriate
+ * permissions declared in its manifest file. Where permissions apply, they are noted in the method
+ * descriptions.
*/
public class TelecomManager {
@@ -583,7 +593,16 @@ public class TelecomManager {
}
/**
- * Register a {@link PhoneAccount} for use by the system.
+ * Register a {@link PhoneAccount} for use by the system. When registering
+ * {@link PhoneAccount}s, existing registrations will be overwritten if the
+ * {@link PhoneAccountHandle} matches that of a {@link PhoneAccount} which is already
+ * registered. Once registered, the {@link PhoneAccount} is listed to the user as an option
+ * when placing calls. The user may still need to enable the {@link PhoneAccount} within
+ * the phone app settings before the account is usable.
+ * <p>
+ * A {@link SecurityException} will be thrown if an app tries to register a
+ * {@link PhoneAccountHandle} where the package name specified within
+ * {@link PhoneAccountHandle#getComponentName()} does not match the package name of the app.
*
* @param account The complete {@link PhoneAccount}.
*/
@@ -876,6 +895,7 @@ public class TelecomManager {
* Processes the specified dial string as an MMI code.
* MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#".
* Some of these sequences launch special behavior through handled by Telephony.
+ * This method uses the default subscription.
* <p>
* Requires that the method-caller be set as the system dialer app.
* </p>
@@ -896,6 +916,31 @@ public class TelecomManager {
}
/**
+ * Processes the specified dial string as an MMI code.
+ * MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#".
+ * Some of these sequences launch special behavior through handled by Telephony.
+ * <p>
+ * Requires that the method-caller be set as the system dialer app.
+ * </p>
+ *
+ * @param accountHandle The handle for the account the MMI code should apply to.
+ * @param dialString The digits to dial.
+ * @return True if the digits were processed as an MMI code, false otherwise.
+ *
+ */
+ public boolean handleMmi(PhoneAccountHandle accountHandle, String dialString) {
+ ITelecomService service = getTelecomService();
+ if (service != null) {
+ try {
+ return service.handlePinMmiForPhoneAccount(accountHandle, dialString);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecomService#handlePinMmi", e);
+ }
+ }
+ return false;
+ }
+
+ /**
* Removes the missed-call notification if one is present.
* <p>
* Requires that the method-caller be set as the system dialer app.
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 5daa568bffc5..0d6b3d9bbb12 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -77,4 +77,6 @@ oneway interface IConnectionServiceAdapter {
void setCallerDisplayName(String callId, String callerDisplayName, int presentation);
void setConferenceableConnections(String callId, in List<String> conferenceableCallIds);
+
+ void addExistingConnection(String callId, in ParcelableConnection connection);
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 91f44b9a055b..fd472130deb4 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -169,6 +169,11 @@ interface ITelecomService {
boolean handlePinMmi(String dialString);
/**
+ * @see TelecomServiceImpl#handleMmi
+ */
+ boolean handlePinMmiForPhoneAccount(in PhoneAccountHandle accountHandle, String dialString);
+
+ /**
* @see TelecomServiceImpl#isTtySupported
*/
boolean isTtySupported();
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 3363ca678c6a..17db3fb97d7b 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -20,6 +20,7 @@ import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Rlog;
+import android.content.res.Resources;
/**
* Contains phone signal strength related information.
@@ -50,6 +51,11 @@ public class SignalStrength implements Parcelable {
//Use int max, as -1 is a valid value in signal strength
public static final int INVALID = 0x7FFFFFFF;
+ private static final int RSRP_THRESH_TYPE_STRICT = 0;
+ private static final int[] RSRP_THRESH_STRICT = new int[] {-140, -115, -105, -95, -85, -44};
+ private static final int[] RSRP_THRESH_LENIENT = new int[] {-140, -128, -118, -108, -98, -44};
+
+
private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
private int mGsmBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5
private int mCdmaDbm; // This value is the RSSI value
@@ -745,12 +751,21 @@ public class SignalStrength implements Parcelable {
*/
int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, rsrpIconLevel = -1, snrIconLevel = -1;
- if (mLteRsrp > -44) rsrpIconLevel = -1;
- else if (mLteRsrp >= -85) rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
- else if (mLteRsrp >= -95) rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
- else if (mLteRsrp >= -105) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
- else if (mLteRsrp >= -115) rsrpIconLevel = SIGNAL_STRENGTH_POOR;
- else if (mLteRsrp >= -140) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ int rsrpThreshType = Resources.getSystem().getInteger(com.android.internal.R.integer.
+ config_LTE_RSRP_threshold_type);
+ int[] threshRsrp;
+ if (rsrpThreshType == RSRP_THRESH_TYPE_STRICT) {
+ threshRsrp = RSRP_THRESH_STRICT;
+ } else {
+ threshRsrp = RSRP_THRESH_LENIENT;
+ }
+
+ if (mLteRsrp > threshRsrp[5]) rsrpIconLevel = -1;
+ else if (mLteRsrp >= threshRsrp[4]) rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
+ else if (mLteRsrp >= threshRsrp[3]) rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
+ else if (mLteRsrp >= threshRsrp[2]) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
+ else if (mLteRsrp >= threshRsrp[1]) rsrpIconLevel = SIGNAL_STRENGTH_POOR;
+ else if (mLteRsrp >= threshRsrp[0]) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
/*
* Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5
@@ -789,6 +804,7 @@ public class SignalStrength implements Parcelable {
else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR;
+
if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
+ rssiIconLevel);
return rssiIconLevel;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a3546ed16c45..0246a2da1359 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3336,6 +3336,17 @@ public class TelephonyManager {
/** @hide */
@SystemApi
+ public boolean handlePinMmiForSubscriber(int subId, String dialString) {
+ try {
+ return getITelephony().handlePinMmiForSubscriber(subId, dialString);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#handlePinMmi", e);
+ }
+ return false;
+ }
+
+ /** @hide */
+ @SystemApi
public void toggleRadioOnOff() {
try {
getITelephony().toggleRadioOnOff();
diff --git a/telephony/java/com/android/ims/ImsConferenceState.java b/telephony/java/com/android/ims/ImsConferenceState.java
index f708d5bc0530..c57ef98abb4d 100644
--- a/telephony/java/com/android/ims/ImsConferenceState.java
+++ b/telephony/java/com/android/ims/ImsConferenceState.java
@@ -24,6 +24,8 @@ import java.util.Set;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telecom.Call;
+import android.telecom.Connection;
/**
* Provides the conference information (defined in RFC 4575) for IMS conference call.
@@ -139,4 +141,30 @@ public class ImsConferenceState implements Parcelable {
return new ImsConferenceState[size];
}
};
+
+ /**
+ * Translates an {@code ImsConferenceState} status type to a telecom connection state.
+ *
+ * @param status The status type.
+ * @return The corresponding {@link android.telecom.Connection} state.
+ */
+ public static int getConnectionStateForStatus(String status) {
+ if (status.equals(STATUS_PENDING)) {
+ return Connection.STATE_INITIALIZING;
+ } else if (status.equals(STATUS_DIALING_IN)) {
+ return Connection.STATE_RINGING;
+ } else if (status.equals(STATUS_ALERTING) ||
+ status.equals(STATUS_DIALING_OUT)) {
+ return Connection.STATE_DIALING;
+ } else if (status.equals(STATUS_ON_HOLD)) {
+ return Connection.STATE_HOLDING;
+ } else if (status.equals(STATUS_CONNECTED) ||
+ status.equals(STATUS_MUTED_VIA_FOCUS) ||
+ status.equals(STATUS_DISCONNECTING)) {
+ return Connection.STATE_ACTIVE;
+ } else if (status.equals(STATUS_DISCONNECTED)) {
+ return Connection.STATE_DISCONNECTED;
+ }
+ return Call.STATE_ACTIVE;
+ }
}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 7f1dc71cf2ab..7531d7b846ed 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -733,6 +733,14 @@ public class MockPackageManager extends PackageManager {
* @hide
*/
@Override
+ public boolean isUpgrade() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
public void installPackage(Uri packageURI, PackageInstallObserver observer,
int flags, String installerPackageName) {
throw new UnsupportedOperationException();
diff --git a/tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java b/tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java
new file mode 100644
index 000000000000..d8a6ffc3f261
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/animation/AnimatorInflater_Delegate.java
@@ -0,0 +1,59 @@
+/*
+ * 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 android.animation;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.content.res.Resources.Theme;
+import android.util.AttributeSet;
+
+/**
+ * Delegate providing alternate implementation to static methods in {@link AnimatorInflater}.
+ */
+public class AnimatorInflater_Delegate {
+
+ @LayoutlibDelegate
+ /*package*/ static Animator loadAnimator(Context context, int id)
+ throws NotFoundException {
+ return loadAnimator(context.getResources(), context.getTheme(), id);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static Animator loadAnimator(Resources resources, Theme theme, int id)
+ throws NotFoundException {
+ return loadAnimator(resources, theme, id, 1);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static Animator loadAnimator(Resources resources, Theme theme, int id,
+ float pathErrorScale) throws NotFoundException {
+ // This is a temporary fix to http://b.android.com/77865. This skips loading the
+ // animation altogether.
+ // TODO: Remove this override when Path.approximate() is supported.
+ return new FakeAnimator();
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static ValueAnimator loadAnimator(Resources res, Theme theme,
+ AttributeSet attrs, ValueAnimator anim, float pathErrorScale)
+ throws NotFoundException {
+ return anim;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/animation/FakeAnimator.java b/tools/layoutlib/bridge/src/android/animation/FakeAnimator.java
new file mode 100644
index 000000000000..78aedc5a3102
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/animation/FakeAnimator.java
@@ -0,0 +1,52 @@
+/*
+ * 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 android.animation;
+
+/**
+ * A fake implementation of Animator which doesn't do anything.
+ */
+public class FakeAnimator extends Animator {
+ @Override
+ public long getStartDelay() {
+ return 0;
+ }
+
+ @Override
+ public void setStartDelay(long startDelay) {
+
+ }
+
+ @Override
+ public Animator setDuration(long duration) {
+ return this;
+ }
+
+ @Override
+ public long getDuration() {
+ return 0;
+ }
+
+ @Override
+ public void setInterpolator(TimeInterpolator value) {
+
+ }
+
+ @Override
+ public boolean isRunning() {
+ return false;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java
index 914a359e3171..e0d3b8cd4de4 100644
--- a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java
@@ -38,8 +38,4 @@ public class AssetManager_Delegate {
Resources_Theme_Delegate.getDelegateManager().removeJavaReferenceFor(theme);
}
- @LayoutlibDelegate
- /*package*/ static void applyThemeStyle(long theme, int styleRes, boolean force) {
- Resources_Theme_Delegate.getDelegateManager().getDelegate(theme).force = force;
- }
}
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
index dd573be4a1fe..66126af47663 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
@@ -163,7 +163,7 @@ public final class BridgeResources extends Resources {
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
- return ResourceHelper.getDrawable(value.getSecond(), mContext);
+ return ResourceHelper.getDrawable(value.getSecond(), mContext, theme);
}
// id was not found or not resolved. Throw a NotFoundException.
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 28a109dec398..a2bd6d7840d0 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -32,6 +32,7 @@ import com.android.resources.ResourceType;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.content.res.Resources.Theme;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.util.TypedValue;
@@ -116,6 +117,13 @@ public final class BridgeTypedArray extends TypedArray {
}
/**
+ * Set the theme to be used for inflating drawables.
+ */
+ public void setTheme(Theme theme) {
+ mTheme = theme;
+ }
+
+ /**
* Return the number of values in this array.
*/
@Override
@@ -663,7 +671,7 @@ public final class BridgeTypedArray extends TypedArray {
}
ResourceValue value = mResourceData[index];
- return ResourceHelper.getDrawable(value, mContext);
+ return ResourceHelper.getDrawable(value, mContext, mTheme);
}
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
index f4a9f52e5493..4bd83e92fa3c 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
@@ -39,9 +39,6 @@ import android.util.TypedValue;
*/
public class Resources_Theme_Delegate {
- // Whether to use the Theme.mThemeResId as primary theme.
- boolean force;
-
// ---- delegate manager ----
private static final DelegateManager<Resources_Theme_Delegate> sManager =
@@ -58,7 +55,8 @@ public class Resources_Theme_Delegate {
Resources thisResources, Theme thisTheme,
int[] attrs) {
boolean changed = setupResources(thisTheme);
- TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
+ BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
+ ta.setTheme(thisTheme);
restoreResources(changed);
return ta;
}
@@ -69,7 +67,9 @@ public class Resources_Theme_Delegate {
int resid, int[] attrs)
throws NotFoundException {
boolean changed = setupResources(thisTheme);
- TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs);
+ BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid,
+ attrs);
+ ta.setTheme(thisTheme);
restoreResources(changed);
return ta;
}
@@ -79,8 +79,9 @@ public class Resources_Theme_Delegate {
Resources thisResources, Theme thisTheme,
AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
boolean changed = setupResources(thisTheme);
- TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(set, attrs,
- defStyleAttr, defStyleRes);
+ BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(set,
+ attrs, defStyleAttr, defStyleRes);
+ ta.setTheme(thisTheme);
restoreResources(changed);
return ta;
}
@@ -91,8 +92,8 @@ public class Resources_Theme_Delegate {
int resid, TypedValue outValue,
boolean resolveRefs) {
boolean changed = setupResources(thisTheme);
- boolean found = RenderSessionImpl.getCurrentContext().resolveThemeAttribute(
- resid, outValue, resolveRefs);
+ boolean found = RenderSessionImpl.getCurrentContext().resolveThemeAttribute(resid,
+ outValue, resolveRefs);
restoreResources(changed);
return found;
}
@@ -107,14 +108,29 @@ public class Resources_Theme_Delegate {
// ---- private helper methods ----
private static boolean setupResources(Theme thisTheme) {
- Resources_Theme_Delegate themeDelegate = sManager.getDelegate(thisTheme.getNativeTheme());
- StyleResourceValue style = resolveStyle(thisTheme.getAppliedStyleResId());
- if (style != null) {
- RenderSessionImpl.getCurrentContext().getRenderResources()
- .applyStyle(style, themeDelegate.force);
- return true;
+ // Key is a space-separated list of theme ids applied that have been merged into the
+ // BridgeContext's theme to make thisTheme.
+ String[] appliedStyles = thisTheme.getKey().split(" ");
+ boolean changed = false;
+ for (String s : appliedStyles) {
+ if (s.isEmpty()) {
+ continue;
+ }
+ // See the definition of force parameter in Theme.applyStyle().
+ boolean force = false;
+ if (s.charAt(s.length() - 1) == '!') {
+ force = true;
+ s = s.substring(0, s.length() - 1);
+ }
+ int styleId = Integer.parseInt(s, 16);
+ StyleResourceValue style = resolveStyle(styleId);
+ if (style != null) {
+ RenderSessionImpl.getCurrentContext().getRenderResources().applyStyle(style, force);
+ changed = true;
+ }
+
}
- return false;
+ return changed;
}
private static void restoreResources(boolean changed) {
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 04a52ea2125d..d8042308ce94 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
@@ -115,7 +115,7 @@ public final class BridgeContext extends Context {
private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
// cache for TypedArray generated from IStyleResourceValue object
- private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
+ private Map<int[], Map<Integer, BridgeTypedArray>> mTypedArrayCache;
private BridgeInflater mBridgeInflater;
private BridgeContentResolver mContentResolver;
@@ -467,7 +467,7 @@ public final class BridgeContext extends Context {
@Override
- public final TypedArray obtainStyledAttributes(int[] attrs) {
+ public final BridgeTypedArray obtainStyledAttributes(int[] attrs) {
// No style is specified here, so create the typed array based on the default theme
// and the styles already applied to it. A null value of style indicates that the default
// theme should be used.
@@ -475,7 +475,7 @@ public final class BridgeContext extends Context {
}
@Override
- public final TypedArray obtainStyledAttributes(int resid, int[] attrs)
+ public final BridgeTypedArray obtainStyledAttributes(int resid, int[] attrs)
throws Resources.NotFoundException {
// get the StyleResourceValue based on the resId;
StyleResourceValue style = getStyleByDynamicId(resid);
@@ -485,9 +485,9 @@ public final class BridgeContext extends Context {
}
if (mTypedArrayCache == null) {
- mTypedArrayCache = new HashMap<int[], Map<Integer,TypedArray>>();
+ mTypedArrayCache = new HashMap<int[], Map<Integer,BridgeTypedArray>>();
- Map<Integer, TypedArray> map = new HashMap<Integer, TypedArray>();
+ Map<Integer, BridgeTypedArray> map = new HashMap<Integer, BridgeTypedArray>();
mTypedArrayCache.put(attrs, map);
BridgeTypedArray ta = createStyleBasedTypedArray(style, attrs);
@@ -497,14 +497,14 @@ public final class BridgeContext extends Context {
}
// get the 2nd map
- Map<Integer, TypedArray> map = mTypedArrayCache.get(attrs);
+ Map<Integer, BridgeTypedArray> map = mTypedArrayCache.get(attrs);
if (map == null) {
- map = new HashMap<Integer, TypedArray>();
+ map = new HashMap<Integer, BridgeTypedArray>();
mTypedArrayCache.put(attrs, map);
}
// get the array from the 2nd map
- TypedArray ta = map.get(resid);
+ BridgeTypedArray ta = map.get(resid);
if (ta == null) {
ta = createStyleBasedTypedArray(style, attrs);
@@ -515,12 +515,12 @@ public final class BridgeContext extends Context {
}
@Override
- public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) {
+ public final BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) {
return obtainStyledAttributes(set, attrs, 0, 0);
}
@Override
- public TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs,
+ public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs,
int defStyleAttr, int defStyleRes) {
Map<String, String> defaultPropMap = null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 22265a30e9ac..05a6fd63f77e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -145,4 +145,9 @@ public class BridgePowerManager implements IPowerManager {
public void wakeUp(long time) throws RemoteException {
// pass for now.
}
+
+ @Override
+ public void boostScreenBrightness(long time) throws RemoteException {
+ // pass for now.
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index 997b1996259b..4c4454dc494a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -95,6 +95,10 @@ public final class BridgeWindow implements IWindow {
}
@Override
+ public void dispatchWindowShown() {
+ }
+
+ @Override
public IBinder asBinder() {
// pass for now.
return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 22f8e1c9defe..677c74401e80 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -32,6 +32,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.content.res.ColorStateList;
+import android.content.res.Resources.Theme;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
import android.graphics.NinePatch_Delegate;
@@ -166,6 +167,17 @@ public final class ResourceHelper {
* @param context the current context
*/
public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
+ return getDrawable(value, context, null);
+ }
+
+ /**
+ * Returns a drawable from the given value.
+ * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable,
+ * or an hexadecimal color
+ * @param context the current context
+ * @param theme the theme to be used to inflate the drawable.
+ */
+ public static Drawable getDrawable(ResourceValue value, BridgeContext context, Theme theme) {
if (value == null) {
return null;
}
@@ -209,7 +221,7 @@ public final class ResourceHelper {
BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
parser, context, value.isFramework());
try {
- return Drawable.createFromXml(context.getResources(), blockParser);
+ return Drawable.createFromXml(context.getResources(), blockParser, theme);
} finally {
blockParser.ensurePopped();
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index f20b890322be..2fcdf345901d 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -137,13 +137,13 @@ public final class CreateInfo implements ICreateInfo {
* The list of methods to rewrite as delegates.
*/
public final static String[] DELEGATE_METHODS = new String[] {
+ "android.animation.AnimatorInflater#loadAnimator", // TODO: remove when Path.approximate() is supported.
"android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
"android.content.res.Resources$Theme#obtainStyledAttributes",
"android.content.res.Resources$Theme#resolveAttribute",
"android.content.res.Resources$Theme#resolveAttributes",
"android.content.res.AssetManager#newTheme",
"android.content.res.AssetManager#deleteTheme",
- "android.content.res.AssetManager#applyThemeStyle",
"android.content.res.TypedArray#getValueAt",
"android.content.res.TypedArray#obtain",
"android.graphics.BitmapFactory#finishDecode",