summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk25
-rw-r--r--cmds/bootanimation/audioplay.cpp16
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java2
-rw-r--r--core/java/android/accounts/AccountManager.java4
-rw-r--r--core/java/android/app/ActivityManagerNative.java22
-rw-r--r--core/java/android/app/ActivityThread.java46
-rw-r--r--core/java/android/app/ApplicationThreadNative.java6
-rw-r--r--core/java/android/app/DownloadManager.java6
-rw-r--r--core/java/android/app/IActivityManager.java13
-rw-r--r--core/java/android/app/IApplicationThread.java3
-rw-r--r--core/java/android/app/LocalActivityManager.java2
-rw-r--r--core/java/android/net/ConnectivityManager.java9
-rw-r--r--core/java/android/net/NetworkCapabilities.java35
-rw-r--r--core/java/android/os/PatternMatcher.java382
-rw-r--r--core/java/android/os/RecoverySystem.java6
-rw-r--r--core/java/android/os/RemoteCallbackList.java26
-rwxr-xr-xcore/java/android/provider/Settings.java6
-rw-r--r--core/java/android/view/Surface.java12
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java10
-rw-r--r--core/java/android/widget/NumberPicker.java60
-rw-r--r--core/java/android/widget/PopupWindow.java15
-rw-r--r--core/java/com/android/internal/util/WakeupMessage.java2
-rw-r--r--core/java/com/android/internal/widget/WatchListDecorLayout.java5
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp6
-rw-r--r--core/jni/android/graphics/Bitmap.h4
-rw-r--r--core/jni/android/graphics/Graphics.cpp9
-rw-r--r--core/jni/android/graphics/GraphicsJNI.h2
-rw-r--r--core/res/res/anim-watch/progress_indeterminate_material.xml42
-rw-r--r--core/res/res/anim-watch/progress_indeterminate_rotation_material.xml24
-rw-r--r--core/res/res/drawable-hdpi/watch_switch_track_mtrl_alpha.png (renamed from core/res/res/drawable-hdpi/watch_switch_track_mtrl.png)bin910 -> 910 bytes
-rw-r--r--core/res/res/drawable-xhdpi/watch_switch_track_mtrl_alpha.png (renamed from core/res/res/drawable-xhdpi/watch_switch_track_mtrl.png)bin1248 -> 1248 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/watch_switch_track_mtrl_alpha.png (renamed from core/res/res/drawable-xxhdpi/watch_switch_track_mtrl.png)bin1992 -> 1992 bytes
-rw-r--r--core/res/res/drawable/watch_switch_track_material.xml (renamed from core/res/res/color/watch_switch_track_color_material.xml)14
-rw-r--r--core/res/res/interpolator-watch/progress_indeterminate_rotation_interpolator.xml18
-rw-r--r--core/res/res/interpolator-watch/trim_end_interpolator.xml18
-rw-r--r--core/res/res/interpolator-watch/trim_offset_interpolator.xml18
-rw-r--r--core/res/res/interpolator-watch/trim_start_interpolator.xml18
-rw-r--r--core/res/res/layout-watch/preference_widget_switch.xml3
-rw-r--r--core/res/res/values-af/strings.xml5
-rw-r--r--core/res/res/values-am/strings.xml5
-rw-r--r--core/res/res/values-ar/strings.xml4
-rw-r--r--core/res/res/values-az-rAZ/strings.xml4
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml5
-rw-r--r--core/res/res/values-be-rBY/strings.xml4
-rw-r--r--core/res/res/values-bg/strings.xml4
-rw-r--r--core/res/res/values-bn-rBD/strings.xml4
-rw-r--r--core/res/res/values-bs-rBA/strings.xml4
-rw-r--r--core/res/res/values-ca/strings.xml4
-rw-r--r--core/res/res/values-cs/strings.xml5
-rw-r--r--core/res/res/values-da/strings.xml4
-rw-r--r--core/res/res/values-de/strings.xml4
-rw-r--r--core/res/res/values-el/strings.xml4
-rw-r--r--core/res/res/values-en-rAU/strings.xml4
-rw-r--r--core/res/res/values-en-rGB/strings.xml4
-rw-r--r--core/res/res/values-en-rIN/strings.xml4
-rw-r--r--core/res/res/values-es-rUS/strings.xml5
-rw-r--r--core/res/res/values-es/strings.xml4
-rw-r--r--core/res/res/values-et-rEE/strings.xml4
-rw-r--r--core/res/res/values-eu-rES/strings.xml5
-rw-r--r--core/res/res/values-fa/strings.xml10
-rw-r--r--core/res/res/values-fi/strings.xml4
-rw-r--r--core/res/res/values-fr-rCA/strings.xml5
-rw-r--r--core/res/res/values-fr/strings.xml5
-rw-r--r--core/res/res/values-gl-rES/strings.xml5
-rw-r--r--core/res/res/values-gu-rIN/strings.xml4
-rw-r--r--core/res/res/values-hi/strings.xml4
-rw-r--r--core/res/res/values-hr/strings.xml4
-rw-r--r--core/res/res/values-hu/strings.xml4
-rw-r--r--core/res/res/values-hy-rAM/strings.xml4
-rw-r--r--core/res/res/values-in/strings.xml4
-rw-r--r--core/res/res/values-is-rIS/strings.xml4
-rw-r--r--core/res/res/values-it/strings.xml4
-rw-r--r--core/res/res/values-iw/strings.xml4
-rw-r--r--core/res/res/values-ja/strings.xml6
-rw-r--r--core/res/res/values-ka-rGE/strings.xml4
-rw-r--r--core/res/res/values-kk-rKZ/strings.xml4
-rw-r--r--core/res/res/values-km-rKH/strings.xml5
-rw-r--r--core/res/res/values-kn-rIN/strings.xml4
-rw-r--r--core/res/res/values-ko/strings.xml5
-rw-r--r--core/res/res/values-ky-rKG/strings.xml5
-rw-r--r--core/res/res/values-lo-rLA/strings.xml5
-rw-r--r--core/res/res/values-lt/strings.xml4
-rw-r--r--core/res/res/values-lv/strings.xml4
-rwxr-xr-xcore/res/res/values-mcc311-mnc480/config.xml7
-rw-r--r--core/res/res/values-mcc722-mnc36/config.xml25
-rw-r--r--core/res/res/values-mk-rMK/strings.xml4
-rw-r--r--core/res/res/values-ml-rIN/strings.xml5
-rw-r--r--core/res/res/values-mn-rMN/strings.xml4
-rw-r--r--core/res/res/values-mr-rIN/strings.xml4
-rw-r--r--core/res/res/values-ms-rMY/strings.xml5
-rw-r--r--core/res/res/values-my-rMM/strings.xml4
-rw-r--r--core/res/res/values-nb/strings.xml4
-rw-r--r--core/res/res/values-ne-rNP/strings.xml4
-rw-r--r--core/res/res/values-nl/strings.xml4
-rw-r--r--core/res/res/values-pa-rIN/strings.xml4
-rw-r--r--core/res/res/values-pl/strings.xml4
-rw-r--r--core/res/res/values-pt-rBR/strings.xml5
-rw-r--r--core/res/res/values-pt-rPT/strings.xml4
-rw-r--r--core/res/res/values-pt/strings.xml5
-rw-r--r--core/res/res/values-ro/strings.xml4
-rw-r--r--core/res/res/values-ru/strings.xml4
-rw-r--r--core/res/res/values-si-rLK/strings.xml4
-rw-r--r--core/res/res/values-sk/strings.xml4
-rw-r--r--core/res/res/values-sl/strings.xml5
-rw-r--r--core/res/res/values-sq-rAL/strings.xml4
-rw-r--r--core/res/res/values-sr/strings.xml5
-rw-r--r--core/res/res/values-sv/strings.xml4
-rw-r--r--core/res/res/values-sw/strings.xml5
-rw-r--r--core/res/res/values-ta-rIN/strings.xml4
-rw-r--r--core/res/res/values-te-rIN/strings.xml4
-rw-r--r--core/res/res/values-th/strings.xml4
-rw-r--r--core/res/res/values-tl/strings.xml4
-rw-r--r--core/res/res/values-tr/strings.xml5
-rw-r--r--core/res/res/values-uk/strings.xml4
-rw-r--r--core/res/res/values-ur-rPK/strings.xml5
-rw-r--r--core/res/res/values-uz-rUZ/strings.xml5
-rw-r--r--core/res/res/values-vi/strings.xml4
-rw-r--r--core/res/res/values-watch/donottranslate.xml22
-rw-r--r--core/res/res/values-watch/styles_material.xml5
-rw-r--r--core/res/res/values-zh-rCN/strings.xml5
-rw-r--r--core/res/res/values-zh-rHK/strings.xml4
-rw-r--r--core/res/res/values-zh-rTW/strings.xml5
-rw-r--r--core/res/res/values-zu/strings.xml4
-rw-r--r--core/res/res/values/config.xml8
-rw-r--r--core/res/res/values/donottranslate.xml3
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--core/tests/coretests/src/android/os/OsTests.java1
-rw-r--r--core/tests/coretests/src/android/os/PatternMatcherTest.java234
-rw-r--r--docs/html/about/dashboards/index.jd50
-rwxr-xr-xdocs/html/guide/topics/location/strategies.jd76
-rwxr-xr-xdocs/html/guide/topics/manifest/uses-feature-element.jd32
-rw-r--r--docs/html/guide/topics/media/camera.jd10
-rw-r--r--docs/html/images/training/ctl-config.pngbin47699 -> 72159 bytes
-rw-r--r--docs/html/images/training/tv/playback/onboarding-fragment-diagram.pngbin0 -> 67583 bytes
-rw-r--r--docs/html/images/training/tv/playback/onboarding-fragment.pngbin0 -> 91531 bytes
-rw-r--r--docs/html/images/training/tv/playback/onboarding-fragment_2x.pngbin0 -> 302265 bytes
-rw-r--r--docs/html/topic/libraries/data-binding/index.jd4
-rwxr-xr-xdocs/html/topic/libraries/support-library/features.jd42
-rw-r--r--docs/html/topic/libraries/support-library/revisions.jd64
-rw-r--r--docs/html/training/_book.yaml9
-rw-r--r--docs/html/training/constraint-layout/images/alignment-constraint-offset_2x.pngbin0 -> 8218 bytes
-rw-r--r--docs/html/training/constraint-layout/images/alignment-constraint_2x.pngbin0 -> 7172 bytes
-rw-r--r--docs/html/training/constraint-layout/images/baseline-constraint_2x.pngbin0 -> 5136 bytes
-rw-r--r--docs/html/training/constraint-layout/images/constraint-fail-fixed_2x.pngbin0 -> 9688 bytes
-rw-r--r--docs/html/training/constraint-layout/images/constraint-fail_2x.pngbin0 -> 9419 bytes
-rw-r--r--docs/html/training/constraint-layout/images/layout-editor-convert-to-constraint_2x.pngbin0 -> 21264 bytes
-rw-r--r--docs/html/training/constraint-layout/images/layout-editor-margin-callout_2-2_2x.pngbin0 -> 8136 bytes
-rw-r--r--docs/html/training/constraint-layout/images/layout-editor-properties-callouts_2-2_2x.pngbin0 -> 40984 bytes
-rw-r--r--docs/html/training/constraint-layout/images/layout-editor_2-2_2x.pngbin0 -> 206243 bytes
-rw-r--r--docs/html/training/constraint-layout/images/parent-constraint_2x.pngbin0 -> 5613 bytes
-rw-r--r--docs/html/training/constraint-layout/images/position-constraint_2x.pngbin0 -> 7161 bytes
-rw-r--r--docs/html/training/constraint-layout/images/thumbnail-add-layout-guideline_2-2.pngbin0 -> 78602 bytes
-rw-r--r--docs/html/training/constraint-layout/images/thumbnail-adjust-constraint-bias.pngbin0 -> 308699 bytes
-rw-r--r--docs/html/training/constraint-layout/images/thumbnail-studio-constraint-first.pngbin0 -> 61879 bytes
-rw-r--r--docs/html/training/constraint-layout/images/thumbnail-studio-constraint-second.pngbin0 -> 65594 bytes
-rw-r--r--docs/html/training/constraint-layout/index.html498
-rw-r--r--docs/html/training/material/images/palette-library-color-profiles_2-1_2x.pngbin0 -> 295117 bytes
-rw-r--r--docs/html/training/material/images/palette-library-title-text-color_2-1_2x.pngbin0 -> 269351 bytes
-rw-r--r--docs/html/training/material/index.jd4
-rw-r--r--docs/html/training/material/palette-colors.html310
-rw-r--r--docs/html/training/testing/unit-testing/instrumented-unit-tests.jd62
-rw-r--r--docs/html/training/tv/playback/index.jd4
-rw-r--r--docs/html/training/tv/playback/onboarding.jd377
-rw-r--r--docs/html/training/tv/start/hardware.jd21
-rw-r--r--docs/image_sources/training/tv/playback/onboarding-fragment-diagram.graffle.zipbin0 -> 99758 bytes
-rw-r--r--libs/hwui/Android.mk8
-rw-r--r--libs/hwui/Caches.cpp17
-rw-r--r--libs/hwui/FontRenderer.cpp71
-rw-r--r--libs/hwui/FontRenderer.h19
-rw-r--r--libs/hwui/GammaFontRenderer.h14
-rw-r--r--libs/hwui/SkiaCanvas.cpp7
-rw-r--r--libs/hwui/font/CacheTexture.cpp12
-rw-r--r--libs/hwui/font/CacheTexture.h2
-rw-r--r--libs/hwui/font/Font.cpp8
-rw-r--r--libs/hwui/font/FontCacheHistoryTracker.cpp100
-rw-r--r--libs/hwui/font/FontCacheHistoryTracker.h64
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp4
-rw-r--r--media/java/android/media/AudioAttributes.java61
-rw-r--r--media/java/android/media/ImageReader.java4
-rw-r--r--media/java/android/media/MediaExtractor.java5
-rw-r--r--media/java/android/media/MediaPlayer.java3
-rw-r--r--media/java/android/media/MediaScanner.java51
-rw-r--r--media/jni/audioeffect/android_media_Visualizer.cpp9
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoService.java8
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoTile.java3
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/PrefState.java8
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java23
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java9
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java44
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_0.xml20
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_1.xml24
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_2.xml24
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_3.xml24
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_4.xml19
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_wifi_0.xml22
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_wifi_1.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_wifi_2.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_wifi_3.xml26
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_wifi_4.xml21
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_signal_0.xml19
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_signal_1.xml23
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_signal_2.xml23
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_signal_3.xml23
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_signal_4.xml20
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml19
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml23
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml23
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml23
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml19
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml4
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml4
-rw-r--r--packages/SystemUI/res/values-kk-rKZ/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pa-rIN/strings.xml2
-rw-r--r--packages/SystemUI/res/values/styles.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java17
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java14
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java238
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java4
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java12
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java21
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityRecord.java29
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java7
-rw-r--r--services/core/java/com/android/server/am/ActivityStartInterceptor.java6
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java7
-rw-r--r--services/core/java/com/android/server/am/UriPermission.java10
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java44
-rw-r--r--services/core/java/com/android/server/audio/FocusRequester.java17
-rw-r--r--services/core/java/com/android/server/audio/MediaFocusControl.java16
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkAgentInfo.java15
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkNotificationManager.java10
-rw-r--r--services/core/java/com/android/server/connectivity/PacManager.java36
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java10
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java14
-rw-r--r--services/core/java/com/android/server/pm/Installer.java5
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java152
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptService.java144
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java14
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java30
-rw-r--r--services/core/java/com/android/server/pm/ShortcutLauncher.java13
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java27
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackageInfo.java9
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackageItem.java7
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java59
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java11
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java70
-rw-r--r--services/net/java/android/net/apf/ApfFilter.java152
-rw-r--r--services/tests/servicestests/src/android/net/apf/ApfTest.java68
-rw-r--r--services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java163
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java30
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java54
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java32
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneConstants.java12
-rw-r--r--tests/UiBench/AndroidManifest.xml10
-rw-r--r--tests/UiBench/src/com/android/test/uibench/SlowBindRecyclerViewActivity.java55
-rw-r--r--tests/UiBench/src/com/android/test/uibench/recyclerview/RvBoxAdapter.java99
-rw-r--r--tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java1
-rw-r--r--wifi/java/android/net/wifi/WifiScanner.java20
269 files changed, 4939 insertions, 1051 deletions
diff --git a/Android.mk b/Android.mk
index 2d5285438392..41966f463661 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1244,6 +1244,31 @@ LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
include $(BUILD_DROIDDOC)
+# ==== generates full navtree for resolving @links in ds postprocessing ====
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
+LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
+LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
+LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
+LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
+LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
+LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
+
+LOCAL_MODULE := ds-ref-navtree
+
+LOCAL_DROIDDOC_OPTIONS:= \
+ $(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
+ -hdf android.whichdoc online \
+ -toroot / \
+ -atLinksNavtree \
+ -navtreeonly
+
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
+
+include $(BUILD_DROIDDOC)
+
# ==== site updates for docs (on the androiddevdocs app engine server) =======================
include $(CLEAR_VARS)
diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp
index 4983b9ac4236..c546072e733a 100644
--- a/cmds/bootanimation/audioplay.cpp
+++ b/cmds/bootanimation/audioplay.cpp
@@ -141,13 +141,27 @@ bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) {
// configure audio source
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1};
+ // Determine channelMask from num_channels
+ SLuint32 channelMask;
+ switch (chunkFormat->num_channels) {
+ case 1:
+ channelMask = SL_SPEAKER_FRONT_CENTER;
+ break;
+ case 2:
+ channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
+ break;
+ default:
+ // Default of 0 will derive mask from num_channels and log a warning.
+ channelMask = 0;
+ }
+
SLDataFormat_PCM format_pcm = {
SL_DATAFORMAT_PCM,
chunkFormat->num_channels,
chunkFormat->sample_rate * 1000, // convert to milliHz
chunkFormat->bits_per_sample,
16,
- SL_SPEAKER_FRONT_CENTER,
+ channelMask,
SL_BYTEORDER_LITTLEENDIAN
};
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index c4eaccc1b406..163e7d2661b9 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -53,7 +53,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
- * Accessibility services are intended to assist users with disabilities in using
+ * Accessibility services should only be used to assist users with disabilities in using
* Android devices and apps. They run in the background and receive callbacks by the system
* when {@link AccessibilityEvent}s are fired. Such events denote some state transition
* in the user interface, for example, the focus has changed, a button has been clicked,
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 632e4b943626..0a9dc3a18375 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -2703,8 +2703,6 @@ public class AccountManager {
* <ul>
* <li>{@link #KEY_ACCOUNT_SESSION_BUNDLE} - encrypted Bundle for
* adding the the to the device later.
- * <li>{@link #KEY_PASSWORD} - optional, the password or password
- * hash of the account.
* <li>{@link #KEY_ACCOUNT_STATUS_TOKEN} - optional, token to check
* status of the account
* </ul>
@@ -2792,8 +2790,6 @@ public class AccountManager {
* <ul>
* <li>{@link #KEY_ACCOUNT_SESSION_BUNDLE} - encrypted Bundle for
* updating the local credentials on device later.
- * <li>{@link #KEY_PASSWORD} - optional, the password or password
- * hash of the account
* <li>{@link #KEY_ACCOUNT_STATUS_TOKEN} - optional, token to check
* status of the account
* </ul>
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index aacd5da58640..50479c8e951b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -3017,6 +3017,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
+ case CAN_BYPASS_WORK_CHALLENGE: {
+ data.enforceInterface(IActivityManager.descriptor);
+ final PendingIntent intent = PendingIntent.CREATOR.createFromParcel(data);
+ final boolean result = canBypassWorkChallenge(intent);
+ reply.writeNoException();
+ reply.writeInt(result ? 1 : 0);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -7091,6 +7099,20 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
return;
}
+ @Override
+ public boolean canBypassWorkChallenge(PendingIntent intent)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ intent.writeToParcel(data, 0);
+ mRemote.transact(CAN_BYPASS_WORK_CHALLENGE, data, reply, 0);
+ reply.readException();
+ final int result = reply.readInt();
+ data.recycle();
+ reply.recycle();
+ return result != 0;
+ }
private IBinder mRemote;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2c5f881321c0..18677dda3b88 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -433,8 +433,10 @@ public final class ActivityThread {
static final class NewIntentData {
List<ReferrerIntent> intents;
IBinder token;
+ boolean andPause;
public String toString() {
- return "NewIntentData{intents=" + intents + " token=" + token + "}";
+ return "NewIntentData{intents=" + intents + " token=" + token
+ + " andPause=" + andPause +"}";
}
}
@@ -751,10 +753,12 @@ public final class ActivityThread {
configChanges, notResumed, config, overrideConfig, true, preserveWindow);
}
- public final void scheduleNewIntent(List<ReferrerIntent> intents, IBinder token) {
+ public final void scheduleNewIntent(
+ List<ReferrerIntent> intents, IBinder token, boolean andPause) {
NewIntentData data = new NewIntentData();
data.intents = intents;
data.token = token;
+ data.andPause = andPause;
sendMessage(H.NEW_INTENT, data);
}
@@ -2787,24 +2791,34 @@ public final class ActivityThread {
}
}
- public final void performNewIntents(IBinder token, List<ReferrerIntent> intents) {
- ActivityClientRecord r = mActivities.get(token);
- if (r != null) {
- final boolean resumed = !r.paused;
- if (resumed) {
- r.activity.mTemporaryPause = true;
- mInstrumentation.callActivityOnPause(r.activity);
- }
- deliverNewIntents(r, intents);
- if (resumed) {
- r.activity.performResume();
- r.activity.mTemporaryPause = false;
- }
+ void performNewIntents(IBinder token, List<ReferrerIntent> intents, boolean andPause) {
+ final ActivityClientRecord r = mActivities.get(token);
+ if (r == null) {
+ return;
+ }
+
+ final boolean resumed = !r.paused;
+ if (resumed) {
+ r.activity.mTemporaryPause = true;
+ mInstrumentation.callActivityOnPause(r.activity);
+ }
+ deliverNewIntents(r, intents);
+ if (resumed) {
+ r.activity.performResume();
+ r.activity.mTemporaryPause = false;
+ }
+
+ if (r.paused && andPause) {
+ // In this case the activity was in the paused state when we delivered the intent,
+ // to guarantee onResume gets called after onNewIntent we temporarily resume the
+ // activity and pause again as the caller wanted.
+ performResumeActivity(token, false, "performNewIntents");
+ performPauseActivityIfNeeded(r, "performNewIntents");
}
}
private void handleNewIntent(NewIntentData data) {
- performNewIntents(data.token, data.intents);
+ performNewIntents(data.token, data.intents, data.andPause);
}
public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index d6da3f44f4a0..05d9d7e412f0 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -190,7 +190,8 @@ public abstract class ApplicationThreadNative extends Binder
data.enforceInterface(IApplicationThread.descriptor);
List<ReferrerIntent> pi = data.createTypedArrayList(ReferrerIntent.CREATOR);
IBinder b = data.readStrongBinder();
- scheduleNewIntent(pi, b);
+ final boolean andPause = data.readInt() == 1;
+ scheduleNewIntent(pi, b, andPause);
return true;
}
@@ -909,12 +910,13 @@ class ApplicationThreadProxy implements IApplicationThread {
data.recycle();
}
- public void scheduleNewIntent(List<ReferrerIntent> intents, IBinder token)
+ public void scheduleNewIntent(List<ReferrerIntent> intents, IBinder token, boolean andPause)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeTypedList(intents);
data.writeStrongBinder(token);
+ data.writeInt(andPause ? 1 : 0);
mRemote.transact(SCHEDULE_NEW_INTENT_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index eb07fbc5271a..6e38347f7c99 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -1089,7 +1089,7 @@ public class DownloadManager {
if (cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_STATUS));
if (DownloadManager.STATUS_SUCCESSFUL == status) {
- return ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, id);
+ return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id);
}
}
} finally {
@@ -1425,7 +1425,7 @@ public class DownloadManager {
* @hide
*/
public Uri getDownloadUri(long id) {
- return ContentUris.withAppendedId(mBaseUri, id);
+ return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id);
}
/**
@@ -1519,7 +1519,7 @@ public class DownloadManager {
// return content URI for cache download
long downloadId = getLong(getColumnIndex(Downloads.Impl._ID));
- return ContentUris.withAppendedId(mBaseUri, downloadId).toString();
+ return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, downloadId).toString();
}
private long getReason(int status) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index e411e03a8a94..5a4470b2ecdb 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -671,6 +671,18 @@ public interface IActivityManager extends IInterface {
*/
public void setHasTopUi(boolean hasTopUi) throws RemoteException;
+ /**
+ * Returns if the target of the PendingIntent can be fired directly, without triggering
+ * a work profile challenge. This can happen if the PendingIntent is to start direct-boot
+ * aware activities, and the target user is in RUNNING_LOCKED state, i.e. we should allow
+ * direct-boot aware activity to bypass work challenge when the user hasn't unlocked yet.
+ * @param intent the {@link PendingIntent} to be tested.
+ * @return {@code true} if the intent should not trigger a work challenge, {@code false}
+ * otherwise.
+ * @throws RemoteException
+ */
+ public boolean canBypassWorkChallenge(PendingIntent intent) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -1062,4 +1074,5 @@ public interface IActivityManager extends IInterface {
int SET_VR_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 377;
int SET_RENDER_THREAD_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 378;
int SET_HAS_TOP_UI = IBinder.FIRST_CALL_TRANSACTION + 379;
+ int CAN_BYPASS_WORK_CHALLENGE = IBinder.FIRST_CALL_TRANSACTION + 380;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 559f69fc2aec..3fa88ae674a4 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -67,7 +67,8 @@ public interface IApplicationThread extends IInterface {
List<ReferrerIntent> pendingNewIntents, int configChanges, boolean notResumed,
Configuration config, Configuration overrideConfig, boolean preserveWindow)
throws RemoteException;
- void scheduleNewIntent(List<ReferrerIntent> intent, IBinder token) throws RemoteException;
+ void scheduleNewIntent(
+ List<ReferrerIntent> intent, IBinder token, boolean andPause) throws RemoteException;
void scheduleDestroyActivity(IBinder token, boolean finished,
int configChanges) throws RemoteException;
void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 2a1e3c250a00..3b273bc1c4b6 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -314,7 +314,7 @@ public class LocalActivityManager {
ArrayList<ReferrerIntent> intents = new ArrayList<>(1);
intents.add(new ReferrerIntent(intent, mParent.getPackageName()));
if (localLOGV) Log.v(TAG, r.id + ": new intent");
- mActivityThread.performNewIntents(r, intents);
+ mActivityThread.performNewIntents(r, intents, false /* andPause */);
r.intent = intent;
moveToState(r, mCurState);
if (mSingleMode) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3c2ac6733c52..52d6b56609de 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -343,6 +343,15 @@ public class ConnectivityManager {
public static final String ACTION_PROMPT_UNVALIDATED = "android.net.conn.PROMPT_UNVALIDATED";
/**
+ * Action used to display a dialog that asks the user whether to avoid a network that is no
+ * longer validated. This intent is used to start the dialog in settings via startActivity.
+ *
+ * @hide
+ */
+ public static final String ACTION_PROMPT_LOST_VALIDATION =
+ "android.net.conn.PROMPT_LOST_VALIDATION";
+
+ /**
* Invalid tethering type.
* @see #startTethering(int, OnStartTetheringCallback, boolean)
* @hide
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 6243f467016a..56eba4f0e3ef 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -182,8 +182,15 @@ public final class NetworkCapabilities implements Parcelable {
*/
public static final int NET_CAPABILITY_CAPTIVE_PORTAL = 17;
+ /**
+ * Indicates that this network is available for use by apps, and not a network that is being
+ * kept up in the background to facilitate fast network switching.
+ * @hide
+ */
+ public static final int NET_CAPABILITY_FOREGROUND = 18;
+
private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
- private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_CAPTIVE_PORTAL;
+ private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_FOREGROUND;
/**
* Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -194,7 +201,8 @@ public final class NetworkCapabilities implements Parcelable {
// http://b/18206275
(1 << NET_CAPABILITY_TRUSTED) |
(1 << NET_CAPABILITY_VALIDATED) |
- (1 << NET_CAPABILITY_CAPTIVE_PORTAL);
+ (1 << NET_CAPABILITY_CAPTIVE_PORTAL) |
+ (1 << NET_CAPABILITY_FOREGROUND);
/**
* Network specifier for factories which want to match any network specifier
@@ -217,8 +225,7 @@ public final class NetworkCapabilities implements Parcelable {
* get immediately torn down because they do not have the requested capability.
*/
private static final long NON_REQUESTABLE_CAPABILITIES =
- (1 << NET_CAPABILITY_VALIDATED) |
- (1 << NET_CAPABILITY_CAPTIVE_PORTAL);
+ MUTABLE_CAPABILITIES & ~(1 << NET_CAPABILITY_TRUSTED);
/**
* Capabilities that are set by default when the object is constructed.
@@ -325,6 +332,7 @@ public final class NetworkCapabilities implements Parcelable {
public String describeFirstNonRequestableCapability() {
if (hasCapability(NET_CAPABILITY_VALIDATED)) return "NET_CAPABILITY_VALIDATED";
if (hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return "NET_CAPABILITY_CAPTIVE_PORTAL";
+ if (hasCapability(NET_CAPABILITY_FOREGROUND)) return "NET_CAPABILITY_FOREGROUND";
// This cannot happen unless the preceding checks are incomplete.
if ((mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES) != 0) {
return "unknown non-requestable capabilities " + Long.toHexString(mNetworkCapabilities);
@@ -352,6 +360,11 @@ public final class NetworkCapabilities implements Parcelable {
(that.mNetworkCapabilities & ~MUTABLE_CAPABILITIES));
}
+ private boolean equalsNetCapabilitiesRequestable(NetworkCapabilities that) {
+ return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) ==
+ (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES));
+ }
+
/**
* Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are
* typically provided by restricted networks.
@@ -749,6 +762,19 @@ public final class NetworkCapabilities implements Parcelable {
equalsSpecifier(nc));
}
+ /**
+ * Checks that our requestable capabilities are the same as those of the given
+ * {@code NetworkCapabilities}.
+ *
+ * @hide
+ */
+ public boolean equalRequestableCapabilities(NetworkCapabilities nc) {
+ if (nc == null) return false;
+ return (equalsNetCapabilitiesRequestable(nc) &&
+ equalsTransportTypes(nc) &&
+ equalsSpecifier(nc));
+ }
+
@Override
public boolean equals(Object obj) {
if (obj == null || (obj instanceof NetworkCapabilities == false)) return false;
@@ -833,6 +859,7 @@ public final class NetworkCapabilities implements Parcelable {
case NET_CAPABILITY_NOT_VPN: capabilities += "NOT_VPN"; break;
case NET_CAPABILITY_VALIDATED: capabilities += "VALIDATED"; break;
case NET_CAPABILITY_CAPTIVE_PORTAL: capabilities += "CAPTIVE_PORTAL"; break;
+ case NET_CAPABILITY_FOREGROUND: capabilities += "FOREGROUND"; break;
}
if (++i < types.length) capabilities += "&";
}
diff --git a/core/java/android/os/PatternMatcher.java b/core/java/android/os/PatternMatcher.java
index 56dc837549a7..3890fbfafb32 100644
--- a/core/java/android/os/PatternMatcher.java
+++ b/core/java/android/os/PatternMatcher.java
@@ -16,6 +16,10 @@
package android.os;
+import android.util.Log;
+
+import java.util.Arrays;
+
/**
* A simple pattern matcher, which is safe to use on untrusted data: it does
* not provide full reg-exp support, only simple globbing that can not be
@@ -44,13 +48,59 @@ public class PatternMatcher implements Parcelable {
* wildcard part of a normal regexp.
*/
public static final int PATTERN_SIMPLE_GLOB = 2;
-
+
+ /**
+ * Pattern type: the given pattern is interpreted with a regular
+ * expression-like syntax for matching against the string it is tested
+ * against. Supported tokens include dot ({@code .}) and sets ({@code [...]})
+ * with full support for character ranges and the not ({@code ^}) modifier.
+ * Supported modifiers include star ({@code *}) for zero-or-more, plus ({@code +})
+ * for one-or-more and full range ({@code {...}}) support. This is a simple
+ * evaulation implementation in which matching is done against the pattern in
+ * realtime with no backtracking support.
+ *
+ * {@hide} Pending approval for public API
+ */
+ public static final int PATTERN_ADVANCED_GLOB = 3;
+
+ // token types for advanced matching
+ private static final int TOKEN_TYPE_LITERAL = 0;
+ private static final int TOKEN_TYPE_ANY = 1;
+ private static final int TOKEN_TYPE_SET = 2;
+ private static final int TOKEN_TYPE_INVERSE_SET = 3;
+
+ // Return for no match
+ private static final int NO_MATCH = -1;
+
+ private static final String TAG = "PatternMatcher";
+
+ // Parsed placeholders for advanced patterns
+ private static final int PARSED_TOKEN_CHAR_SET_START = -1;
+ private static final int PARSED_TOKEN_CHAR_SET_INVERSE_START = -2;
+ private static final int PARSED_TOKEN_CHAR_SET_STOP = -3;
+ private static final int PARSED_TOKEN_CHAR_ANY = -4;
+ private static final int PARSED_MODIFIER_RANGE_START = -5;
+ private static final int PARSED_MODIFIER_RANGE_STOP = -6;
+ private static final int PARSED_MODIFIER_ZERO_OR_MORE = -7;
+ private static final int PARSED_MODIFIER_ONE_OR_MORE = -8;
+
private final String mPattern;
private final int mType;
-
+ private final int[] mParsedPattern;
+
+
+ private static final int MAX_PATTERN_STORAGE = 2048;
+ // workspace to use for building a parsed advanced pattern;
+ private static final int[] sParsedPatternScratch = new int[MAX_PATTERN_STORAGE];
+
public PatternMatcher(String pattern, int type) {
mPattern = pattern;
mType = type;
+ if (mType == PATTERN_ADVANCED_GLOB) {
+ mParsedPattern = parseAndVerifyAdvancedPattern(pattern);
+ } else {
+ mParsedPattern = null;
+ }
}
public final String getPath() {
@@ -62,7 +112,7 @@ public class PatternMatcher implements Parcelable {
}
public boolean match(String str) {
- return matchPattern(mPattern, str, mType);
+ return matchPattern(str, mPattern, mParsedPattern, mType);
}
public String toString() {
@@ -77,6 +127,9 @@ public class PatternMatcher implements Parcelable {
case PATTERN_SIMPLE_GLOB:
type = "GLOB: ";
break;
+ case PATTERN_ADVANCED_GLOB:
+ type = "ADVANCED: ";
+ break;
}
return "PatternMatcher{" + type + mPattern + "}";
}
@@ -88,11 +141,13 @@ public class PatternMatcher implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mPattern);
dest.writeInt(mType);
+ dest.writeIntArray(mParsedPattern);
}
public PatternMatcher(Parcel src) {
mPattern = src.readString();
mType = src.readInt();
+ mParsedPattern = src.createIntArray();
}
public static final Parcelable.Creator<PatternMatcher> CREATOR
@@ -106,16 +161,21 @@ public class PatternMatcher implements Parcelable {
}
};
- static boolean matchPattern(String pattern, String match, int type) {
+ static boolean matchPattern(String match, String pattern, int[] parsedPattern, int type) {
if (match == null) return false;
if (type == PATTERN_LITERAL) {
return pattern.equals(match);
} if (type == PATTERN_PREFIX) {
return match.startsWith(pattern);
- } else if (type != PATTERN_SIMPLE_GLOB) {
- return false;
+ } else if (type == PATTERN_SIMPLE_GLOB) {
+ return matchGlobPattern(pattern, match);
+ } else if (type == PATTERN_ADVANCED_GLOB) {
+ return matchAdvancedPattern(parsedPattern, match);
}
-
+ return false;
+ }
+
+ static boolean matchGlobPattern(String pattern, String match) {
final int NP = pattern.length();
if (NP <= 0) {
return match.length() <= 0;
@@ -194,4 +254,310 @@ public class PatternMatcher implements Parcelable {
return false;
}
-}
+
+ /**
+ * Parses the advanced pattern and returns an integer array representation of it. The integer
+ * array treats each field as a character if positive and a unique token placeholder if
+ * negative. This method will throw on any pattern structure violations.
+ */
+ synchronized static int[] parseAndVerifyAdvancedPattern(String pattern) {
+ int ip = 0;
+ final int LP = pattern.length();
+
+ int it = 0;
+
+ boolean inSet = false;
+ boolean inRange = false;
+ boolean inCharClass = false;
+
+ boolean addToParsedPattern;
+
+ while (ip < LP) {
+ if (it > MAX_PATTERN_STORAGE - 3) {
+ throw new IllegalArgumentException("Pattern is too large!");
+ }
+
+ char c = pattern.charAt(ip);
+ addToParsedPattern = false;
+
+ switch (c) {
+ case '[':
+ if (inSet) {
+ addToParsedPattern = true; // treat as literal or char class in set
+ } else {
+ if (pattern.charAt(ip + 1) == '^') {
+ sParsedPatternScratch[it++] = PARSED_TOKEN_CHAR_SET_INVERSE_START;
+ ip++; // skip over the '^'
+ } else {
+ sParsedPatternScratch[it++] = PARSED_TOKEN_CHAR_SET_START;
+ }
+ ip++; // move to the next pattern char
+ inSet = true;
+ continue;
+ }
+ break;
+ case ']':
+ if (!inSet) {
+ addToParsedPattern = true; // treat as literal outside of set
+ } else {
+ int parsedToken = sParsedPatternScratch[it - 1];
+ if (parsedToken == PARSED_TOKEN_CHAR_SET_START ||
+ parsedToken == PARSED_TOKEN_CHAR_SET_INVERSE_START) {
+ throw new IllegalArgumentException(
+ "You must define characters in a set.");
+ }
+ sParsedPatternScratch[it++] = PARSED_TOKEN_CHAR_SET_STOP;
+ inSet = false;
+ inCharClass = false;
+ }
+ break;
+ case '{':
+ if (!inSet) {
+ if (it == 0 || isParsedModifier(sParsedPatternScratch[it - 1])) {
+ throw new IllegalArgumentException("Modifier must follow a token.");
+ }
+ sParsedPatternScratch[it++] = PARSED_MODIFIER_RANGE_START;
+ ip++;
+ inRange = true;
+ }
+ break;
+ case '}':
+ if (inRange) { // only terminate the range if we're currently in one
+ sParsedPatternScratch[it++] = PARSED_MODIFIER_RANGE_STOP;
+ inRange = false;
+ }
+ break;
+ case '*':
+ if (!inSet) {
+ if (it == 0 || isParsedModifier(sParsedPatternScratch[it - 1])) {
+ throw new IllegalArgumentException("Modifier must follow a token.");
+ }
+ sParsedPatternScratch[it++] = PARSED_MODIFIER_ZERO_OR_MORE;
+ }
+ break;
+ case '+':
+ if (!inSet) {
+ if (it == 0 || isParsedModifier(sParsedPatternScratch[it - 1])) {
+ throw new IllegalArgumentException("Modifier must follow a token.");
+ }
+ sParsedPatternScratch[it++] = PARSED_MODIFIER_ONE_OR_MORE;
+ }
+ break;
+ case '.':
+ if (!inSet) {
+ sParsedPatternScratch[it++] = PARSED_TOKEN_CHAR_ANY;
+ }
+ break;
+ case '\\': // escape
+ if (ip + 1 >= LP) {
+ throw new IllegalArgumentException("Escape found at end of pattern!");
+ }
+ c = pattern.charAt(++ip);
+ addToParsedPattern = true;
+ break;
+ default:
+ addToParsedPattern = true;
+ break;
+ }
+ if (inSet) {
+ if (inCharClass) {
+ sParsedPatternScratch[it++] = c;
+ inCharClass = false;
+ } else {
+ // look forward for character class
+ if (ip + 2 < LP
+ && pattern.charAt(ip + 1) == '-'
+ && pattern.charAt(ip + 2) != ']') {
+ inCharClass = true;
+ sParsedPatternScratch[it++] = c; // set first token as lower end of range
+ ip++; // advance past dash
+ } else { // literal
+ sParsedPatternScratch[it++] = c; // set first token as literal
+ sParsedPatternScratch[it++] = c; // set second set as literal
+ }
+ }
+ } else if (inRange) {
+ int endOfSet = pattern.indexOf('}', ip);
+ if (endOfSet < 0) {
+ throw new IllegalArgumentException("Range not ended with '}'");
+ }
+ String rangeString = pattern.substring(ip, endOfSet);
+ int commaIndex = rangeString.indexOf(',');
+ try {
+ final int rangeMin;
+ final int rangeMax;
+ if (commaIndex < 0) {
+ int parsedRange = Integer.parseInt(rangeString);
+ rangeMin = rangeMax = parsedRange;
+ } else {
+ rangeMin = Integer.parseInt(rangeString.substring(0, commaIndex));
+ if (commaIndex == rangeString.length() - 1) { // e.g. {n,} (n or more)
+ rangeMax = Integer.MAX_VALUE;
+ } else {
+ rangeMax = Integer.parseInt(rangeString.substring(commaIndex + 1));
+ }
+ }
+ if (rangeMin > rangeMax) {
+ throw new IllegalArgumentException(
+ "Range quantifier minimum is greater than maximum");
+ }
+ sParsedPatternScratch[it++] = rangeMin;
+ sParsedPatternScratch[it++] = rangeMax;
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Range number format incorrect", e);
+ }
+ ip = endOfSet;
+ continue; // don't increment ip
+ } else if (addToParsedPattern) {
+ sParsedPatternScratch[it++] = c;
+ }
+ ip++;
+ }
+ if (inSet) {
+ throw new IllegalArgumentException("Set was not terminated!");
+ }
+ return Arrays.copyOf(sParsedPatternScratch, it);
+ }
+
+ private static boolean isParsedModifier(int parsedChar) {
+ return parsedChar == PARSED_MODIFIER_ONE_OR_MORE ||
+ parsedChar == PARSED_MODIFIER_ZERO_OR_MORE ||
+ parsedChar == PARSED_MODIFIER_RANGE_STOP ||
+ parsedChar == PARSED_MODIFIER_RANGE_START;
+ }
+
+ static boolean matchAdvancedPattern(int[] parsedPattern, String match) {
+
+ // create indexes
+ int ip = 0, im = 0;
+
+ // one-time length check
+ final int LP = parsedPattern.length, LM = match.length();
+
+ // The current character being analyzed in the pattern
+ int patternChar;
+
+ int tokenType;
+
+ int charSetStart = 0, charSetEnd = 0;
+
+ while (ip < LP) { // we still have content in the pattern
+
+ patternChar = parsedPattern[ip];
+ // get the match type of the next verb
+
+ switch (patternChar) {
+ case PARSED_TOKEN_CHAR_ANY:
+ tokenType = TOKEN_TYPE_ANY;
+ ip++;
+ break;
+ case PARSED_TOKEN_CHAR_SET_START:
+ case PARSED_TOKEN_CHAR_SET_INVERSE_START:
+ tokenType = patternChar == PARSED_TOKEN_CHAR_SET_START
+ ? TOKEN_TYPE_SET
+ : TOKEN_TYPE_INVERSE_SET;
+ charSetStart = ip + 1; // start from the char after the set start
+ while (++ip < LP && parsedPattern[ip] != PARSED_TOKEN_CHAR_SET_STOP);
+ charSetEnd = ip - 1; // we're on the set stop, end is the previous
+ ip++; // move the pointer to the next pattern entry
+ break;
+ default:
+ charSetStart = ip;
+ tokenType = TOKEN_TYPE_LITERAL;
+ ip++;
+ break;
+ }
+
+ final int minRepetition;
+ final int maxRepetition;
+
+ // look for a match length modifier
+ if (ip >= LP) {
+ minRepetition = maxRepetition = 1;
+ } else {
+ patternChar = parsedPattern[ip];
+ switch (patternChar) {
+ case PARSED_MODIFIER_ZERO_OR_MORE:
+ minRepetition = 0;
+ maxRepetition = Integer.MAX_VALUE;
+ ip++;
+ break;
+ case PARSED_MODIFIER_ONE_OR_MORE:
+ minRepetition = 1;
+ maxRepetition = Integer.MAX_VALUE;
+ ip++;
+ break;
+ case PARSED_MODIFIER_RANGE_START:
+ minRepetition = parsedPattern[++ip];
+ maxRepetition = parsedPattern[++ip];
+ ip += 2; // step over PARSED_MODIFIER_RANGE_STOP and on to the next token
+ break;
+ default:
+ minRepetition = maxRepetition = 1; // implied literal
+ break;
+ }
+ }
+ if (minRepetition > maxRepetition) {
+ return false;
+ }
+
+ // attempt to match as many characters as possible
+ int matched = matchChars(match, im, LM, tokenType, minRepetition, maxRepetition,
+ parsedPattern, charSetStart, charSetEnd);
+
+ // if we found a conflict, return false immediately
+ if (matched == NO_MATCH) {
+ return false;
+ }
+
+ // move the match pointer the number of characters matched
+ im += matched;
+ }
+ return ip >= LP && im >= LM; // have parsed entire string and regex
+ }
+
+ private static int matchChars(String match, int im, final int lm, int tokenType,
+ int minRepetition, int maxRepetition, int[] parsedPattern,
+ int tokenStart, int tokenEnd) {
+ int matched = 0;
+
+ while(matched < maxRepetition
+ && matchChar(match, im + matched, lm, tokenType, parsedPattern, tokenStart,
+ tokenEnd)) {
+ matched++;
+ }
+
+ return matched < minRepetition ? NO_MATCH : matched;
+ }
+
+ private static boolean matchChar(String match, int im, final int lm, int tokenType,
+ int[] parsedPattern, int tokenStart, int tokenEnd) {
+ if (im >= lm) { // we've overrun the string, no match
+ return false;
+ }
+ switch (tokenType) {
+ case TOKEN_TYPE_ANY:
+ return true;
+ case TOKEN_TYPE_SET:
+ for (int i = tokenStart; i < tokenEnd; i += 2) {
+ char matchChar = match.charAt(im);
+ if (matchChar >= parsedPattern[i] && matchChar <= parsedPattern[i + 1]) {
+ return true;
+ }
+ }
+ return false;
+ case TOKEN_TYPE_INVERSE_SET:
+ for (int i = tokenStart; i < tokenEnd; i += 2) {
+ char matchChar = match.charAt(im);
+ if (matchChar >= parsedPattern[i] && matchChar <= parsedPattern[i + 1]) {
+ return false;
+ }
+ }
+ return true;
+ case TOKEN_TYPE_LITERAL:
+ return match.charAt(im) == parsedPattern[tokenStart];
+ default:
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 507379baaa94..90bd11fe83bc 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -724,6 +724,7 @@ public class RecoverySystem {
String line = null;
int bytesWrittenInMiB = -1, bytesStashedInMiB = -1;
int timeTotal = -1;
+ int uncryptTime = -1;
int sourceVersion = -1;
while ((line = in.readLine()) != null) {
// Here is an example of lines in last_install:
@@ -759,6 +760,8 @@ public class RecoverySystem {
if (line.startsWith("time")) {
timeTotal = scaled;
+ } else if (line.startsWith("uncrypt_time")) {
+ uncryptTime = scaled;
} else if (line.startsWith("source_build")) {
sourceVersion = scaled;
} else if (line.startsWith("bytes_written")) {
@@ -774,6 +777,9 @@ public class RecoverySystem {
if (timeTotal != -1) {
MetricsLogger.histogram(context, "ota_time_total", timeTotal);
}
+ if (uncryptTime != -1) {
+ MetricsLogger.histogram(context, "ota_uncrypt_time", uncryptTime);
+ }
if (sourceVersion != -1) {
MetricsLogger.histogram(context, "ota_source_version", sourceVersion);
}
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index 5849350cc49e..3546e17698b9 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -288,20 +288,22 @@ public class RemoteCallbackList<E extends IInterface> {
* @see #beginBroadcast
*/
public void finishBroadcast() {
- if (mBroadcastCount < 0) {
- throw new IllegalStateException(
- "finishBroadcast() called outside of a broadcast");
- }
-
- Object[] active = mActiveBroadcast;
- if (active != null) {
- final int N = mBroadcastCount;
- for (int i=0; i<N; i++) {
- active[i] = null;
+ synchronized (mCallbacks) {
+ if (mBroadcastCount < 0) {
+ throw new IllegalStateException(
+ "finishBroadcast() called outside of a broadcast");
}
+
+ Object[] active = mActiveBroadcast;
+ if (active != null) {
+ final int N = mBroadcastCount;
+ for (int i=0; i<N; i++) {
+ active[i] = null;
+ }
+ }
+
+ mBroadcastCount = -1;
}
-
- mBroadcastCount = -1;
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 40e3e6e59900..498e36936ec7 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7488,6 +7488,12 @@ public final class Settings {
"network_switch_notification_rate_limit_millis";
/**
+ * Whether to automatically switch away from wifi networks that lose Internet access.
+ * @hide
+ */
+ public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi";
+
+ /**
* Whether Wifi display is enabled/disabled
* 0=disabled. 1=enabled.
* @hide
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index f92d83af93a0..9f46f3fc75b0 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -33,6 +33,18 @@ import dalvik.system.CloseGuard;
/**
* Handle onto a raw buffer that is being managed by the screen compositor.
+ *
+ * <p>A Surface is generally created by or from a consumer of image buffers (such as a
+ * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, or
+ * {@link android.renderscript.Allocation}), and is handed to some kind of producer (such as
+ * {@link android.opengl.EGL14#eglCreateWindowSurface(android.opengl.EGLDisplay,android.opengl.EGLConfig,java.lang.Object,int[],int) OpenGL},
+ * {@link android.media.MediaPlayer#setSurface MediaPlayer}, or
+ * {@link android.hardware.camera2.CameraDevice#createCaptureSession CameraDevice}) to draw
+ * into.</p>
+ *
+ * <p><strong>Note:</strong> A Surface acts like a
+ * {@link java.lang.ref.WeakReference weak reference} to the consumer it is associated with. By
+ * itself it will not keep its parent consumer from being reclaimed.</p>
*/
public class Surface implements Parcelable {
private static final String TAG = "Surface";
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index c0c8e64aacc8..2e9cbf20607b 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2056,12 +2056,10 @@ public final class InputMethodManager {
* have any input method subtype.
*/
public InputMethodSubtype getCurrentInputMethodSubtype() {
- synchronized (mH) {
- try {
- return mService.getCurrentInputMethodSubtype();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ try {
+ return mService.getCurrentInputMethodSubtype();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index c3ddec787bfa..25580fd2496e 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -16,6 +16,8 @@
package android.widget;
+import com.android.internal.R;
+
import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.Widget;
@@ -29,10 +31,12 @@ import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
import android.text.Spanned;
import android.text.TextUtils;
+import android.text.TextWatcher;
import android.text.method.NumberKeyListener;
import android.util.AttributeSet;
import android.util.SparseArray;
@@ -52,9 +56,6 @@ import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
-import com.android.internal.R;
-import libcore.icu.LocaleData;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -62,6 +63,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import libcore.icu.LocaleData;
+
/**
* A widget that enables the user to select a number from a predefined range.
* There are two flavors of this widget and which one is presented to the user
@@ -1991,7 +1994,7 @@ public class NumberPicker extends LinearLayout {
removeCallbacks(mChangeCurrentByOneFromLongPressCommand);
}
if (mSetSelectionCommand != null) {
- removeCallbacks(mSetSelectionCommand);
+ mSetSelectionCommand.cancel();
}
if (mBeginSoftInputOnLongPressCommand != null) {
removeCallbacks(mBeginSoftInputOnLongPressCommand);
@@ -2033,18 +2036,14 @@ public class NumberPicker extends LinearLayout {
}
/**
- * Posts an {@link SetSelectionCommand} from the given <code>selectionStart
- * </code> to <code>selectionEnd</code>.
+ * Posts a {@link SetSelectionCommand} from the given
+ * {@code selectionStart} to {@code selectionEnd}.
*/
private void postSetSelectionCommand(int selectionStart, int selectionEnd) {
if (mSetSelectionCommand == null) {
- mSetSelectionCommand = new SetSelectionCommand();
- } else {
- removeCallbacks(mSetSelectionCommand);
+ mSetSelectionCommand = new SetSelectionCommand(mInputText);
}
- mSetSelectionCommand.mSelectionStart = selectionStart;
- mSetSelectionCommand.mSelectionEnd = selectionEnd;
- post(mSetSelectionCommand);
+ mSetSelectionCommand.post(selectionStart, selectionEnd);
}
/**
@@ -2090,6 +2089,12 @@ public class NumberPicker extends LinearLayout {
@Override
public CharSequence filter(
CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
+ // We don't know what the output will be, so always cancel any
+ // pending set selection command.
+ if (mSetSelectionCommand != null) {
+ mSetSelectionCommand.cancel();
+ }
+
if (mDisplayedValues == null) {
CharSequence filtered = super.filter(source, start, end, dest, dstart, dend);
if (filtered == null) {
@@ -2237,12 +2242,39 @@ public class NumberPicker extends LinearLayout {
/**
* Command for setting the input text selection.
*/
- class SetSelectionCommand implements Runnable {
- private int mSelectionStart;
+ private static class SetSelectionCommand implements Runnable {
+ private final EditText mInputText;
+ private int mSelectionStart;
private int mSelectionEnd;
+ /** Whether this runnable is currently posted. */
+ private boolean mPosted;
+
+ public SetSelectionCommand(EditText inputText) {
+ mInputText = inputText;
+ }
+
+ public void post(int selectionStart, int selectionEnd) {
+ mSelectionStart = selectionStart;
+ mSelectionEnd = selectionEnd;
+
+ if (!mPosted) {
+ mInputText.post(this);
+ mPosted = true;
+ }
+ }
+
+ public void cancel() {
+ if (mPosted) {
+ mInputText.removeCallbacks(this);
+ mPosted = false;
+ }
+ }
+
+ @Override
public void run() {
+ mPosted = false;
mInputText.setSelection(mSelectionStart, mSelectionEnd);
}
}
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index b12c03ca9c15..9b89491ce408 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1758,11 +1758,22 @@ public class PopupWindow {
*/
public int getMaxAvailableHeight(
@NonNull View anchor, int yOffset, boolean ignoreBottomDecorations) {
- final Rect displayFrame = new Rect();
+ Rect displayFrame = null;
+ final Rect visibleDisplayFrame = new Rect();
+
+ anchor.getWindowVisibleDisplayFrame(visibleDisplayFrame);
if (ignoreBottomDecorations) {
+ // In the ignore bottom decorations case we want to
+ // still respect all other decorations so we use the inset visible
+ // frame on the top right and left and take the bottom
+ // value from the full frame.
+ displayFrame = new Rect();
anchor.getWindowDisplayFrame(displayFrame);
+ displayFrame.top = visibleDisplayFrame.top;
+ displayFrame.right = visibleDisplayFrame.right;
+ displayFrame.left = visibleDisplayFrame.left;
} else {
- anchor.getWindowVisibleDisplayFrame(displayFrame);
+ displayFrame = visibleDisplayFrame;
}
final int[] anchorPos = mTmpDrawingLocation;
diff --git a/core/java/com/android/internal/util/WakeupMessage.java b/core/java/com/android/internal/util/WakeupMessage.java
index 7d222c74ac3b..46098c58108f 100644
--- a/core/java/com/android/internal/util/WakeupMessage.java
+++ b/core/java/com/android/internal/util/WakeupMessage.java
@@ -108,7 +108,7 @@ public class WakeupMessage implements AlarmManager.OnAlarmListener {
}
if (stillScheduled) {
Message msg = mHandler.obtainMessage(mCmd, mArg1, mArg2, mObj);
- mHandler.handleMessage(msg);
+ mHandler.dispatchMessage(msg);
msg.recycle();
}
}
diff --git a/core/java/com/android/internal/widget/WatchListDecorLayout.java b/core/java/com/android/internal/widget/WatchListDecorLayout.java
index 538cecaec616..5b49611fa4b0 100644
--- a/core/java/com/android/internal/widget/WatchListDecorLayout.java
+++ b/core/java/com/android/internal/widget/WatchListDecorLayout.java
@@ -306,8 +306,9 @@ public class WatchListDecorLayout extends FrameLayout
if (mListView.getChildCount() > 0) {
if (mListView.getLastVisiblePosition() >= mListView.getCount() - 1) {
View lastChild = mListView.getChildAt(mListView.getChildCount() - 1);
- setScrolling(mBottomPanel,
- lastChild.getY() + lastChild.getHeight() - mBottomPanel.getTop());
+ setScrolling(mBottomPanel, Math.max(
+ 0,
+ lastChild.getY() + lastChild.getHeight() - mBottomPanel.getTop()));
} else {
// shift to hide the frame, last child is not the last position
setScrolling(mBottomPanel, mBottomPanel.getHeight());
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index d7550a4d9695..72755ce105c8 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -151,12 +151,12 @@ Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc,
mPixelRef->unref();
}
-Bitmap::Bitmap(void* address, int fd,
+Bitmap::Bitmap(void* address, int fd, size_t mappedSize,
const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
: mPixelStorageType(PixelStorageType::Ashmem) {
mPixelStorage.ashmem.address = address;
mPixelStorage.ashmem.fd = fd;
- mPixelStorage.ashmem.size = ashmem_get_size_region(fd);
+ mPixelStorage.ashmem.size = mappedSize;
mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable));
// Note: this will trigger a call to onStrongRefDestroyed(), but
// we want the pixel ref to have a ref count of 0 at this point
@@ -1027,7 +1027,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
// Map the pixels in place and take ownership of the ashmem region.
nativeBitmap = GraphicsJNI::mapAshmemPixelRef(env, bitmap.get(),
- ctable, dupFd, const_cast<void*>(blob.data()), !isMutable);
+ ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable);
SkSafeUnref(ctable);
if (!nativeBitmap) {
close(dupFd);
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
index eadba5c0e634..aaea178e7387 100644
--- a/core/jni/android/graphics/Bitmap.h
+++ b/core/jni/android/graphics/Bitmap.h
@@ -51,8 +51,8 @@ public:
const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
Bitmap(void* address, void* context, FreeFunc freeFunc,
const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
- Bitmap(void* address, int fd, const SkImageInfo& info, size_t rowBytes,
- SkColorTable* ctable);
+ Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info,
+ size_t rowBytes, SkColorTable* ctable);
const SkImageInfo& info() const;
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 528541dadfb8..889a3db81e6f 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -613,7 +613,7 @@ android::Bitmap* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitm
return nullptr;
}
- android::Bitmap* wrapper = new android::Bitmap(addr, fd, info, rowBytes, ctable);
+ android::Bitmap* wrapper = new android::Bitmap(addr, fd, size, info, rowBytes, ctable);
wrapper->getSkBitmap(bitmap);
// since we're already allocated, we lockPixels right away
// HeapAllocator behaves this way too
@@ -623,7 +623,7 @@ android::Bitmap* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitm
}
android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
- SkColorTable* ctable, int fd, void* addr, bool readOnly) {
+ SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly) {
const SkImageInfo& info = bitmap->info();
if (info.colorType() == kUnknown_SkColorType) {
doThrowIAE(env, "unknown bitmap configuration");
@@ -633,7 +633,8 @@ android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
if (!addr) {
// Map existing ashmem region if not already mapped.
int flags = readOnly ? (PROT_READ) : (PROT_READ | PROT_WRITE);
- addr = mmap(NULL, ashmem_get_size_region(fd), flags, MAP_SHARED, fd, 0);
+ size = ashmem_get_size_region(fd);
+ addr = mmap(NULL, size, flags, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
return nullptr;
}
@@ -643,7 +644,7 @@ android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
// attempting to compute our own.
const size_t rowBytes = bitmap->rowBytes();
- android::Bitmap* wrapper = new android::Bitmap(addr, fd, info, rowBytes, ctable);
+ android::Bitmap* wrapper = new android::Bitmap(addr, fd, size, info, rowBytes, ctable);
wrapper->getSkBitmap(bitmap);
if (readOnly) {
bitmap->pixelRef()->setImmutable();
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 5baa8f8740c2..a21570992850 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -101,7 +101,7 @@ public:
SkColorTable* ctable);
static android::Bitmap* mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
- SkColorTable* ctable, int fd, void* addr, bool readOnly);
+ SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly);
/**
* Given a bitmap we natively allocate a memory block to store the contents
diff --git a/core/res/res/anim-watch/progress_indeterminate_material.xml b/core/res/res/anim-watch/progress_indeterminate_material.xml
new file mode 100644
index 000000000000..8f00d6c4cb66
--- /dev/null
+++ b/core/res/res/anim-watch/progress_indeterminate_material.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+ <objectAnimator
+ android:duration="3333"
+ android:interpolator="@interpolator/trim_start_interpolator"
+ android:propertyName="trimPathStart"
+ android:repeatCount="-1"
+ android:valueFrom="0"
+ android:valueTo="0.75"
+ android:valueType="floatType" />
+ <objectAnimator
+ android:duration="3333"
+ android:interpolator="@interpolator/trim_end_interpolator"
+ android:propertyName="trimPathEnd"
+ android:repeatCount="-1"
+ android:valueFrom="0"
+ android:valueTo="0.75"
+ android:valueType="floatType" />
+ <objectAnimator
+ android:duration="3333"
+ android:interpolator="@interpolator/trim_offset_interpolator"
+ android:propertyName="trimPathOffset"
+ android:repeatCount="-1"
+ android:valueFrom="0"
+ android:valueTo="0.25"
+ android:valueType="floatType" />
+</set>
diff --git a/core/res/res/anim-watch/progress_indeterminate_rotation_material.xml b/core/res/res/anim-watch/progress_indeterminate_rotation_material.xml
new file mode 100644
index 000000000000..63e66ec24410
--- /dev/null
+++ b/core/res/res/anim-watch/progress_indeterminate_rotation_material.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@interpolator/progress_indeterminate_rotation_interpolator"
+ android:duration="16666"
+ android:propertyName="rotation"
+ android:repeatCount="-1"
+ android:valueFrom="0"
+ android:valueTo="720"
+ android:valueType="floatType" />
diff --git a/core/res/res/drawable-hdpi/watch_switch_track_mtrl.png b/core/res/res/drawable-hdpi/watch_switch_track_mtrl_alpha.png
index ecee3e137ef6..ecee3e137ef6 100644
--- a/core/res/res/drawable-hdpi/watch_switch_track_mtrl.png
+++ b/core/res/res/drawable-hdpi/watch_switch_track_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/watch_switch_track_mtrl.png b/core/res/res/drawable-xhdpi/watch_switch_track_mtrl_alpha.png
index 1aa544227380..1aa544227380 100644
--- a/core/res/res/drawable-xhdpi/watch_switch_track_mtrl.png
+++ b/core/res/res/drawable-xhdpi/watch_switch_track_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl.png b/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl_alpha.png
index af2042be7f59..af2042be7f59 100644
--- a/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl.png
+++ b/core/res/res/drawable-xxhdpi/watch_switch_track_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/color/watch_switch_track_color_material.xml b/core/res/res/drawable/watch_switch_track_material.xml
index 402a536b4d12..79e92a331071 100644
--- a/core/res/res/color/watch_switch_track_color_material.xml
+++ b/core/res/res/drawable/watch_switch_track_material.xml
@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
-
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
http://www.apache.org/licenses/LICENSE-2.0
-
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
-<!-- Used for the background of switch track for watch switch preference. -->
+
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="false"
- android:alpha="0.4" android:color="?attr/colorPrimary" />
- <item android:color="?attr/colorPrimary" />
+ <item android:state_enabled="false">
+ <bitmap android:alpha="0.1" android:src="@drawable/watch_switch_track_mtrl_alpha" />
+ </item>
+ <item>
+ <bitmap android:alpha="0.2" android:src="@drawable/watch_switch_track_mtrl_alpha" />
+ </item>
</selector>
diff --git a/core/res/res/interpolator-watch/progress_indeterminate_rotation_interpolator.xml b/core/res/res/interpolator-watch/progress_indeterminate_rotation_interpolator.xml
new file mode 100644
index 000000000000..ed2655cb0ac8
--- /dev/null
+++ b/core/res/res/interpolator-watch/progress_indeterminate_rotation_interpolator.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0,0.0 c 0.032,0.0 0.016,0.2 0.08,0.2 l 0.12,0.0 c 0.032,0.0 0.016,0.2 0.08,0.2 l 0.12,0.0 c 0.032,0.0 0.016,0.2 0.08,0.2 l 0.12,0.0 c 0.032,0.0 0.016,0.2 0.08,0.2 l 0.12,0.0 c 0.032,0.0 0.016,0.2 0.08,0.2 l 0.12,0.0 L 1.0,1.0" />
diff --git a/core/res/res/interpolator-watch/trim_end_interpolator.xml b/core/res/res/interpolator-watch/trim_end_interpolator.xml
new file mode 100644
index 000000000000..f46d5e0e7c82
--- /dev/null
+++ b/core/res/res/interpolator-watch/trim_end_interpolator.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0,0.0 c 0.08,0.0 0.04,1.0 0.2,1.0 l 0.8,0.0 L 1.0,1.0" />
diff --git a/core/res/res/interpolator-watch/trim_offset_interpolator.xml b/core/res/res/interpolator-watch/trim_offset_interpolator.xml
new file mode 100644
index 000000000000..d58672e9cb42
--- /dev/null
+++ b/core/res/res/interpolator-watch/trim_offset_interpolator.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0,0.0 l 0.4,1.0 l 0.6,0.0 L 1.0,1.0" />
diff --git a/core/res/res/interpolator-watch/trim_start_interpolator.xml b/core/res/res/interpolator-watch/trim_start_interpolator.xml
new file mode 100644
index 000000000000..365609c97d75
--- /dev/null
+++ b/core/res/res/interpolator-watch/trim_start_interpolator.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:pathData="M 0.0,0.0 l 0.2,0.0 c 0.08,0.0 0.04,1.0 0.2,1.0 l 0.6,0.0 L 1.0,1.0" />
diff --git a/core/res/res/layout-watch/preference_widget_switch.xml b/core/res/res/layout-watch/preference_widget_switch.xml
index a1a845abfe3a..5881cf0c4d1e 100644
--- a/core/res/res/layout-watch/preference_widget_switch.xml
+++ b/core/res/res/layout-watch/preference_widget_switch.xml
@@ -24,8 +24,7 @@
android:thumb="@drawable/watch_switch_thumb_material_anim"
android:thumbTint="@color/watch_switch_thumb_color_material"
android:thumbTintMode="multiply"
- android:track="@drawable/watch_switch_track_mtrl"
- android:trackTint="@color/watch_switch_track_color_material"
+ android:track="@drawable/watch_switch_track_material"
android:focusable="false"
android:clickable="false"
android:background="@null" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 677017d45a0b..be8c1cd3f4e8 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Gekoppel aan <xliff:g id="SESSION">%s</xliff:g>. Tik om die netwerk te bestuur."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Altydaan-VPN koppel tans..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Altydaan-VPN gekoppel"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Altydaan-VPN is ontkoppel"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Altydaan-VPN-fout"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Tik om op te stel"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tik om op te stel"</string>
<string name="upload_file" msgid="2897957172366730416">"Kies lêer"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Geen lêer gekies nie"</string>
<string name="reset" msgid="2448168080964209908">"Stel terug"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Voer taalnaam in"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Voorgestel"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Alle tale"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Soek"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Werkmodus is AF"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Stel werkprofiel in staat om te werk, insluitend programme, agtergrondsinkronisering en verwante kenmerke."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 721f884d4412..e92b2815e5dd 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"ለ<xliff:g id="SESSION">%s</xliff:g> የተገናኘ። አውታረመረቡን ለማደራጀት ሁለቴ ንካ።"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ሁልጊዜ የበራ VPN በመገናኘት ላይ…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"ሁልጊዜ የበራ VPN ተገናኝቷል"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ሁልጊዜ የበራ የVPN ግንኙነት ተቋርጧል"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"ሁልጊዜ የበራ VPN ስህተት"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"ለማዋቀር መታ ያድርጉ"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"ለማዋቀር መታ ያድርጉ"</string>
<string name="upload_file" msgid="2897957172366730416">"ፋይል ምረጥ"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ምንም ፋይል አልተመረጠም"</string>
<string name="reset" msgid="2448168080964209908">"ዳግም አስጀምር"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"የቋንቋ ስም ይተይቡ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"የተጠቆሙ"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"ሁሉም ቋንቋዎች"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"ፈልግ"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"የሥራ ሁነታ ጠፍቷል"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"መተግበሪያዎችን፣ የበስተጀርባ ሥምረት እና ተዛማጅ ባሕሪዎችን ጨምሮ የሥራ መገለጫ እንዲሰራ ይፍቀዱ።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 630c292fac2c..5d6fb92dad5e 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1343,8 +1343,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"تم الاتصال بـ <xliff:g id="SESSION">%s</xliff:g>. انقر لإدارة الشبكة."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"‏جارٍ الاتصال بشبكة ظاهرية خاصة (VPN) دائمة التشغيل..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"‏تم الاتصال بشبكة ظاهرية خاصة (VPN) دائمة التشغيل"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"‏تم فصل الشبكة الظاهرية الخاصة (VPN) دائمة التشغيل"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"‏خطأ بشبكة ظاهرية خاصة (VPN) دائمة التشغيل"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"انقر للتهيئة."</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"انقر للإعداد."</string>
<string name="upload_file" msgid="2897957172366730416">"اختيار ملف"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"لم يتم اختيار أي ملف"</string>
<string name="reset" msgid="2448168080964209908">"إعادة تعيين"</string>
@@ -1791,6 +1792,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"اكتب اسم اللغة"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"المقترحة"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"جميع اللغات"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"كل المناطق"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"البحث"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"وضع العمل معطَّل"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"السماح باستخدام الملف الشخصي للعمل، بما في ذلك التطبيقات ومزامنة الخلفية والميزات ذات الصلة."</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 502131ac0b09..8c375a0bed1e 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> sessiyaya qoşulun. Şəbəkəni idarə etmək üçün tıklayın."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Həmişə aktiv VPN bağlanır..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN bağlantısı həmişə aktiv"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Həmişə aktiv VPN bağlantısı kəsildi"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Həmişə aktiv VPN xətası"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Konfiqurasiya üçün tıklayın"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Quraşdırmaq üçün tıklayın"</string>
<string name="upload_file" msgid="2897957172366730416">"Fayl seçin"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Heç bir fayl seçilməyib"</string>
<string name="reset" msgid="2448168080964209908">"Sıfırlayın"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Dil adını daxil edin"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Təklif edilmiş"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Bütün dillər"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Bütün bölgələr"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Axtarın"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"İş rejimi DEAKTİVDİR"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Tətbiq, arxa fon sinxronizasiyası və digər əlaqədar xüsusiyyətlər daxil olmaqla iş profilinin fəaliyyətinə icazə verin."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index c8fc56f63508..2cf1d7c6414c 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1268,8 +1268,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Povezano sa sesijom <xliff:g id="SESSION">%s</xliff:g>. Dodirnite da biste upravljali mrežom."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Povezivanje stalno uključenog VPN-a..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Stalno uključeni VPN je povezan"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Veza sa stalno uključenim VPN-om je prekinuta"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Greška stalno uključenog VPN-a"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Dodirnite da biste konfigurisali"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Dodirnite da biste podesili"</string>
<string name="upload_file" msgid="2897957172366730416">"Odaberi datoteku"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nije izabrana nijedna datoteka"</string>
<string name="reset" msgid="2448168080964209908">"Ponovo postavi"</string>
@@ -1683,6 +1684,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Unesite naziv jezika"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženi"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Svi jezici"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Pretraži"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Režim za Work je ISKLJUČEN"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Dozvoljava profilu za Work da funkcioniše, uključujući aplikacije, sinhronizaciju u pozadini i srodne funkcije."</string>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index c98b1513e954..43c878254d21 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -1293,8 +1293,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Падлучаны да <xliff:g id="SESSION">%s</xliff:g>. Націсніце, каб кiраваць сеткай."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Падключэнне заўсёды ўключанага VPN..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Заўсёды ўключаны i падключаны VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Заўсёды ўключаны VPN адключаны"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Памылка заўсёды ўключанага VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Дакраніцеся, каб сканфігураваць"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Дакраніцеся, каб наладзіць"</string>
<string name="upload_file" msgid="2897957172366730416">"Выберыце файл"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Файл не выбраны"</string>
<string name="reset" msgid="2448168080964209908">"Скінуць"</string>
@@ -1719,6 +1720,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Увядзіце назву мовы"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Прапанаваныя"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Усе мовы"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Усе рэгіёны"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Шукаць"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Рэжым працы АДКЛЮЧАНЫ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Дазволіць функцыянаванне працоўнага профілю, у тым ліку праграм, фонавай сінхранізацыі і звязаных з імі функцый."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index cffc8509134b..33b78db7e655 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Свързана с/ъс <xliff:g id="SESSION">%s</xliff:g>. Докоснете, за да управлявате мрежата."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Установява се връзка с винаги включената виртуална частна мрежа (VPN)…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Установена е връзка с винаги включената виртуална частна мрежа (VPN)"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Няма връзка с винаги включената виртуална частна мрежа (VPN)"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Грешка във винаги включената виртуална частна мрежа (VPN)"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Докоснете, за да конфигурирате"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Докоснете, за да настроите"</string>
<string name="upload_file" msgid="2897957172366730416">"Избор на файл"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Няма избран файл"</string>
<string name="reset" msgid="2448168080964209908">"Повторно задаване"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Въведете име на език"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Всички езици"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Всички региони"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Търсене"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Работният режим е ИЗКЛЮЧЕН"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Разрешаване на функционирането на служебния потребителски профил, включително приложенията, синхронизирането на заден план и свързаните функции."</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index aa2d5d545c7f..6e894eb8e05c 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> তে সংযুক্ত হয়েছে৷ নেটওয়ার্ক পরিচালনা করতে আলতো চাপুন৷"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"সর্বদা-চালু VPN সংযুক্ত হচ্ছে..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"সর্বদা-চালু VPN সংযুক্ত হয়েছে"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"সর্বদা-চালু VPN এর সংযোগ বিচ্ছিন্ন হয়েছে"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"সর্বদা-চালু VPN ত্রুটি"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"কনফিগার করতে আলতো চাপুন"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"সেট আপ করতে আলতো চাপুন"</string>
<string name="upload_file" msgid="2897957172366730416">"ফাইল বেছে নিন"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"কোনো ফাইল নির্বাচন করা হয়নি"</string>
<string name="reset" msgid="2448168080964209908">"পুনরায় সেট করুন"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"ভাষার নাম লিখুন"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"প্রস্তাবিত"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"সকল ভাষা"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"সমস্ত অঞ্চল"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"অনুসন্ধান করুন"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"কাজের মোড বন্ধ আছে"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"অ্যাপ্লিকেশান, পটভূমি সিঙ্ক এবং সম্পর্কিত বৈশিষ্ট্যগুলি সহ কর্মস্থলের প্রোফাইলটিকে কাজ করার অনুমতি দিন।"</string>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index d9bb9f0ec518..bc364c7e92c1 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -1270,8 +1270,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Povezano sa sesijom <xliff:g id="SESSION">%s</xliff:g>. Dodirnite da upravljate mrežom."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Povezivanje na uvijek aktivni VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Povezan na uvijek aktivni VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Uvijek aktivni VPN nije povezan"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Greška u povezivanju na uvijek aktivni VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Dodirnite za konfiguriranje"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Dodirnite za postavke"</string>
<string name="upload_file" msgid="2897957172366730416">"Odabir fajla"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nije izabran nijedan fajl"</string>
<string name="reset" msgid="2448168080964209908">"Ponovno pokretanje"</string>
@@ -1685,6 +1686,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Ukucajte naziv jezika"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženo"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Svi jezici"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Sve regije"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pretraga"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Radni način rada je ISKLJUČEN"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Omogući radnom profilu da funkcionira, uključujući aplikacije, sinhronizaciju u pozadini i povezane funkcije."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index b3a0cdeb256b..ae3dce6a4d46 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Connectat a <xliff:g id="SESSION">%s</xliff:g>. Pica per gestionar la xarxa."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"T\'estàs connectant a la VPN sempre activada…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Estàs connectat a la VPN sempre activada"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"La VPN sempre activada està desconnectada"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Error de la VPN sempre activada"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Toca per configurar"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Toca per configurar"</string>
<string name="upload_file" msgid="2897957172366730416">"Trieu un fitxer"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"No s\'ha escollit cap fitxer"</string>
<string name="reset" msgid="2448168080964209908">"Restableix"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Nom de l\'idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggerits"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Tots els idiomes"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Totes les regions"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Cerca"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Mode de feina desactivat"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Permet que el perfil professional funcioni, incloses les aplicacions, la sincronització en segon pla i les funcions relacionades."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 59f83853d967..bffd34bc3c89 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1293,8 +1293,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Připojeno k relaci <xliff:g id="SESSION">%s</xliff:g>. Klepnutím můžete síť spravovat."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Připojování k trvalé síti VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Je připojena trvalá síť VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Trvalá síť VPN je odpojena"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Chyba trvalé sítě VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Klepnutím zahájíte konfiguraci"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Klepnutím přejděte do Nastavení"</string>
<string name="upload_file" msgid="2897957172366730416">"Zvolit soubor"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Není vybrán žádný soubor"</string>
<string name="reset" msgid="2448168080964209908">"Resetovat"</string>
@@ -1719,6 +1720,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Zadejte název jazyka"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Navrhované"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Všechny jazyky"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Vyhledávání"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Pracovní režim je VYPNUTÝ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Povolí fungování pracovního profilu, včetně aplikací, synchronizace na pozadí a souvisejících funkcí."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 48b3b87c8918..68480b59ef64 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Forbundet til <xliff:g id="SESSION">%s</xliff:g>. Tryk for at administrere netværket."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Opretter forbindelse til altid aktiveret VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN er forbundet"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Forbindelsen til altid aktiveret VPN er afbrudt"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Fejl i altid aktiveret VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Tryk for at konfigurere"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tryk for at konfigurere"</string>
<string name="upload_file" msgid="2897957172366730416">"Vælg fil"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string>
<string name="reset" msgid="2448168080964209908">"Nulstil"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Angiv sprogets navn"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Foreslået"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Alle sprog"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Alle områder"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Søg"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Arbejdstilstand er slået FRA"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Tillad, at arbejdsprofilen aktiveres, bl.a. i forbindelse med apps, baggrundssynkronisering og relaterede funktioner."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index cb61390d9452..c2a775bb3158 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Verbunden mit <xliff:g id="SESSION">%s</xliff:g>. Zum Verwalten des Netzwerks tippen"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Verbindung zu durchgehend aktivem VPN wird hergestellt…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Mit durchgehend aktivem VPN verbunden"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Verbindung zu durchgehend aktivem VPN getrennt"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Durchgehend aktives VPN – Verbindungsfehler"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Zum Konfigurieren tippen"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Zum Einrichten tippen"</string>
<string name="upload_file" msgid="2897957172366730416">"Datei auswählen"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Keine ausgewählt"</string>
<string name="reset" msgid="2448168080964209908">"Zurücksetzen"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Sprache eingeben"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Vorschläge"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Alle Sprachen"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Alle Regionen"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Suche"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Arbeitsmodus ist AUS"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Arbeitsprofil aktivieren, einschließlich Apps, Synchronisierung im Hintergrund und verknüpfter Funktionen."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 54f39ebd334c..9d4936cc552b 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Συνδέθηκε με <xliff:g id="SESSION">%s</xliff:g>. Πατήστε για να διαχειριστείτε το δίκτυο."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Σύνδεση πάντα ενεργοποιημένου VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Έχει συνδεθεί πάντα ενεργοποιημένο VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Το πάντα ενεργοποιημένο VPN αποσυνδέθηκε"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Σφάλμα πάντα ενεργοποιημένου VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Πατήστε για διαμόρφωση"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Πατήστε για ρύθμιση"</string>
<string name="upload_file" msgid="2897957172366730416">"Επιλογή αρχείου"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Δεν επιλέχθηκε κανένα αρχείο."</string>
<string name="reset" msgid="2448168080964209908">"Επαναφορά"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Εισαγ. όνομα γλώσσας"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Προτεινόμενες"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Όλες οι γλώσσες"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Όλες οι περιοχές"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Αναζήτηση"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Λειτουργία εργασίας ΑΠΕΝΕΡΓ/ΝΗ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Να επιτρέπεται η λειτουργία του προφίλ εργασίας σας, συμπεριλαμβανομένων των εφαρμογών, του συγχρονισμού στο παρασκήνιο και των σχετικών λειτουργιών."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index aeb9634eb480..7cbe6a89f16d 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN connecting…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN connected"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN disconnected"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Always-on VPN error"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Tap to configure"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tap to set up"</string>
<string name="upload_file" msgid="2897957172366730416">"Choose file"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string>
<string name="reset" msgid="2448168080964209908">"Reset"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"All regions"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index aeb9634eb480..7cbe6a89f16d 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN connecting…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN connected"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN disconnected"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Always-on VPN error"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Tap to configure"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tap to set up"</string>
<string name="upload_file" msgid="2897957172366730416">"Choose file"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string>
<string name="reset" msgid="2448168080964209908">"Reset"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"All regions"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index aeb9634eb480..7cbe6a89f16d 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Connected to <xliff:g id="SESSION">%s</xliff:g>. Tap to manage the network."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN connecting…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN connected"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN disconnected"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Always-on VPN error"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Tap to configure"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tap to set up"</string>
<string name="upload_file" msgid="2897957172366730416">"Choose file"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"No file chosen"</string>
<string name="reset" msgid="2448168080964209908">"Reset"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Type language name"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggested"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"All languages"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"All regions"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Search"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 85fb97c0c8ed..c8f2099d57ce 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Pulsa para gestionar la red."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Estableciendo conexión con la VPN siempre activada..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Se estableció conexión con la VPN siempre activada."</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Se desconectó la VPN siempre activada"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Se produjo un error al establecer conexión con la VPN siempre activada."</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Presiona para configurar"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Presiona para configurar"</string>
<string name="upload_file" msgid="2897957172366730416">"Elegir archivo"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"No se seleccionó un archivo."</string>
<string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Nombre del idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos los idiomas"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Búsqueda"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabajo DESACTIVADO"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Permite que se active el perfil de trabajo, incluidas las apps, la sincronización en segundo plano y las funciones relacionadas."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index df9251f86c56..d93b9a933e54 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toca para administrar la red."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Conectando VPN siempre activada…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN siempre activada conectada"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN siempre activada desconectada"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Error de VPN siempre activada"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Toca para configurar"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Toca para configurar"</string>
<string name="upload_file" msgid="2897957172366730416">"Seleccionar archivo"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Archivo no seleccionado"</string>
<string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Nombre de idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos los idiomas"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Todas las regiones"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Buscar"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabajo desactivado"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Permite que se utilice el perfil de trabajo, incluidas las aplicaciones, la sincronización en segundo plano y las funciones relacionadas."</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 44698fe64463..508c45133d75 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Ühendatud seansiga <xliff:g id="SESSION">%s</xliff:g>. Koputage võrgu haldamiseks"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Ühendamine alati sees VPN-iga …"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Ühendatud alati sees VPN-iga"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Alati sees VPN pole ühendatud"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Alati sees VPN-i viga"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Puudutage seadistamiseks"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Puudutage seadistamiseks"</string>
<string name="upload_file" msgid="2897957172366730416">"Valige fail"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ühtegi faili pole valitud"</string>
<string name="reset" msgid="2448168080964209908">"Lähtesta"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Sisestage keele nimi"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Soovitatud"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Kõik keeled"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Kõik piirkonnad"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Otsing"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Töörežiim on VÄLJA LÜLITATUD"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Lubatakse tööprofiili toimingud, sh rakendused, taustal sünkroonimine ja seotud funktsioonid."</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 6f33f312bf59..28652ea25436 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> saiora konektatuta. Sakatu sarea kudeatzeko."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Beti aktibatuta dagoen VPNa konektatzen…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Beti aktibatuta dagoen VPNa konektatu da"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Deskonektatu egin da beti aktibatuta dagoen VPN konexioa"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Beti aktibatuta dagoen VPN errorea"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Sakatu konfiguratzeko"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Konfiguratzeko, sakatu hau"</string>
<string name="upload_file" msgid="2897957172366730416">"Aukeratu fitxategia"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ez da fitxategirik aukeratu"</string>
<string name="reset" msgid="2448168080964209908">"Berrezarri"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Adierazi hizkuntza"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Iradokitakoak"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Hizkuntza guztiak"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Bilaketa"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Desaktibatuta dago laneko modua"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Baimendu laneko profilak funtzionatzea, besteak beste, aplikazioak, atzeko planoko sinkronizazioa eta erlazionatutako eginbideak."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index e86b256454ab..899190e66e8f 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -924,9 +924,9 @@
<item quantity="one">در <xliff:g id="COUNT_1">%d</xliff:g> سال</item>
<item quantity="other">در <xliff:g id="COUNT_1">%d</xliff:g> سال</item>
</plurals>
- <string name="VideoView_error_title" msgid="3534509135438353077">"مشکل در ویدیو"</string>
- <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"متأسفیم، این ویدیو برای پخش جریانی با این دستگاه معتبر نیست."</string>
- <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"پخش این ویدیو ممکن نیست."</string>
+ <string name="VideoView_error_title" msgid="3534509135438353077">"مشکل در ویدئو"</string>
+ <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"متأسفیم، این ویدئو برای پخش جریانی با این دستگاه معتبر نیست."</string>
+ <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"پخش این ویدئو ممکن نیست."</string>
<string name="VideoView_error_button" msgid="2822238215100679592">"تأیید"</string>
<string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>، <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="noon" msgid="7245353528818587908">"ظهر"</string>
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"به <xliff:g id="SESSION">%s</xliff:g> متصل شد. برای مدیریت شبکه ضربه بزنید."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"‏در حال اتصال VPN همیشه فعال…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"‏VPN همیشه فعال متصل شد"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"‏ارتباط VPN همیشه روشن قطع شد"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"‏خطای VPN همیشه فعال"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"جهت پیکربندی ضربه بزنید"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"برای راه‌اندازی ضربه بزنید"</string>
<string name="upload_file" msgid="2897957172366730416">"انتخاب فایل"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"هیچ فایلی انتخاب نشد"</string>
<string name="reset" msgid="2448168080964209908">"بازنشانی"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"نام زبان را تایپ کنید"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"پیشنهادشده"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"همه زبان‌ها"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"همه منطقه‌ها"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"جستجو"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"حالت کاری خاموش است"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"به نمایه کاری اجازه فعالیت ( شامل استفاده از برنامه‌ها، همگام‌سازی در پس‌زمینه و قابلیت‌های مرتبط) داده شود."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index e624e22da077..ccafbb5036d6 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Yhdistetty: <xliff:g id="SESSION">%s</xliff:g>. Hallinnoi verkkoa napauttamalla."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Yhdistetään aina käytössä olevaan VPN-verkkoon..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Yhdistetty aina käytössä olevaan VPN-verkkoon"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Aina käytössä olevan VPN:n yhteys on katkaistu"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Aina käytössä oleva VPN: virhe"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Määritä napauttamalla."</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Määritä koskettamalla."</string>
<string name="upload_file" msgid="2897957172366730416">"Valitse tiedosto"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ei valittua tiedostoa"</string>
<string name="reset" msgid="2448168080964209908">"Palauta"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Anna kielen nimi"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Ehdotukset"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Kaikki kielet"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Kaikki alueet"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Haku"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Työtila on pois käytöstä"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Sallii työprofiiliin toiminnan, esimerkiksi sovellukset ja taustasynkronoinnin."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index f6b2ab1758e6..8df66e3fc907 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN permanent en cours de connexion…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN permanent connecté"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"RPV permanent déconnecté"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Erreur du VPN permanent"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Touchez pour configurer"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Touchez pour configurer"</string>
<string name="upload_file" msgid="2897957172366730416">"Choisir un fichier"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Aucun fichier sélectionné"</string>
<string name="reset" msgid="2448168080964209908">"Réinitialiser"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Entrez la langue"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggestions"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Toutes les langues"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Rechercher"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Le mode Travail est désactivé"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Autoriser le fonctionnement du profil professionnel, y compris les applications, la synchronisation en arrière-plan et les fonctionnalités associées."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index d726c63baf29..b211a776344a 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN permanent en cours de connexion…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN permanent connecté"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN permanent déconnecté"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Erreur du VPN permanent"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Appuyez ici pour configurer."</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Appuyer pour configurer"</string>
<string name="upload_file" msgid="2897957172366730416">"Sélectionner un fichier"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Aucun fichier sélectionné"</string>
<string name="reset" msgid="2448168080964209908">"Réinitialiser"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Saisissez la langue"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Recommandations"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Toutes les langues"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Rechercher"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Mode professionnel DÉSACTIVÉ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Autoriser le fonctionnement du profil professionnel, y compris les applications, la synchronisation en arrière-plan et les fonctionnalités associées."</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 16a46f1adee5..62e2fdd2f24b 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toca aquí para xestionar a rede."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sempre activada conectándose..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre activada conectada"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Desconectouse a VPN sempre activada"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro na VPN sempre activada"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Toca para configurar"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tocar para configurar"</string>
<string name="upload_file" msgid="2897957172366730416">"Escoller un ficheiro"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Non se seleccionou ningún ficheiro"</string>
<string name="reset" msgid="2448168080964209908">"Restablecer"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suxeridos"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Buscar"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Modo de traballo DESACTIVADO"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Permite que funcione o perfil de traballo, incluídas as aplicacións, a sincronización en segundo plano e as funcións relacionadas."</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index 1f49bec1f8ed..a4d2d6e1b20d 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> થી કનેક્ટ થયાં. નેટવર્કને સંચાલિત કરવા માટે ટૅપ કરો."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"હંમેશા-ચાલુ VPN કનેક્ટ થઈ રહ્યું છે…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"હંમેશા-ચાલુ VPN કનેક્ટ થયું"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"હંમેશાં-ચાલુ VPN ડિસ્કનેક્ટ થયું"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"હંમેશાં ચાલુ VPN ભૂલ"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"ગોઠવવા માટે ટૅપ કરો"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"સેટ કરવા માટે ટૅપ કરો"</string>
<string name="upload_file" msgid="2897957172366730416">"ફાઇલ પસંદ કરો"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"કોઈ ફાઇલ પસંદ કરેલી નથી"</string>
<string name="reset" msgid="2448168080964209908">"ફરીથી સેટ કરો"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"ભાષાનું નામ ટાઇપ કરો"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"સૂચવેલા"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"બધી ભાષાઓ"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"તમામ પ્રદેશ"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"શોધ"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"કાર્ય મોડ બંધ છે"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"કાર્ય પ્રોફાઇલને ઍપ્લિકેશનો, પૃષ્ઠભૂમિ સમન્વયન અને સંબંધિત સુવિધાઓ સહિતનું કાર્ય કરવાની મંજૂરી આપો."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 3fd6f9e7e4b1..3956c3500c06 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> से कनेक्‍ट किया गया. नेटवर्क प्रबंधित करने के लिए टैप करें."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"हमेशा-चालू VPN कनेक्ट हो रहा है…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"हमेशा-चालू VPN कनेक्ट है"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"हमेशा-चालू VPN डिस्‍कनेक्‍ट है"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"हमेशा-चालू VPN त्रुटि"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"कॉन्फ़िगर करने के लिए टैप करें"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"सेट करने के लिए टैप करें"</string>
<string name="upload_file" msgid="2897957172366730416">"फ़ाइल चुनें"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"कोई फ़ाइल चुनी नहीं गई"</string>
<string name="reset" msgid="2448168080964209908">"रीसेट करें"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"भाषा का नाम लिखें"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"सुझाए गए"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"सभी भाषाएं"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"सभी क्षेत्र"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"खोजें"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बंद है"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"ऐप्स, पृष्ठभूमि समन्वयन और संबंधित सुविधाओं सहित कार्य प्रोफ़ाइल को काम करने की अनुमति दें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 8b503c985307..d3e309e7dfe3 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1268,8 +1268,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Povezan sa sesijom <xliff:g id="SESSION">%s</xliff:g>. Dotaknite za upravljanje mrežom."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Povezivanje s uvijek uključenom VPN mrežom…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Povezan s uvijek uključenom VPN mrežom"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Prekinuta je veza s uvijek uključenom VPN mrežom"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Pogreška uvijek uključene VPN mreže"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Dodirnite da biste konfigurirali"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Dodirnite za postavljanje"</string>
<string name="upload_file" msgid="2897957172366730416">"Odaberite datoteku"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nema odabranih datoteka"</string>
<string name="reset" msgid="2448168080964209908">"Ponovo postavi"</string>
@@ -1683,6 +1684,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Unesite naziv jezika"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Predloženo"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Svi jezici"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Sve regije"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pretraži"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Radni je način ISKLJUČEN"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Omogućuje radnom profilu da funkcionira, uključujući aplikacije, sinkronizaciju u pozadini i povezane značajke."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index ebdae0fe6756..bc9cf5629249 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Csatlakozva ide: <xliff:g id="SESSION">%s</xliff:g>. Érintse meg a hálózat kezeléséhez."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Csatlakozás a mindig bekapcsolt VPN-hez..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Csatlakozva a mindig bekapcsolt VPN-hez"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Kapcsolat bontva a mindig bekapcsolt VPN-nel"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Hiba a mindig bekapcsolt VPN-nel"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Koppintson a konfiguráláshoz"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Koppintson ide a beállításhoz"</string>
<string name="upload_file" msgid="2897957172366730416">"Fájl kiválasztása"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nincs fájl kiválasztva"</string>
<string name="reset" msgid="2448168080964209908">"Alaphelyzet"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Adja meg a nyelvet"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Javasolt"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Minden nyelv"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Minden régió"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Keresés"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"A munka mód KI van kapcsolva"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Munkaprofil használatának engedélyezése, beleértve az alkalmazásokat, a háttérben való szinkronizálást és a kapcsolódó funkciókat."</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 7178c5f11262..7a54f6678539 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Կապակացված է <xliff:g id="SESSION">%s</xliff:g>-ին: Սեղմեք` ցանցը կառավարելու համար:"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Միշտ-միացված VPN-ը կապվում է..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Միշտ-առցանց VPN-ը կապակցված է"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"«Միշտ միացված VPN»-ն անջատված է"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"VPN սխալը միշտ միացված"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Հպեք՝ կազմաձևելու համար"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Հպեք՝ կարգավորելու համար"</string>
<string name="upload_file" msgid="2897957172366730416">"Ընտրել ֆայլը"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ոչ մի ֆայլ չի ընտրված"</string>
<string name="reset" msgid="2448168080964209908">"Վերակայել"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Մուտքագրեք լեզուն"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Առաջարկներ"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Բոլոր լեզուները"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Բոլոր տարածաշրջանները"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Որոնում"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Աշխատանքային ռեժիմն ԱՆՋԱՏՎԱԾ Է"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Միացնել աշխատանքային պրոֆիլը՝ հավելվածները, ֆոնային համաժամեցումը և առնչվող գործառույթները"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 41902b54397c..bbae86dfb28a 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Tersambung ke <xliff:g id="SESSION">%s</xliff:g>. Ketuk untuk mengelola jaringan."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Menyambungkan VPN selalu aktif..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN selalu aktif tersambung"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN selalu aktif terputus"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Kesalahan VPN selalu aktif"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Ketuk untuk mengonfigurasi"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Ketuk untuk menyiapkan"</string>
<string name="upload_file" msgid="2897957172366730416">"Pilih file"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Tidak ada file yang dipilih"</string>
<string name="reset" msgid="2448168080964209908">"Setel ulang"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Ketik nama bahasa"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Disarankan"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Semua bahasa"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Semua wilayah"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Telusuri"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Mode kerja NONAKTIF"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Izinkan profil kerja berfungsi, termasuk aplikasi, sinkronisasi latar belakang, dan fitur terkait."</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 34165bafa8ce..45a97e95fc1f 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Tengt við <xliff:g id="SESSION">%s</xliff:g>. Ýttu til að hafa umsjón með netinu."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Sívirkt VPN tengist…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Sívirkt VPN tengt"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Sívirkt VPN aftengt"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Villa í sívirku VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Ýttu til að stilla"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Ýttu til að setja upp"</string>
<string name="upload_file" msgid="2897957172366730416">"Velja skrá"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Engin skrá valin"</string>
<string name="reset" msgid="2448168080964209908">"Endurstilla"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Sláðu inn heiti tungumáls"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Tillögur"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Öll tungumál"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Öll svæði"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Leita"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Slökkt á vinnusniði"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Leyfa virkni vinnusniðs, m.a. forrita, samstillingar í bakgrunni og tengdra eiginleika."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 5668e6d264be..34946ff2a8f8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Collegata a <xliff:g id="SESSION">%s</xliff:g>. Tocca per gestire la rete."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Connessione a VPN sempre attiva…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre attiva connessa"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN sempre attiva disconnessa"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Errore VPN sempre attiva"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Tocca per configurare"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tocca per configurare"</string>
<string name="upload_file" msgid="2897957172366730416">"Scegli file"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nessun file è stato scelto"</string>
<string name="reset" msgid="2448168080964209908">"Reimposta"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Digita nome lingua"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Suggerite"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Tutte le lingue"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Tutte le aree geografiche"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Cerca"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Modalità Lavoro DISATTIVATA"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Attiva il profilo di lavoro, incluse app, sincronizzazione in background e funzioni correlate."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 19f39536c650..f6576415ce2d 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1293,8 +1293,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"מחובר אל <xliff:g id="SESSION">%s</xliff:g>. הקש כדי לנהל את הרשת."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"‏ה-VPN שמופעל תמיד, מתחבר..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"‏ה-VPN שפועל תמיד, מחובר"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"‏חיבור תמידי ל-VPN מנותק"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"‏שגיאת VPN שמופעל תמיד"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"הקש כדי להגדיר"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"הקש כדי להגדיר"</string>
<string name="upload_file" msgid="2897957172366730416">"בחר קובץ"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"לא נבחר קובץ"</string>
<string name="reset" msgid="2448168080964209908">"איפוס"</string>
@@ -1719,6 +1720,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"הקלד שם שפה"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"הצעות"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"כל השפות"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"כל האזורים"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"חיפוש"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"מצב העבודה כבוי"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"אפשר לפרופיל העבודה לפעול, כולל אפליקציות, סנכרון ברקע ותכונות קשורות."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 23e9535cc5c0..3408ef8f2546 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -374,7 +374,7 @@
<string name="permdesc_callPhone" msgid="3740797576113760827">"電話番号への自動発信をアプリに許可します。これにより、予期せぬ発信や料金が発生する可能性があります。なお、緊急通報番号への発信は許可されません。悪意のあるアプリが確認なしで発信し、料金が発生する恐れがあります。"</string>
<string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS通話サービスへのアクセス"</string>
<string name="permdesc_accessImsCallService" msgid="8992884015198298775">"IMSサービスがユーザー操作なしで電話をかけることをアプリに許可します。"</string>
- <string name="permlab_readPhoneState" msgid="9178228524507610486">"端末のステータスとIDの読み取り"</string>
+ <string name="permlab_readPhoneState" msgid="9178228524507610486">"端末情報と ID の読み取り"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"端末の電話機能へのアクセスをアプリに許可します。これにより、電話番号、端末ID、通話中かどうか、通話相手の電話番号をアプリから特定できるようになります。"</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"タブレットのスリープを無効化"</string>
<string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"テレビのスリープを無効化"</string>
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>に接続しました。ネットワークを管理するにはタップしてください。"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPNに常時接続しています…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPNに常時接続しました"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"常時接続 VPN の接続を解除しました"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"常時接続VPNのエラー"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"タップして設定"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"設定するにはタップします"</string>
<string name="upload_file" msgid="2897957172366730416">"ファイルを選択"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ファイルが選択されていません"</string>
<string name="reset" msgid="2448168080964209908">"リセット"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"言語名を入力"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"言語の候補"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"すべての言語"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"すべての地域"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"検索"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Work モード OFF"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"仕事用プロファイルで、アプリ、バックグラウンド同期などの関連機能の使用を許可します。"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index fbe1b0083b9d..95829e162968 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"მიერთებულია <xliff:g id="SESSION">%s</xliff:g>-ზე. შეეხეთ ქსელის სამართავად."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"მიმდინარეობს მუდმივად ჩართული VPN-ის მიერთება…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"მუდმივად ჩართული VPN-ის მიერთებულია"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"მუდმივად ჩართული VPN გათიშულია"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"შეცდომა მუდამ VPN-ზე"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"შეეხეთ პარამეტრების კონფიგურაციისთვის"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"შეეხეთ დასაყენებლად"</string>
<string name="upload_file" msgid="2897957172366730416">"ფაილის არჩევა"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ფაილი არჩეული არ არის"</string>
<string name="reset" msgid="2448168080964209908">"საწყისზე დაბრუნება"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"აკრიფეთ ენის სახელი"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"რეკომენდებული"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"ყველა ენა"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"ყველა რეგიონი"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"ძიება"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"სამსახურის რეჟიმი გამორთულია"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"სამსახურის პროფილის მუშაობის დაშვება, მათ შორის, აპების, ფონური სინქრონიზაციის და დაკავშირებული ფუნქციების."</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 11497b962ae0..e34a2b4b44e0 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> жүйесіне жалғанған. Желіні басқару үшін түріңіз."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Әрқашан қосылған ВЖЖ жалғануда…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Әрқашан қосылған ВЖЖ жалғанған"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Әрқашан қосулы VPN желісі ажыратылды"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Әрқашан қосылған ВЖЖ қателігі"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Конфигурациялау үшін түртіңіз"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Реттеу үшін түртіңіз"</string>
<string name="upload_file" msgid="2897957172366730416">"Файлды таңдау"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ешқандай файл таңдалмаған"</string>
<string name="reset" msgid="2448168080964209908">"Қайта реттеу"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Тіл атауын теріңіз"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Ұсынылған"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Барлық тілдер"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Барлық аймақтар"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Іздеу"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Жұмыс режимі ӨШІРУЛІ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Жұмыс профиліне, соның ішінде, қолданбаларға, фондық синхрондауға және қатысты мүмкіндіктерге жұмыс істеуге рұқсат ету."</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 85fb30317281..b0dfb50bde4c 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1245,8 +1245,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"បាន​ភ្ជាប់​ទៅ <xliff:g id="SESSION">%s</xliff:g> ។ ប៉ះ ដើម្បី​គ្រប់គ្រង​បណ្ដាញ។"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"បើក​ការ​តភ្ជាប់ VPN ជា​និច្ច..។"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"ភ្ជាប់ VPN ជា​និច្ច"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"បានផ្តាច់ VPN ដែលបើកជានិច្ច"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"បើក​កំហុស VPN ជា​និច្ច"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"ប៉ះដើម្បីកំណត់រចនាសម្ព័ន្ធ"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"ប៉ះដើម្បីដំឡើង"</string>
<string name="upload_file" msgid="2897957172366730416">"ជ្រើស​​ឯកសារ"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"គ្មាន​ឯកសារ​បាន​ជ្រើស"</string>
<string name="reset" msgid="2448168080964209908">"កំណត់​ឡើងវិញ"</string>
@@ -1649,6 +1650,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"វាយបញ្ចូលឈ្មោះភាសា"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"បាន​ស្នើ"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"ភាសាទាំងអស់"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"ស្វែងរក"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"របៀបការងារបានបិទ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"អនុញ្ញាតឲ្យប្រវត្តិរូបការងារដំណើរការ ដោយរាប់បញ្ចូលទាំងកម្មវិធី ការធ្វើសមកាលកម្មផ្ទៃខាងក្រោយ និងលក្ខណៈពិសេសដែលពាក់ព័ន្ធ។"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index ab3775101c15..25cba944dfd7 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ. ನೆಟ್‍ವರ್ಕ್ ನಿರ್ವಹಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ಯಾವಾಗಲೂ-ಆನ್ VPN ಸಂಪರ್ಕಗೊಳ್ಳುತ್ತಿದೆ…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"ಯಾವಾಗಲೂ-ಆನ್ VPN ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ಯಾವಾಗಲೂ-ಆನ್ VPN ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"ಯಾವಾಗಲೂ-ಆನ್ VPN ದೋಷ"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"ಕಾನ್ಫಿಗರ್ ಮಾಡಲು ಟ್ಯಾಪ್‌ ಮಾಡಿ"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"ಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="upload_file" msgid="2897957172366730416">"ಫೈಲ್ ಆಯ್ಕೆಮಾಡು"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ಯಾವುದೇ ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿಲ್ಲ"</string>
<string name="reset" msgid="2448168080964209908">"ಮರುಹೊಂದಿಸು"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"ಭಾಷೆ ಹೆಸರನ್ನು ಟೈಪ್ ಮಾಡಿ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"ಸೂಚಿತ ಭಾಷೆ"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"ಎಲ್ಲಾ ಭಾಷೆಗಳು"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"ಎಲ್ಲಾ ಪ್ರದೇಶಗಳು"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"ಹುಡುಕು"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"ಕೆಲಸದ ಮೋಡ್ ಆಫ್ ಆಗಿದೆ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಹಿನ್ನೆಲೆ ಸಿಂಕ್ ಮತ್ತು ಇತರ ಸಂಬಂಧಿತ ವೈಶಿಷ್ಟ್ಯಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌‌ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಅನುಮತಿಸಿ."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 1df55c92d810..353ff86f4ba1 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>에 연결되어 있습니다. 네트워크를 관리하려면 누르세요."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"연결 유지 VPN에 연결하는 중…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"연결 유지 VPN에 연결됨"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"연결 유지 VPN 연결 해제됨"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"연결 유지 VPN 오류"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"설정하려면 탭하세요."</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"탭하여 설정"</string>
<string name="upload_file" msgid="2897957172366730416">"파일 선택"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"파일을 선택하지 않았습니다."</string>
<string name="reset" msgid="2448168080964209908">"초기화"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"언어 이름 입력"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"추천"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"모든 언어"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"검색"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"직장 모드가 사용 중지됨"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"앱, 백그라운드 동기화 및 관련 기능을 포함한 직장 프로필이 작동하도록 허용"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 9e0c6cf6675a..7de6b035afcd 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> сеансына туташуу ишке ашты. Желенин параметрлерин өзгөртүү үчүн бул жерди басыңыз."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Дайым иштеген VPN туташууда…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Дайым иштеген VPN туташтырылды"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Дайым иштеген VPN ажыратылды"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Дайым иштеген VPN\'де ката кетти"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Конфигурациялоо үчүн таптап коюңуз"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Жөндөө үчүн таптаңыз"</string>
<string name="upload_file" msgid="2897957172366730416">"Файл тандоо"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Эч файл тандалган жок"</string>
<string name="reset" msgid="2448168080964209908">"Баштапкы абалга келтирүү"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Тилди киргизиңиз"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Сунушталган"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Бардык тилдер"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Издөө"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Жумуш режими ӨЧҮРҮЛГӨН"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Жумуш профилин, ошондой эле колдонмолорду, фондо шайкештирүү жана ага байланыштуу функцияларды иштетиңиз."</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index dbf404497fe4..b742837d0cd2 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"ເຊື່ອມຕໍ່ກັບ <xliff:g id="SESSION">%s</xliff:g> ແລ້ວ. ແຕະເພື່ອຈັດການເຄືອຂ່າຍ."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ກຳລັງເຊື່ອມຕໍ່ Always-on VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"ເຊື່ອມຕໍ່ VPN ແບບເປີດຕະຫຼອດເວລາແລ້ວ"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ຕັດການເຊື່ອມຕໍ່ VPN ແບບເປີດໃຊ້ຕະຫຼອດເວລາແລ້ວ"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"VPN ແບບເປີດຕະຫຼອດເກີດຄວາມຜິດພາດ"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"ແຕະເພື່ອຕັ້ງຄ່າ"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"ແຕະເພື່ອຕັ້ງຄ່າ"</string>
<string name="upload_file" msgid="2897957172366730416">"ເລືອກໄຟລ໌"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ບໍ່ໄດ້ເລືອກໄຟລ໌ເທື່ອ"</string>
<string name="reset" msgid="2448168080964209908">"ຣີເຊັດ"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"ພິມຊື່ພາສາ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"ແນະນຳ"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"ທຸກພາ​ສາ​"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"ຄົ້ນຫາ"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"ໂໝດບ່ອນເຮັດວຽກປິດຢູ່"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"ອະນຸຍາດໃຫ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກສາມາດນຳໃຊ້ໄດ້ ເຊິ່ງຮວມທັງແອັບ, ການຊິ້ງຂໍ້ມູນໃນພື້ນຫຼັງ ແລະ ຄຸນສົມບັດທີ່ກ່ຽວຂ້ອງ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7ab35aab50c1..b1da138ef597 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1293,8 +1293,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Prisijungta prie <xliff:g id="SESSION">%s</xliff:g>. Jei norite valdyti tinklą, palieskite."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Prisijungiama prie visada įjungto VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Prisijungta prie visada įjungto VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Visada įjungtas VPN atjungtas"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Visada įjungto VPN klaida"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Palieskite, kad konfigūruotumėte"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Palieskite, kad nustatytumėte"</string>
<string name="upload_file" msgid="2897957172366730416">"Pasirinkti failą"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nepasirinktas joks failas"</string>
<string name="reset" msgid="2448168080964209908">"Atstatyti"</string>
@@ -1719,6 +1720,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Įveskite kalbos pav."</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Siūloma"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Visos kalbos"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Visi regionai"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Paieška"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Darbo režimas išjungtas"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Leisti veikti darbo profiliui, įskaitant programas, sinchronizavimą fone ir susijusias funkcijas."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index e0c83c439227..2a9fb22e2ff6 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1268,8 +1268,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Ir izveidots savienojums ar: <xliff:g id="SESSION">%s</xliff:g>. Pieskarieties, lai pārvaldītu tīklu."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Notiek savienojuma izveide ar vienmēr ieslēgtu VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Izveidots savienojums ar vienmēr ieslēgtu VPN."</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Vienmēr ieslēgts VPN ir atvienots"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Kļūda saistībā ar vienmēr ieslēgtu VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Pieskarieties, lai konfigurētu."</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Pieskarieties, lai iestatītu."</string>
<string name="upload_file" msgid="2897957172366730416">"Izvēlēties failu"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Neviens fails nav izvēlēts"</string>
<string name="reset" msgid="2448168080964209908">"Atiestatīt"</string>
@@ -1683,6 +1684,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Ierakstiet valodas nosaukumu"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Ieteiktās"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Visas valodas"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Visi reģioni"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Meklēt"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Darba režīms IZSLĒGTS"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Atļaujiet darboties darba profilam, tostarp lietotnēm, sinhronizācijai fonā un saistītajām funkcijām."</string>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 4e17e985a147..b1dd47b0c6a1 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -70,11 +70,4 @@
</string-array>
<string translatable="false" name="prohibit_manual_network_selection_in_gobal_mode">true</string>
- <!-- Network switching warnings use toasts. -->
- <integer translatable="false" name="config_networkNotifySwitchType">2</integer>
- <!-- Notify when switching from Wi-Fi to cellular data. -->
- <string-array translatable="false" name="config_networkNotifySwitches">
- <item>WIFI-CELLULAR</item>
- </string-array>
-
</resources>
diff --git a/core/res/res/values-mcc722-mnc36/config.xml b/core/res/res/values-mcc722-mnc36/config.xml
new file mode 100644
index 000000000000..daf5373f7b5b
--- /dev/null
+++ b/core/res/res/values-mcc722-mnc36/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Don't use roaming icon for considered operators -->
+ <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+ <item>72234</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 413fe0ab4794..e80dd1ed2eb9 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Поврзани сте на <xliff:g id="SESSION">%s</xliff:g>. Допрете за да управувате со мрежата."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Поврзување со секогаш вклучена VPN..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Поврзани со секогаш вклучена VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Секогаш вклучената VPN е неповрзана"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Грешка на секогаш вклучена VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Допрете за конфигурирање"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Допрете за да поставите"</string>
<string name="upload_file" msgid="2897957172366730416">"Избери датотека"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Не е избрана датотека"</string>
<string name="reset" msgid="2448168080964209908">"Ресетирај"</string>
@@ -1649,6 +1650,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Внеси име на јазик"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Сите јазици"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Сите региони"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Пребарај"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Режимот на работа е ИСКЛУЧЕН"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Дозволете работниот профил да функционира, вклучувајќи ги апликациите, синхронизирањето во заднина и други поврзани функции."</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 2d416ba2faa0..039c52e4e7a5 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> എന്ന സെഷനിലേക്ക് കണക്റ്റുചെയ്തു. നെറ്റ്‌വർക്ക് മാനേജുചെയ്യാൻ ടാപ്പുചെയ്യുക."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"എല്ലായ്‌പ്പോഴും ഓണായിരിക്കുന്ന VPN കണക്റ്റുചെയ്യുന്നു…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"എല്ലായ്‌പ്പോഴും ഓണായിരിക്കുന്ന VPN കണക്റ്റുചെയ്‌തു"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"\'എല്ലായ്‌പ്പോഴും ഓണായിരിക്കുന്ന VPN\' വിച്ഛേദിച്ചു"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"എല്ലായ്‌പ്പോഴും ഓണായിരിക്കുന്ന VPN പിശക്"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"കോൺഫിഗർ ചെയ്യുന്നതിന് ടാപ്പുചെയ്യുക"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"സജ്ജമാക്കാൻ ടാപ്പുചെയ്യുക"</string>
<string name="upload_file" msgid="2897957172366730416">"ഫയല്‍‌ തിരഞ്ഞെടുക്കുക"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ഫയലൊന്നും തിരഞ്ഞെടുത്തില്ല"</string>
<string name="reset" msgid="2448168080964209908">"പുനഃസജ്ജമാക്കുക"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"ഭാഷയുടെ പേര് ടൈപ്പുചെയ്യുക"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"നിര്‍‌ദ്ദേശിച്ചത്"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"എല്ലാ ഭാഷകളും"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"തിരയുക"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"ഔദ്യോഗിക മോഡ് ഓഫാണ്"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"ആപ്സും, പശ്ചാത്തല സമന്വയവും ബന്ധപ്പെട്ട ഫീച്ചറുകളും ഉൾപ്പെടെ, ഔദ്യോഗിക പ്രൊഫൈലിനെ പ്രവർത്തിക്കാൻ അനുവദിക്കുക."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index ac0d24117ddd..c280445215b7 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>-д холбогдов. Сүлжээг удирдах бол товшино уу."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Байнгын VPN-д холбогдож байна..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Байнга VPN холбоотой"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Тогтмол асаалттай VPN салсан"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Байнгын VPN алдаа"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Тохируулахын тулд товшино уу"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Тохируулахын тулд товшино уу"</string>
<string name="upload_file" msgid="2897957172366730416">"Файл сонгох"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Сонгосон файл байхгүй"</string>
<string name="reset" msgid="2448168080964209908">"Бүгдийг цэвэрлэх"</string>
@@ -1645,6 +1646,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Улсын хэлийг бичнэ үү"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Санал болгосон"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Бүх хэл"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Бүх бүс нутаг"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Хайх"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Ажлын горимыг УНТРААСАН байна"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Ажлын профайлд апп, дэвсгэр синхрончлол болон бусад холбоотой тохиргоог ажиллахыг зөвшөөрнө үү."</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 2b6abe40f82b..899194410412 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> शी कनेक्ट केले. नेटवर्क व्यवस्थापित करण्यासाठी टॅप करा."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN कनेक्ट करणे नेहमी-चालू…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN कनेक्ट केलेले नेहमी-चालू"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"नेहमी-चालू असलेले VPN डिस्कनेक्ट केले"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"VPN त्रुटी नेहमी-चालू"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"कॉन्फिगर करण्यासाठी टॅप करा"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"सेट करण्यासाठी टॅप करा"</string>
<string name="upload_file" msgid="2897957172366730416">"फाईल निवडा"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"फाईल निवडली नाही"</string>
<string name="reset" msgid="2448168080964209908">"रीसेट करा"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"भाषा नाव टाइप करा"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"सूचित केलेले"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"सर्व भाषा"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"सर्व प्रदेश"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"शोध"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बंद आहे"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"कार्य प्रोफाइलला अॅप्स, पार्श्वभूमी संकालन आणि संबंधित वैशिष्ट्यांच्या समावेशासह कार्य करण्याची परवानगी द्या."</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index b2589e51288e..a947c1cdba29 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Bersambung kepada <xliff:g id="SESSION">%s</xliff:g>. Ketik untuk mengurus rangkaian."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sentiasa hidup sedang disambungkan..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sentiasa hidup telah disambungkan"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN sentiasa hidup diputuskan sambungannya"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Ralat VPN sentiasa hidup"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Ketik untuk membuat konfigurasi"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Ketik untuk menyediakan"</string>
<string name="upload_file" msgid="2897957172366730416">"Pilih fail"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Tiada fail dipilih"</string>
<string name="reset" msgid="2448168080964209908">"Tetapkan semula"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Taipkan nama bahasa"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Dicadangkan"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Semua bahasa"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Cari"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Mod kerja DIMATIKAN"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Benarkan profil kerja berfungsi, termasuk apl, penyegerakan latar belakang dan ciri yang berkaitan."</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 093914363992..ad95243283b2 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> သို့ ချိတ်ဆက်ထားသည်။ ကွန်ရက်ကို စီမံခန့်ခွဲရန် တို့ပါ။"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"အမြဲတမ်းဖွင့်ထား VPN ဆက်သွယ်နေစဉ်…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"အမြဲတမ်းဖွင့်ထား VPN ဆက်သွယ်မှုရှိ"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"အမြဲတမ်းဖွင့်ထားရသော VPN ပြတ်တောက်နေသည်"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"အမြဲတမ်းဖွင့်ထား VPN အမှား"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"ပြင်ဆင်သတ်မှတ်ရန် တို့ပါ"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"ပြင်ဆင်သတ်မှတ်ရန် တို့ပါ"</string>
<string name="upload_file" msgid="2897957172366730416">"ဖိုင်ရွေးချယ်ရန်"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"မည်သည့်ဖိုင်ကိုမှမရွေးပါ"</string>
<string name="reset" msgid="2448168080964209908">"ပြန်လည်သတ်မှတ်ရန်"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"ဘာသာစကားအမည် ထည့်ပါ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"အကြံပြုထားသော"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"ဘာသာစကားများအားလုံး"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"ဒေသအားလုံး"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"ရှာဖွေရန်"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"အလုပ်မုဒ် ပိတ်ထားသည်"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"အက်ပ်များ၊ နောက်ခံစင့်ခ်လုပ်ခြင်း၊ နှင့်သက်ဆိုင်သည့်အင်္ဂါရပ်များကို ဆောင်ရွက်ရန် အလုပ်ပရိုဖိုင်ကိုခွင့်ပြုပါ။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index ab837931745f..7812bb98ed1c 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Koblet til <xliff:g id="SESSION">%s</xliff:g>. Trykk for å administrere nettverket."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Alltid-på VPN kobler til ..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Alltid-på VPN er tilkoblet"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Alltid på-VPN er frakoblet"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Alltid-på VPN-feil"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Trykk for å konfigurere"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Trykk for å konfigurere"</string>
<string name="upload_file" msgid="2897957172366730416">"Velg fil"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil er valgt"</string>
<string name="reset" msgid="2448168080964209908">"Tilbakestill"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Skriv inn språknavn"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Foreslått"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Alle språk"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Alle områder"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Søk"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Jobbmodus er AV"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Slå på jobbprofilen, inkludert apper, synkronisering i bakgrunnen og relaterte funksjoner."</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 39acf6b006f8..145bdb06c4d4 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1249,8 +1249,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>सँग जोडिएको। नेटवर्क प्रबन्ध गर्न हान्नुहोस्।"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN जडान सधै जोड्दै…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"सधैँ खुल्ला हुने VPN जोडिएको"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"सधैँ-सक्रिय VPN लाई विच्छेद गरियो"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"सधैँ भरि VPN त्रुटिमा"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"कन्फिगर गर्न ट्याप गर्नुहोस्"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"सेट अप गर्न ट्याप गर्नुहोस्"</string>
<string name="upload_file" msgid="2897957172366730416">"फाइल छान्नुहोस्"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"कुनै फाइल छानिएको छैन"</string>
<string name="reset" msgid="2448168080964209908">"पुनःसेट गर्नु"</string>
@@ -1653,6 +1654,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"भाषाको नाम टाइप गर्नुहोस्"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"सुझाव दिइयो"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"सम्पूर्ण भाषाहरू"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"सबै क्षेत्रहरू"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"खोज"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बन्द छ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"अनुप्रयोग, पृष्ठभूमि सिंक र सम्बन्धित विशेषताहरू सहित, कार्य प्रोफाइललाई कार्य गर्न अनुमति दिनुहोस्।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 99cc80f8c613..d24a55d8ba82 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Verbonden met <xliff:g id="SESSION">%s</xliff:g>. Tik om het netwerk te beheren."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Always-on VPN-verbinding maken…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Always-on VPN-verbinding"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN-verbinding ontkoppeld"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Fout met Always-on VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Tik om te configureren"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tik om in te stellen"</string>
<string name="upload_file" msgid="2897957172366730416">"Bestand kiezen"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Geen bestand geselecteerd"</string>
<string name="reset" msgid="2448168080964209908">"Resetten"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Typ een taalnaam"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Voorgesteld"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Alle talen"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Alle regio\'s"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Zoeken"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Werkmodus is UIT"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Functioneren van werkprofiel toestaan, waaronder apps, synchronisatie op de achtergrond en gerelateerde functies."</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index 59564601c0bc..f87ccbff7391 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ। ਨੈੱਟਵਰਕ ਦੇ ਪ੍ਰਬੰਧਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ਹਮੇਸ਼ਾਂ-ਚਾਲੂ VPN ਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"ਹਮੇਸ਼ਾਂ-ਚਾਲੂ VPN ਕਨੈਕਟ ਕੀਤਾ"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ਹਮੇਸ਼ਾ-ਚਾਲੂ VPN ਡਿਸਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"ਹਮੇਸ਼ਾਂ-ਚਾਲੂ VPN ਅਸ਼ੁੱਧੀ"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"ਸੰਰੂਪਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"ਸਥਾਪਤ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="upload_file" msgid="2897957172366730416">"ਫਾਈਲ ਚੁਣੋ"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ਕੋਈ ਫਾਈਲ ਨਹੀਂ ਚੁਣੀ ਗਈ"</string>
<string name="reset" msgid="2448168080964209908">"ਰੀਸੈੱਟ ਕਰੋ"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"ਭਾਸ਼ਾ ਨਾਮ ਟਾਈਪ ਕਰੋ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"ਸੁਝਾਈਆਂ ਗਈਆਂ"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"ਸਾਰੇ ਖੇਤਰ"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"ਖੋਜ"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"ਕੰਮ ਮੋਡ ਬੰਦ ਹੈ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"ਐਪਾਂ, ਬੈਕਗ੍ਰਾਊਂਡ ਸਮਕਾਲੀਕਰਨ, ਅਤੇ ਸਬੰਧਿਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋਏ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਕੰਮ ਕਰਨ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 84ee0f8bb7bf..d20a7ab541eb 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1293,8 +1293,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Nawiązano połączenie: <xliff:g id="SESSION">%s</xliff:g>. Dotknij, aby zarządzać siecią."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Łączę ze stałą siecią VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Połączono ze stałą siecią VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Rozłączono ze stałą siecią VPN"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Błąd stałej sieci VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Kliknij, by skonfigurować"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Kliknij, by skonfigurować"</string>
<string name="upload_file" msgid="2897957172366730416">"Wybierz plik"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nie wybrano pliku"</string>
<string name="reset" msgid="2448168080964209908">"Resetuj"</string>
@@ -1719,6 +1720,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Wpisz nazwę języka"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugerowane"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Wszystkie języki"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Wszystkie kraje"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Szukaj"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Tryb pracy jest WYŁĄCZONY"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Włącz profil do pracy, w tym aplikacje, synchronizację w tle i inne funkcje."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 67398350bc40..fc89cde3023e 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerenciar a rede."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sempre ativa conectando..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre ativa conectada"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN sempre ativa desconectada"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro na VPN sempre ativa"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Toque para configurar"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Toque para configurar"</string>
<string name="upload_file" msgid="2897957172366730416">"Escolher arquivo"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nenhum arquivo escolhido"</string>
<string name="reset" msgid="2448168080964209908">"Redefinir"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Digitar nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Pesquisa"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Permitir que o perfil de trabalho funcione, incluindo apps, sincronização em segundo plano e recursos relacionados"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 5e244a9638cb..a24af8d18318 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Ligado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerir a rede."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"A ligar VPN sempre ativa..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre ativa ligada"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN sempre ativa desligada"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro da VPN sempre ativa"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Toque para configurar"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tocar para configurar"</string>
<string name="upload_file" msgid="2897957172366730416">"Escolher ficheiro"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Não foi selecionado nenhum ficheiro"</string>
<string name="reset" msgid="2448168080964209908">"Repor"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Intr. nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Todas as regiões"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Pesquisa"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Permitir o funcionamento do perfil de trabalho, incluindo as aplicações, a sincronização em segundo plano e as funcionalidades relacionadas."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 67398350bc40..fc89cde3023e 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Conectado a <xliff:g id="SESSION">%s</xliff:g>. Toque para gerenciar a rede."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN sempre ativa conectando..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN sempre ativa conectada"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"VPN sempre ativa desconectada"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Erro na VPN sempre ativa"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Toque para configurar"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Toque para configurar"</string>
<string name="upload_file" msgid="2897957172366730416">"Escolher arquivo"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nenhum arquivo escolhido"</string>
<string name="reset" msgid="2448168080964209908">"Redefinir"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Digitar nome do idioma"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugeridos"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Todos os idiomas"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Pesquisa"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Permitir que o perfil de trabalho funcione, incluindo apps, sincronização em segundo plano e recursos relacionados"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 042ea6268af3..37f320d43c48 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1268,8 +1268,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Conectat la <xliff:g id="SESSION">%s</xliff:g>. Apăsați pentru a gestiona rețeaua."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Se efectuează conectarea la rețeaua VPN activată permanent…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Conectat(ă) la rețeaua VPN activată permanent"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Rețeaua VPN activată permanent a fost deconectată"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Eroare de rețea VPN activată permanent"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Atingeți ca să configurați"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Atingeți pentru a configura"</string>
<string name="upload_file" msgid="2897957172366730416">"Alegeți un fișier"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nu au fost găsite fișiere"</string>
<string name="reset" msgid="2448168080964209908">"Resetați"</string>
@@ -1683,6 +1684,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Numele limbii"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugerate"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Toate limbile"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Toate regiunile"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Căutați"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Modul de serviciu e DEZACTIVAT"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Permiteți profilului de serviciu să funcționeze, inclusiv aplicațiile, sincronizarea în fundal și funcțiile asociate."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index bbb1488563bf..f61fffc637e5 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1293,8 +1293,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Подключено: \"<xliff:g id="SESSION">%s</xliff:g>\". Нажмите здесь, чтобы изменить настройки сети."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Подключение…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Подключено"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Отключено"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Ошибка"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Нажмите, чтобы настроить."</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Нажмите, чтобы настроить"</string>
<string name="upload_file" msgid="2897957172366730416">"Выбрать файл"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Не выбран файл"</string>
<string name="reset" msgid="2448168080964209908">"Сбросить"</string>
@@ -1719,6 +1720,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Введите язык"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Рекомендуемые"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Все языки"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Все регионы"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Поиск"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Рабочий режим отключен"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Включить рабочий профиль: приложения, фоновую синхронизацию и связанные функции."</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 5917d6dc6761..5d858e571569 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1245,8 +1245,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> වෙත සම්බන්ධිතයි. ජාලය කළමනාකරණය කිරීමට තට්ටු කරන්න."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"සැමවිටම VPN සම්බන්ධ වෙමින්…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"නිරතුරුවම VPN සම්බන්ධ කර ඇත"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"සැමවිට ක්‍රියාත්මක VPN විසන්ධි කරන ලදී"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"සැමවිට සක්‍රිය VPN දෝෂය"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"වින්‍යාස කිරීමට තට්ටු කරන්න"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"පිහිටුවීමට තට්ටු කරන්න"</string>
<string name="upload_file" msgid="2897957172366730416">"ගොනුව තෝරන්න"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ගොනුවක් තෝරාගෙන නැත"</string>
<string name="reset" msgid="2448168080964209908">"යළි පිහිටුවන්න"</string>
@@ -1649,6 +1650,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"භාෂා නම ටයිප් කරන්න"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"යෝජිත"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"සියලු භාෂා"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"සියලු ප්‍රදේශ"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"සෙවීම"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"වැඩ ප්‍රකාරය ක්‍රියාවිරහිතයි"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"යෙදුම්, පසුබිම සමමුහුර්ත කිරීම, සහ සම්බන්ධිත විශේෂාංග ඇතුළුව, ක්‍රියා කිරීමට කාර්යාල පැතිකඩට ඉඩ දෙන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 10a64fe0eb5e..4e3a4d46422f 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1293,8 +1293,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Pripojené k relácii <xliff:g id="SESSION">%s</xliff:g>. Po klepnutí môžete sieť spravovať."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Pripájanie k vždy zapnutej sieti VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Pripojenie k vždy zapnutej sieti VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Vždy zapnutá sieť VPN bola odpojená"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Chyba vždy zapnutej siete VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Klepnutím spustíte konfiguráciu"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Klepnutím prejdete do Nastavení"</string>
<string name="upload_file" msgid="2897957172366730416">"Zvoliť súbor"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nie je vybratý žiadny súbor"</string>
<string name="reset" msgid="2448168080964209908">"Obnoviť"</string>
@@ -1719,6 +1720,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Zadajte názov jazyka"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Navrhované"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Všetky jazyky"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Všetky regióny"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Vyhľadávanie"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Pracovný režim je VYPNUTÝ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Povoľte fungovanie pracovného profilu vrátane aplikácií, synchronizácie na pozadí a súvisiacich funkcií."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 28031e1b191b..f5aac609c7a0 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1293,8 +1293,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Povezan z mestom <xliff:g id="SESSION">%s</xliff:g>. Tapnite za upravljanje omrežja."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Povezovanje v stalno vklopljeno navidezno zasebno omrežje ..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Vzpostavljena povezava v stalno vklopljeno navidezno zasebno omrežje"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Povezava s stalno vklopljenim VPN-jem je prekinjena"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Napaka stalno vklopljenega navideznega zasebnega omrežja"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Dotanite se, če želite konfigurirati"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Dotaknite se, če želite nastaviti"</string>
<string name="upload_file" msgid="2897957172366730416">"Izberi datoteko"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nobena datoteka ni izbrana"</string>
<string name="reset" msgid="2448168080964209908">"Ponastavi"</string>
@@ -1719,6 +1720,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Vnesite ime jezika"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Predlagano"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Vsi jeziki"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Išči"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Delovni način IZKLOPLJEN"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Dovoljeno delovanje delovnega profila, vključno z aplikacijami, sinhronizacijo v ozadju in povezanimi funkcijami."</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index e83f39c6bebd..c554f9c8e582 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Lidhur me <xliff:g id="SESSION">%s</xliff:g>. Trokit për të menaxhuar rrjetin."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Po lidh VPN-në për aktivizim të përhershëm…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN e lidhur në mënyrë të përhershme"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Rrjeti VPN gjithmonë aktiv u shkëput"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Gabimi VPN-je për aktivizimin e përhershëm"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Trokit për të konfiguruar"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Trokit për ta konfiguruar"</string>
<string name="upload_file" msgid="2897957172366730416">"Zgjidh skedarin"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Nuk u zgjodh asnjë skedar"</string>
<string name="reset" msgid="2448168080964209908">"Rivendos"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Shkruaj emrin e gjuhës"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Sugjeruar"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Të gjitha gjuhët"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Të gjitha rajonet"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Kërko"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Modaliteti i punës është JOAKTIV"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Lejoje profilin e punës të funksionojë, duke përfshirë aplikacionet, sinkronizimin në sfond dhe funksionet e lidhura."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 5b3986fafba7..a7d13ae12620 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1268,8 +1268,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Повезано са сесијом <xliff:g id="SESSION">%s</xliff:g>. Додирните да бисте управљали мрежом."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Повезивање стално укљученог VPN-а..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Стално укључени VPN је повезан"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Веза са стално укљученим VPN-ом је прекинута"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Грешка стално укљученог VPN-а"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Додирните да бисте конфигурисали"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Додирните да бисте подесили"</string>
<string name="upload_file" msgid="2897957172366730416">"Одабери датотеку"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Није изабрана ниједна датотека"</string>
<string name="reset" msgid="2448168080964209908">"Поново постави"</string>
@@ -1683,6 +1684,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Унесите назив језика"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Предложени"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Сви језици"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Претражи"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Режим за Work је ИСКЉУЧЕН"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Дозвољава профилу за Work да функционише, укључујући апликације, синхронизацију у позадини и сродне функције."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index b9d724772624..c0ee103238b6 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Ansluten till <xliff:g id="SESSION">%s</xliff:g>. Knacka lätt för att hantera nätverket."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Ansluter till Always-on VPN ..."</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Ansluten till Always-on VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Always-on VPN har kopplats från"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Fel på Always-on VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Tryck om du vill konfigurera"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Tryck för att konfigurera"</string>
<string name="upload_file" msgid="2897957172366730416">"Välj fil"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ingen fil har valts"</string>
<string name="reset" msgid="2448168080964209908">"Återställ"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Ange språket"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Förslag"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Alla språk"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Alla regioner"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Söka"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Arbetsläget är inaktiverat"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Tillåt att jobbprofilen är aktiv, inklusive appar, bakgrundssynkronisering och andra tillhörande funktioner."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 959c04dd29cc..f8e794b67834 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1241,8 +1241,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Imeunganishwa kwa <xliff:g id="SESSION">%s</xliff:g>. Gonga ili kudhibiti mtandao"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Kila mara VPN iliyowashwa inaunganishwa…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Kila mara VPN iliyowashwa imeunganishwa"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Iwe imeondoa VPN kila wakati"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Kila mara kuna hitilafu ya VPN iliyowashwa"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Gonga ili uweke mipangilio"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Gonga ili uweke mipangilio"</string>
<string name="upload_file" msgid="2897957172366730416">"Chagua faili"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Hakuna faili iliyochaguliwa"</string>
<string name="reset" msgid="2448168080964209908">"Weka upya"</string>
@@ -1645,6 +1646,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Weka jina la lugha"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Inayopendekezwa"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Lugha zote"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Tafuta"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Hali ya kazi IMEZIMWA"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Ruhusu wasifu wa kazini utumike, ikiwa ni pamoja na programu, usawazishaji wa chini chini na vipengele vinavyohusiana."</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 68c0da9d9679..ebeb986530bf 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> உடன் இணைக்கப்பட்டது. நெட்வொர்க்கை நிர்வகிக்க, தட்டவும்."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"எப்போதும் இயங்கும் VPN உடன் இணைக்கிறது…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"எப்போதும் இயங்கும் VPN இணைக்கப்பட்டது"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"எப்போதும் இயங்கும் VPN துண்டிக்கப்பட்டது"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"எப்போதும் இயங்கும் VPN பிழை"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"உள்ளமைக்க, தட்டவும்"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"அமைக்க, தட்டவும்"</string>
<string name="upload_file" msgid="2897957172366730416">"கோப்பைத் தேர்வுசெய்"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"எந்தக் கோப்பும் தேர்வுசெய்யப்படவில்லை"</string>
<string name="reset" msgid="2448168080964209908">"மீட்டமை"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"மொழி பெயரை உள்ளிடுக"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"பரிந்துரைகள்"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"எல்லா மொழிகளும்"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"எல்லா மண்டலங்களும்"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"தேடு"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"பணிப் பயன்முறை முடக்கப்பட்டது"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"செயல்பட, பணி சுயவிவரத்தை அனுமதி. இதில் பயன்பாடுகள், பின்னணி ஒத்திசைவு மற்றும் தொடர்புடைய அம்சங்கள் அடங்கும்."</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 4e2a5810df5a..3535c268007a 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g>కు కనెక్ట్ చేయబడింది. నెట్‌వర్క్‌ను నిర్వహించడానికి నొక్కండి."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"ఎల్లప్పుడూ-ఆన్‌లో ఉండే VPN కనెక్ట్ చేయబడుతోంది…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"ఎల్లప్పుడూ-ఆన్‌లో ఉండే VPN కనెక్ట్ చేయబడింది"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ఎల్లప్పుడూ ఆన్‌లో ఉండే VPN డిస్‌కనెక్ట్ చేయబడింది"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"ఎల్లప్పుడూ-ఆన్‌లో ఉండే VPN లోపం"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"కాన్ఫిగర్ చేయడానికి నొక్కండి"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"సెటప్ చేయడానికి నొక్కండి"</string>
<string name="upload_file" msgid="2897957172366730416">"ఫైల్‌ను ఎంచుకోండి"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ఫైల్ ఎంచుకోబడలేదు"</string>
<string name="reset" msgid="2448168080964209908">"రీసెట్ చేయి"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"భాష పేరును టైప్ చేయండి"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"సూచించినవి"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"అన్ని భాషలు"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"అన్ని ప్రాంతాలు"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"శోధించు"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"కార్యాలయ మోడ్ ఆఫ్ చేయబడింది"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"అనువర్తనాలు, నేపథ్య సమకాలీకరణ మరియు సంబంధిత లక్షణాలతో సహా కార్యాలయ ప్రొఫైల్‌ను పని చేయడానికి అనుమతించండి."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 332e70b70939..13c066026f0a 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"เชื่อมต่อกับ <xliff:g id="SESSION">%s</xliff:g> แตะเพื่อจัดการเครือข่าย"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"กำลังเชื่อมต่อ VPN แบบเปิดตลอดเวลา…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"เชื่อมต่อ VPN แบบเปิดตลอดเวลาแล้ว"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"ยกเลิกการเชื่อมต่อ VPN แบบเปิดตลอดเวลาแล้ว"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"ข้อผิดพลาดของ VPN แบบเปิดตลอดเวลา"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"แตะเพื่อกำหนดค่า"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"แตะเพื่อตั้งค่า"</string>
<string name="upload_file" msgid="2897957172366730416">"เลือกไฟล์"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"ไม่ได้เลือกไฟล์ไว้"</string>
<string name="reset" msgid="2448168080964209908">"รีเซ็ต"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"พิมพ์ชื่อภาษา"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"แนะนำ"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"ทุกภาษา"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"ภูมิภาคทั้งหมด"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"ค้นหา"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"โหมดทำงานปิดอยู่"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"อนุญาตให้โปรไฟล์งานทำงานได้ ซึ่งรวมถึงแอป การซิงค์ในพื้นหลัง และคุณลักษณะอื่นที่เกี่ยวข้อง"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 065f7b4cf967..375bbe7593e8 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Nakakonekta sa <xliff:g id="SESSION">%s</xliff:g>. Tapikin upang pamahalaan ang network."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Kumukonekta ang Always-on VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Nakakonekta ang Always-on VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Hindi nakakonekta ang palaging naka-on na VPN"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Error sa Always-on VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"I-tap upang i-configure"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"I-tap upang i-set up"</string>
<string name="upload_file" msgid="2897957172366730416">"Pumili ng file"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Walang napiling file"</string>
<string name="reset" msgid="2448168080964209908">"I-reset"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"I-type ang wika"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Iminumungkahi"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Lahat ng wika"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Lahat ng rehiyon"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Maghanap"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"NAKA-OFF ang work mode"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Payagang gumana ang profile sa trabaho, kasama na ang mga app, pag-sync sa background at mga may kaugnayang feature."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 5cf25fdbd7f6..6e622fe98762 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> oturumuna bağlı. Ağı yönetmek için hafifçe vurun."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Her zaman açık VPN\'ye bağlanılıyor…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Her zaman açık VPN\'ye bağlanıldı"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Her zaman açık VPN bağlantısı kesildi"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Her zaman açık VPN hatası"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Yapılandırmak için dokunun"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Ayarlamak için dokunun"</string>
<string name="upload_file" msgid="2897957172366730416">"Dosya seç"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Seçili dosya yok"</string>
<string name="reset" msgid="2448168080964209908">"Sıfırla"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Dil adını yazın"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Önerilen"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Tüm diller"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Ara"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"İş modu KAPALI"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Uygulamalar, arka planda senkronizasyon ve ilgili özellikler dahil olmak üzere iş profilinin çalışmasına izin ver."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 1f5856d25e82..dd129380d55e 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1293,8 +1293,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Під’єднано до <xliff:g id="SESSION">%s</xliff:g>. Торкніться, щоб керувати мережею."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Під’єднання до постійної мережі VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Під’єднано до постійної мережі VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Постійну мережу VPN від’єднано"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Помилка постійної мережі VPN"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Торкніться, щоб налаштувати"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Торкніться, щоб налаштувати"</string>
<string name="upload_file" msgid="2897957172366730416">"Виберіть файл"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Не вибрано файл"</string>
<string name="reset" msgid="2448168080964209908">"Віднов."</string>
@@ -1719,6 +1720,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Введіть назву мови"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Пропоновані"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Усі мови"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Усі регіони"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Пошук"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Робочий профіль ВИМКНЕНО"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Увімкнути робочий профіль, зокрема додатки, фонову синхронізацію та пов’язані функції."</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 996a50ba65ad..1620aadae4ba 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> سے منسلک ہے۔ نیٹ ورک کا نظم کرنے کیلئے تھپتھپائیں۔"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"‏ہمیشہ آن VPN مربوط ہو رہا ہے…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"‏ہمیشہ آن VPN مربوط ہوگیا"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"‏ہمیشہ آن VPN غیر منسلک ہو گیا"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"‏ہمیشہ آن VPN کی خرابی"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"کنفیگر کرنے کیلئے تھپتھپائیں"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"سیٹ اپ کرنے کیلئے تھپتھپائیں"</string>
<string name="upload_file" msgid="2897957172366730416">"فائل منتخب کریں"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"کوئی فائل منتخب نہیں کی گئی"</string>
<string name="reset" msgid="2448168080964209908">"دوبارہ ترتیب دیں"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"زبان کا نام ٹائپ کریں"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"تجویز کردہ"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"سبھی زبانیں"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"تلاش"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"کام موڈ آف ہے"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"دفتری پروفائل کو کام کرنے دیں، بشمول ایپس، پس منظر کی مطابقت پذیری اور متعلقہ خصوصیات۔"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index a12bdadfefb8..27adee9d1ef2 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"<xliff:g id="SESSION">%s</xliff:g> ulandi. Tarmoq sozlamalarini o‘zgartirish uchun bu yerni bosing."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Ulanmoqda…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Ulandi"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Doimiy VPN o‘chirildi"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Xato"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Sozlash uchun bosing"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Sozlash uchun bosing"</string>
<string name="upload_file" msgid="2897957172366730416">"Faylni tanlash"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Hech qanday fayl tanlanmadi"</string>
<string name="reset" msgid="2448168080964209908">"Asliga qaytarish"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"Til nomini kiriting"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Taklif etiladi"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Barcha tillar"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"Qidiruv"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Ish rejimi O‘CHIQ"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Ishchi profilini yoqish: ilovalar, fonda sinxronlash va bog‘liq funksiyalar."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 6984027673a4..91712377b227 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Đã kết nối với <xliff:g id="SESSION">%s</xliff:g>. Chạm để quản lý mạng."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"Đang kết nối VPN luôn bật…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"Đã kết nối VPN luôn bật"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Đã ngắt kết nối VPN luôn bật"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Lỗi VPN luôn bật"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Nhấn để định cấu hình"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Nhấn để thiết lập"</string>
<string name="upload_file" msgid="2897957172366730416">"Chọn tệp"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Không có tệp nào được chọn"</string>
<string name="reset" msgid="2448168080964209908">"Đặt lại"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Nhập tên ngôn ngữ"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Ðược đề xuất"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Tất cả ngôn ngữ"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Tất cả khu vực"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Tìm kiếm"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Chế độ làm việc đang TẮT"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Cho phép hồ sơ công việc hoạt động, bao gồm ứng dụng, đồng bộ hóa trong nền và các tính năng liên quan."</string>
diff --git a/core/res/res/values-watch/donottranslate.xml b/core/res/res/values-watch/donottranslate.xml
new file mode 100644
index 000000000000..d247ff6f5694
--- /dev/null
+++ b/core/res/res/values-watch/donottranslate.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <!-- DO NOT TRANSLATE Spans within this text are applied to style composing regions
+ within an EditText widget. The text content is ignored and not used.
+ Note: This is @color/material_deep_teal_200, cannot use @color references here. -->
+ <string name="candidates_style" translatable="false"><font color="#80cbc4">candidates</font></string>
+ </resources>
diff --git a/core/res/res/values-watch/styles_material.xml b/core/res/res/values-watch/styles_material.xml
index a5e48451f538..8a080d9c155d 100644
--- a/core/res/res/values-watch/styles_material.xml
+++ b/core/res/res/values-watch/styles_material.xml
@@ -101,9 +101,4 @@ please see styles_device_defaults.xml.
<item name="gravity">@integer/config_dialogTextGravity</item>
<item name="ellipsize">end</item>
</style>
-
- <!-- DO NOTE TRANSLATE Spans within this text are applied to style composing regions
- within an EditText widget. The text content is ignored and not used.
- Note: This is @color/material_deep_teal_200, cannot use @color references here. -->
- <string name="candidates_style"><font color="#80cbc4">candidates</font></string>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index d3428b3ccd5e..e4dfcb63d4d1 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"已连接到<xliff:g id="SESSION">%s</xliff:g>。点按即可管理网络。"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"正在连接到始终开启的 VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"已连接到始终开启的 VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"始终开启的 VPN 已断开连接"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"始终开启的 VPN 出现错误"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"点按即可进行配置"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"点按即可进行设置"</string>
<string name="upload_file" msgid="2897957172366730416">"选择文件"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"未选定任何文件"</string>
<string name="reset" msgid="2448168080964209908">"重置"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"输入语言名称"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"建议语言"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"所有语言"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"搜索"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"工作模式已关闭"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"启用工作资料,包括应用、后台同步和相关功能。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 734a5063ef68..480b33f6f316 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"已連線至 <xliff:g id="SESSION">%s</xliff:g>,輕按一下即可管理網絡。"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"正在連線至永久連線的 VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"已連線至永久連線的 VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"永久連線的 VPN 已中斷"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"永久連線的 VPN 發生錯誤"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"輕觸即可設定"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"輕按即可設定"</string>
<string name="upload_file" msgid="2897957172366730416">"選擇檔案"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"未選擇檔案"</string>
<string name="reset" msgid="2448168080964209908">"重設"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"輸入語言名稱"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"建議"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"所有語言"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"所有國家/地區"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"搜尋"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"工作模式已關閉"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"允許使用應用程式、背景同步及相關功能的工作設定檔。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 73ed62c7436c..6c6f636b9f66 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"已連線至 <xliff:g id="SESSION">%s</xliff:g>,輕觸一下即可管理網路。"</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"正在連線至永久連線的 VPN…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"已連線至永久連線的 VPN"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"永久連線的 VPN 已中斷連線"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"永久連線的 VPN 發生錯誤"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"輕觸即可進行設定"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"輕觸即可進行設定"</string>
<string name="upload_file" msgid="2897957172366730416">"選擇檔案"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"未選擇任何檔案"</string>
<string name="reset" msgid="2448168080964209908">"重設"</string>
@@ -1647,6 +1648,8 @@
<string name="search_language_hint" msgid="7042102592055108574">"請輸入語言名稱"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"建議語言"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"所有語言"</string>
+ <!-- no translation found for region_picker_section_all (8966316787153001779) -->
+ <skip />
<string name="locale_search_menu" msgid="2560710726687249178">"搜尋"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Work 模式已關閉"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"啟用 Work 設定檔,包括應用程式、背景同步處理和相關功能。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 12818fc6d46f..86af6252ee11 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1243,8 +1243,9 @@
<string name="vpn_text_long" msgid="4907843483284977618">"Ixhume ku-<xliff:g id="SESSION">%s</xliff:g>. Thepha ukuphatha inethiwekhi."</string>
<string name="vpn_lockdown_connecting" msgid="6443438964440960745">"I-VPN ehlala ikhanya iyaxhuma…"</string>
<string name="vpn_lockdown_connected" msgid="8202679674819213931">"I-VPN ehlala ikhanya ixhunyiwe"</string>
+ <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"Njalo kuvuliwe i-VPN kunqamukile"</string>
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Iphutha le-VPN ehlala ikhanya"</string>
- <string name="vpn_lockdown_config" msgid="4655589351146766608">"Thinta ukuze umise"</string>
+ <string name="vpn_lockdown_config" msgid="5099330695245008680">"Thepha ukuze usethe"</string>
<string name="upload_file" msgid="2897957172366730416">"Khetha ifayela"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"Ayikho ifayela ekhethiwe"</string>
<string name="reset" msgid="2448168080964209908">"Setha kabusha"</string>
@@ -1647,6 +1648,7 @@
<string name="search_language_hint" msgid="7042102592055108574">"Thayipha igama lolimi"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Okuphakanyisiwe"</string>
<string name="language_picker_section_all" msgid="3097279199511617537">"Zonke izilimi"</string>
+ <string name="region_picker_section_all" msgid="8966316787153001779">"Zonke izifunda"</string>
<string name="locale_search_menu" msgid="2560710726687249178">"Sesha"</string>
<string name="work_mode_off_title" msgid="8954725060677558855">"Imodi yomsebenzi IVALIWE"</string>
<string name="work_mode_off_message" msgid="3286169091278094476">"Vumela iphrofayela yomsebenzi ukuze isebenze, efaka izinhlelo zokusebenza, ukuvumelanisa kwangemuva, nezici ezisondelene."</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5035d0d358f4..43f8dc769432 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -275,6 +275,11 @@
<string-array translatable="false" name="config_networkNotifySwitches">
</string-array>
+ <!-- Whether the device should automatically switch away from Wi-Fi networks that lose
+ Internet access. Actual device behaviour is controlled by
+ Settings.Global.NETWORK_AVOID_BAD_WIFI. This is the default value of that setting. -->
+ <integer translatable="false" name="config_networkAvoidBadWifi">1</integer>
+
<!-- List of regexpressions describing the interface (if any) that represent tetherable
USB interfaces. If the device doesn't want to support tethering over USB this should
be empty. An example would be "usb.*" -->
@@ -2603,4 +2608,7 @@
<item>110,119:112</item>
-->
<string-array translatable="false" name="config_convert_to_emergency_number_map" />
+
+ <!-- An array of packages for which notifications cannot be blocked. -->
+ <string-array translatable="false" name="config_nonBlockableNotificationPackages" />
</resources>
diff --git a/core/res/res/values/donottranslate.xml b/core/res/res/values/donottranslate.xml
index a139529482da..3a1679c19fc8 100644
--- a/core/res/res/values/donottranslate.xml
+++ b/core/res/res/values/donottranslate.xml
@@ -26,4 +26,7 @@
<string name="icu_abbrev_wday_month_day_no_year">eeeMMMMd</string>
<!-- @hide DO NOT TRANSLATE. date formatting pattern for system ui.-->
<string name="system_ui_date_pattern">@string/icu_abbrev_wday_month_day_no_year</string>
+ <!-- @hide DO NOT TRANSLATE Spans within this text are applied to style composing regions
+ within an EditText widget. The text content is ignored and not used. -->
+ <string name="candidates_style" translatable="false"><u>candidates</u></string>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6649aeffeb1d..bbcd6d57f30a 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3128,8 +3128,6 @@
<string name="fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
<string name="fast_scroll_numeric_alphabet">\u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
- <string name="candidates_style"><u>candidates</u></string>
-
<!-- External media notification strings -->
<skip />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index da223d91dd89..fa90e2444fd8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1751,6 +1751,7 @@
<java-symbol type="integer" name="config_networkTransitionTimeout" />
<java-symbol type="integer" name="config_networkNotifySwitchType" />
<java-symbol type="array" name="config_networkNotifySwitches" />
+ <java-symbol type="integer" name="config_networkAvoidBadWifi" />
<java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
<java-symbol type="integer" name="config_notificationsBatteryLedOff" />
<java-symbol type="integer" name="config_notificationsBatteryLedOn" />
@@ -2709,4 +2710,6 @@
<java-symbol type="drawable" name="ic_restart" />
<java-symbol type="array" name="config_convert_to_emergency_number_map" />
+
+ <java-symbol type="array" name="config_nonBlockableNotificationPackages" />
</resources>
diff --git a/core/tests/coretests/src/android/os/OsTests.java b/core/tests/coretests/src/android/os/OsTests.java
index 582bf1ae204a..985fa4f3cfc8 100644
--- a/core/tests/coretests/src/android/os/OsTests.java
+++ b/core/tests/coretests/src/android/os/OsTests.java
@@ -32,6 +32,7 @@ public class OsTests {
suite.addTestSuite(IdleHandlerTest.class);
suite.addTestSuite(MessageQueueTest.class);
suite.addTestSuite(MessengerTest.class);
+ suite.addTestSuite(PatternMatcherTest.class);
suite.addTestSuite(SystemPropertiesTest.class);
return suite;
diff --git a/core/tests/coretests/src/android/os/PatternMatcherTest.java b/core/tests/coretests/src/android/os/PatternMatcherTest.java
new file mode 100644
index 000000000000..9645ccc11b76
--- /dev/null
+++ b/core/tests/coretests/src/android/os/PatternMatcherTest.java
@@ -0,0 +1,234 @@
+package android.os;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+@SmallTest
+public class PatternMatcherTest extends TestCase{
+
+ @Test
+ public void testAdvancedPatternMatchesAnyToken() {
+ PatternMatcher matcher = new PatternMatcher(".", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertMatches("a", matcher);
+ assertMatches("b", matcher);
+ assertNotMatches("", matcher);
+ }
+
+ @Test
+ public void testAdvancedPatternMatchesSetToken() {
+ PatternMatcher matcher = new PatternMatcher("[a]", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertMatches("a", matcher);
+ assertNotMatches("b", matcher);
+
+ matcher = new PatternMatcher("[.*+{}\\]\\\\[]", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertMatches(".", matcher);
+ assertMatches("*", matcher);
+ assertMatches("+", matcher);
+ assertMatches("{", matcher);
+ assertMatches("}", matcher);
+ assertMatches("]", matcher);
+ assertMatches("\\", matcher);
+ assertMatches("[", matcher);
+ }
+
+ @Test
+ public void testAdvancedPatternMatchesSetCharacterClassToken() {
+ PatternMatcher matcher = new PatternMatcher("[a-z]", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertMatches("a", matcher);
+ assertMatches("b", matcher);
+ assertNotMatches("A", matcher);
+ assertNotMatches("1", matcher);
+
+ matcher = new PatternMatcher("[a-z][0-9]", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertMatches("a1", matcher);
+ assertNotMatches("1a", matcher);
+ assertNotMatches("aa", matcher);
+
+ matcher = new PatternMatcher("[z-a]", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertNotMatches("a", matcher);
+ assertNotMatches("z", matcher);
+ assertNotMatches("A", matcher);
+
+ matcher = new PatternMatcher("[^0-9]", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertMatches("a", matcher);
+ assertMatches("z", matcher);
+ assertMatches("A", matcher);
+ assertNotMatches("9", matcher);
+ assertNotMatches("5", matcher);
+ assertNotMatches("0", matcher);
+
+ assertPoorlyFormattedPattern("[]a]");
+ matcher = new PatternMatcher("[\\[a]", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertMatches("a", matcher);
+ assertMatches("[", matcher);
+ }
+
+ @Test
+ public void testAdvancedPatternMatchesEscapedCharacters() {
+ PatternMatcher matcher = new PatternMatcher("\\.", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertMatches(".", matcher);
+ assertNotMatches("a", matcher);
+ assertNotMatches("1", matcher);
+
+ matcher = new PatternMatcher("a\\+", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertMatches("a+", matcher);
+ assertNotMatches("a", matcher);
+ assertNotMatches("aaaaa", matcher);
+
+ matcher = new PatternMatcher("[\\a-\\z]", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertMatches("a", matcher);
+ assertMatches("z", matcher);
+ assertNotMatches("A", matcher);
+ }
+
+ @Test
+ public void testAdvancedPatternMatchesLiteralTokens() {
+ PatternMatcher matcher = new PatternMatcher("a", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertNotMatches("", matcher);
+ assertMatches("a", matcher);
+ assertNotMatches("z", matcher);
+
+ matcher = new PatternMatcher("az", PatternMatcher.PATTERN_ADVANCED_GLOB);
+ assertNotMatches("", matcher);
+ assertMatches("az", matcher);
+ assertNotMatches("za", matcher);
+ }
+
+ @Test
+ public void testAdvancedPatternMatchesSetZeroOrMore() {
+ PatternMatcher matcher = new PatternMatcher("[a-z]*", PatternMatcher.PATTERN_ADVANCED_GLOB);
+
+ assertMatches("", matcher);
+ assertMatches("a", matcher);
+ assertMatches("abcdefg", matcher);
+ assertNotMatches("abc1", matcher);
+ assertNotMatches("1abc", matcher);
+ }
+
+ @Test
+ public void testAdvancedPatternMatchesSetOneOrMore() {
+ PatternMatcher matcher = new PatternMatcher("[a-z]+", PatternMatcher.PATTERN_ADVANCED_GLOB);
+
+ assertNotMatches("", matcher);
+ assertMatches("a", matcher);
+ assertMatches("abcdefg", matcher);
+ assertNotMatches("abc1", matcher);
+ assertNotMatches("1abc", matcher);
+ }
+
+
+ @Test
+ public void testAdvancedPatternMatchesSingleRange() {
+ PatternMatcher matcher = new PatternMatcher("[a-z]{1}",
+ PatternMatcher.PATTERN_ADVANCED_GLOB);
+
+ assertNotMatches("", matcher);
+ assertMatches("a", matcher);
+ assertMatches("z", matcher);
+ assertNotMatches("1", matcher);
+ assertNotMatches("aa", matcher);
+ }
+
+ @Test
+ public void testAdvancedPatternMatchesFullRange() {
+ PatternMatcher matcher = new PatternMatcher("[a-z]{1,5}",
+ PatternMatcher.PATTERN_ADVANCED_GLOB);
+
+ assertNotMatches("", matcher);
+ assertMatches("a", matcher);
+ assertMatches("zazaz", matcher);
+ assertNotMatches("azazaz", matcher);
+ assertNotMatches("11111", matcher);
+ }
+
+ @Test
+ public void testAdvancedPatternMatchesPartialRange() {
+ PatternMatcher matcher = new PatternMatcher("[a-z]{3,}",
+ PatternMatcher.PATTERN_ADVANCED_GLOB);
+
+ assertNotMatches("", matcher);
+ assertMatches("aza", matcher);
+ assertMatches("zazaz", matcher);
+ assertMatches("azazazazazaz", matcher);
+ assertNotMatches("aa", matcher);
+ }
+
+ @Test
+ public void testAdvancedPatternMatchesComplexPatterns() {
+ PatternMatcher matcher = new PatternMatcher(
+ "/[0-9]{4}/[0-9]{2}/[0-9]{2}/[a-zA-Z0-9_]+\\.html",
+ PatternMatcher.PATTERN_ADVANCED_GLOB);
+
+ assertNotMatches("", matcher);
+ assertMatches("/2016/09/07/got_this_working.html", matcher);
+ assertMatches("/2016/09/07/got_this_working2.html", matcher);
+ assertNotMatches("/2016/09/07/got_this_working2dothtml", matcher);
+ assertNotMatches("/2016/9/7/got_this_working.html", matcher);
+
+ matcher = new PatternMatcher(
+ "/b*a*bar.*",
+ PatternMatcher.PATTERN_ADVANCED_GLOB);
+
+ assertMatches("/babar", matcher);
+ assertMatches("/babarfff", matcher);
+ assertMatches("/bbaabarfff", matcher);
+ assertMatches("/babar?blah", matcher);
+ assertMatches("/baaaabar?blah", matcher);
+ assertNotMatches("?bar", matcher);
+ assertNotMatches("/bar", matcher);
+ assertNotMatches("/baz", matcher);
+ assertNotMatches("/ba/bar", matcher);
+ assertNotMatches("/barf", matcher);
+ assertNotMatches("/", matcher);
+ assertNotMatches("?blah", matcher);
+ }
+
+ @Test
+ public void testAdvancedPatternPoorFormatThrowsIllegalArgumentException() {
+ assertPoorlyFormattedPattern("[a-z");
+ assertPoorlyFormattedPattern("a{,4}");
+ assertPoorlyFormattedPattern("a{0,a}");
+ assertPoorlyFormattedPattern("a{\\1, 2}");
+ assertPoorlyFormattedPattern("[]");
+ assertPoorlyFormattedPattern("a{}");
+ assertPoorlyFormattedPattern("{3,4}");
+ assertPoorlyFormattedPattern("a+{3,4}");
+ assertPoorlyFormattedPattern("*.");
+ assertPoorlyFormattedPattern(".+*");
+ assertPoorlyFormattedPattern("a{3,4");
+ assertPoorlyFormattedPattern("[a");
+ assertPoorlyFormattedPattern("abc\\");
+ assertPoorlyFormattedPattern("+.");
+
+ StringBuilder charSet = new StringBuilder("[");
+ for (int i = 0; i < 1024; i++) {
+ charSet.append('a' + (i % 26));
+ }
+ charSet.append("]");
+ assertPoorlyFormattedPattern(charSet.toString());
+ }
+
+ private void assertMatches(String string, PatternMatcher matcher) {
+ assertTrue("'" + string + "' should match '" + matcher.toString() + "'",
+ matcher.match(string));
+ }
+
+ private void assertNotMatches(String string, PatternMatcher matcher) {
+ assertTrue("'" + string + "' should not match '" + matcher.toString() + "'",
+ !matcher.match(string));
+ }
+
+ private void assertPoorlyFormattedPattern(String format) {
+ try {
+ new PatternMatcher(format, PatternMatcher.PATTERN_ADVANCED_GLOB);
+ } catch (IllegalArgumentException e) {
+ return;// expected
+ }
+
+ fail("'" + format + "' was erroneously created");
+ }
+}
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index f5d23e8b4032..2721c85fb62a 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -59,7 +59,7 @@ Platform Versions</a>.</p>
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on August 1, 2016.
+<p style="clear:both"><em>Data collected during a 7-day period ending on September 5, 2016.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -81,7 +81,7 @@ Screens</a>.</p>
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on August 1, 2016.
+<p style="clear:both"><em>Data collected during a 7-day period ending on September 5, 2016.
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -101,7 +101,7 @@ support for any lower version (for example, support for version 2.0 also implies
<img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chl=GL%202.0%7CGL%203.0%7CGL%203.1&chf=bg%2Cs%2C00000000&chd=t%3A46.0%2C42.6%2C11.4&chco=c4df9b%2C6fad0c&cht=p&chs=400x250">
+src="//chart.googleapis.com/chart?chl=GL%202.0%7CGL%203.0%7CGL%203.1&chf=bg%2Cs%2C00000000&chd=t%3A44.9%2C42.3%2C12.8&chco=c4df9b%2C6fad0c&cht=p&chs=400x250">
<p>To declare which version of OpenGL ES your application requires, you should use the {@code
android:glEsVersion} attribute of the <a
@@ -119,21 +119,21 @@ uses.</p>
</tr>
<tr>
<td>2.0</td>
-<td>46.0%</td>
+<td>44.9%</td>
</tr>
<tr>
<td>3.0</td>
-<td>42.6%</td>
+<td>42.3%</td>
</tr>
<tr>
<td>3.1</td>
-<td>11.4%</td>
+<td>12.8%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on August 1, 2016</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on September 5, 2016</em></p>
@@ -147,19 +147,19 @@ var SCREEN_DATA =
"Large": {
"hdpi": "0.5",
"ldpi": "0.2",
- "mdpi": "4.3",
+ "mdpi": "4.1",
"tvdpi": "2.1",
"xhdpi": "0.5"
},
"Normal": {
- "hdpi": "40.0",
- "mdpi": "3.8",
- "tvdpi": "0.1",
- "xhdpi": "27.3",
+ "hdpi": "39.5",
+ "mdpi": "3.5",
+ "tvdpi": "0.2",
+ "xhdpi": "28.4",
"xxhdpi": "15.5"
},
"Small": {
- "ldpi": "1.8"
+ "ldpi": "1.6"
},
"Xlarge": {
"hdpi": "0.3",
@@ -167,8 +167,8 @@ var SCREEN_DATA =
"xhdpi": "0.7"
}
},
- "densitychart": "//chart.googleapis.com/chart?chd=t%3A2.0%2C11.0%2C2.2%2C40.8%2C28.5%2C15.5&chf=bg%2Cs%2C00000000&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&cht=p&chs=400x250&chco=c4df9b%2C6fad0c",
- "layoutchart": "//chart.googleapis.com/chart?chd=t%3A3.9%2C7.6%2C86.7%2C1.8&chf=bg%2Cs%2C00000000&chl=Xlarge%7CLarge%7CNormal%7CSmall&cht=p&chs=400x250&chco=c4df9b%2C6fad0c"
+ "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A1.8%2C10.5%2C2.3%2C40.4%2C29.6%2C15.5&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250",
+ "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A3.9%2C7.4%2C87.2%2C1.6&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250"
}
];
@@ -176,7 +176,7 @@ var SCREEN_DATA =
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?chd=t%3A0.1%2C1.7%2C1.6%2C16.7%2C29.2%2C35.5%2C15.2&chf=bg%2Cs%2C00000000&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat%7CLollipop%7CMarshmallow&cht=p&chs=500x250&chco=c4df9b%2C6fad0c",
+ "chart": "//chart.googleapis.com/chart?chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat%7CLollipop%7CMarshmallow&chd=t%3A0.1%2C1.5%2C1.4%2C15.6%2C27.7%2C35.0%2C18.7&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=500x250",
"data": [
{
"api": 8,
@@ -186,47 +186,47 @@ var VERSION_DATA =
{
"api": 10,
"name": "Gingerbread",
- "perc": "1.7"
+ "perc": "1.5"
},
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "1.6"
+ "perc": "1.4"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "6.0"
+ "perc": "5.6"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "8.3"
+ "perc": "7.7"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "2.4"
+ "perc": "2.3"
},
{
"api": 19,
"name": "KitKat",
- "perc": "29.2"
+ "perc": "27.7"
},
{
"api": 21,
"name": "Lollipop",
- "perc": "14.1"
+ "perc": "13.1"
},
{
"api": 22,
"name": "Lollipop",
- "perc": "21.4"
+ "perc": "21.9"
},
{
"api": 23,
"name": "Marshmallow",
- "perc": "15.2"
+ "perc": "18.7"
}
]
}
diff --git a/docs/html/guide/topics/location/strategies.jd b/docs/html/guide/topics/location/strategies.jd
index 2dfed2ce6e8e..548ed9c99f34 100755
--- a/docs/html/guide/topics/location/strategies.jd
+++ b/docs/html/guide/topics/location/strategies.jd
@@ -133,36 +133,69 @@ notifications and the third is the minimum change in distance between notificati
both to zero requests location notifications as frequently as possible. The last parameter is your
{@link android.location.LocationListener}, which receives callbacks for location updates.</p>
-<p>To request location updates from the GPS provider,
-substitute <code>GPS_PROVIDER</code> for <code>NETWORK_PROVIDER</code>. You can also request
-location updates from both the GPS and the Network Location Provider by calling {@link
-android.location.LocationManager#requestLocationUpdates requestLocationUpdates()} twice&mdash;once
-for <code>NETWORK_PROVIDER</code> and once for <code>GPS_PROVIDER</code>.</p>
+<p>To request location updates from the GPS provider, use {@link
+android.location.LocationManager#GPS_PROVIDER} instead of {@link
+android.location.LocationManager#NETWORK_PROVIDER}. You can also request
+location updates from both the GPS and the Network Location Provider by calling
+{@link android.location.LocationManager#requestLocationUpdates
+requestLocationUpdates()} twice&mdash;once for {@link
+android.location.LocationManager#NETWORK_PROVIDER} and once for {@link
+android.location.LocationManager#GPS_PROVIDER}.</p>
<h3 id="Permission">Requesting User Permissions</h3>
-<p>In order to receive location updates from <code>NETWORK_PROVIDER</code> or
-<code>GPS_PROVIDER</code>, you must request user permission by declaring either the {@code
-ACCESS_COARSE_LOCATION} or {@code ACCESS_FINE_LOCATION} permission, respectively, in your Android
-manifest file. For example:</p>
+<p>
+ In order to receive location updates from {@link
+ android.location.LocationManager#NETWORK_PROVIDER} or {@link
+ android.location.LocationManager#GPS_PROVIDER}, you must request the user's
+ permission by declaring either the {@code ACCESS_COARSE_LOCATION} or {@code
+ ACCESS_FINE_LOCATION} permission, respectively, in your Android manifest file.
+ Without these permissions, your application will fail at runtime when
+ requesting location updates.
+</p>
+
+<p>
+ If you are using both {@link
+ android.location.LocationManager#NETWORK_PROVIDER} and {@link
+ android.location.LocationManager#GPS_PROVIDER}, then you need to request only
+ the {@code ACCESS_FINE_LOCATION} permission, because it includes permission
+ for both providers. Permission for {@code ACCESS_COARSE_LOCATION} allows
+ access only to {@link android.location.LocationManager#NETWORK_PROVIDER}.
+</p>
+
+<p id="location-feature-caution" class="caution">
+ <strong>Caution:</strong> If your app targets Android 5.0 (API level 21) or
+ higher, you <em>must</em> declare that your app uses the
+ <code>android.hardware.location.network</code> or
+ <code>android.hardware.location.gps</code> hardware feature in the manifest
+ file, depending on whether your app receives location updates from {@link
+ android.location.LocationManager#NETWORK_PROVIDER} or from {@link
+ android.location.LocationManager#GPS_PROVIDER}. If your app receives location
+ information from either of these location provider sources, you need to
+ declare that the app uses these hardware features in your app manifest.
+ On devices running verions prior to Android 5.0 (API 21), requesting the
+ {@code ACCESS_FINE_LOCATION} or {@code ACCESS_COARSE_LOCATION} permission
+ includes an implied request for location hardware features. However,
+ requesting those permissions <em>does not</em> automatically request location
+ hardware features on Android 5.0 (API level 21) and higher.
+</p>
+<p>
+ The following code sample demonstrates how to declare the permission and
+ hardware feature in the manifest file of an app that reads data from the
+ device's GPS:
+</p>
<pre>
&lt;manifest ... &gt;
&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
...
+ &lt;!-- Needed only if your app targets Android 5.0 (API level 21) or higher. --&gt;
+ &lt;uses-feature android:name="android.hardware.location.gps" /&gt;
+ ...
&lt;/manifest&gt;
</pre>
-<p>Without these permissions, your application will fail at runtime when requesting
-location updates.</p>
-
-<p class="note"><strong>Note:</strong> If you are using both <code>NETWORK_PROVIDER</code> and
-<code>GPS_PROVIDER</code>, then you need to request only the {@code ACCESS_FINE_LOCATION}
-permission, because it includes permission for both providers. (Permission for {@code
-ACCESS_COARSE_LOCATION} includes permission only for <code>NETWORK_PROVIDER</code>.)</p>
-
-
<h2 id="BestPerformance">Defining a Model for the Best Performance</h2>
<p>Location-based applications are now commonplace, but due to the less than optimal
@@ -404,9 +437,10 @@ don't have a device, you can still test your location-based features by mocking
the Android emulator. There are three different ways to send your application mock location
data: using Android Studio, DDMS, or the "geo" command in the emulator console.</p>
-<p class="note"><strong>Note:</strong> Providing mock location data is injected as GPS location
-data, so you must request location updates from <code>GPS_PROVIDER</code> in order for mock location
-data to work.</p>
+<p class="note"><strong>Note:</strong> Providing mock location data is injected
+as GPS location data, so you must request location updates from {@link
+android.location.LocationManager#GPS_PROVIDER} in order for mock location data
+to work.</p>
<h3 id="MockAVD">Using Android Studio</h3>
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index 9b32244b736f..26ae59f9d336 100755
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -1666,6 +1666,15 @@ densities: '160'
<pre>&lt;uses-feature android:name="android.hardware.camera" android:required="false" /&gt;</pre>
+<p class="caution">
+ <strong>Caution:</strong> If your app targets Android 5.0 (API level 21) or
+ higher and uses the <code>ACCESS_COARSE_LOCATION</code> or
+ <code>ACCESS_FINE_LOCATION</code> permission in order to receive location
+ updates from the network or a GPS, respectively, you must also explicitly
+ declare that your app uses the <code>android.hardware.location.network</code>
+ or <code>android.hardware.location.gps</code> hardware features.
+</p>
+
<p class="table-caption" id="permissions-features">
<strong>Table 2. </strong>Device permissions that imply device hardware use.
</p>
@@ -1717,14 +1726,29 @@ densities: '160'
</tr>
<tr>
<td><code>ACCESS_COARSE_LOCATION</code></td>
- <td><code>android.hardware.location.network</code> <em>and</em>
-<br><code>android.hardware.location</code></td>
+ <td>
+ <p>
+ <code>android.hardware.location</code>
+ </p>
+ <p>
+ <code>android.hardware.location.network</code>
+ (Only when target API level is 20 orlower.)
+ </p>
+ </td>
<!-- <td></td> -->
</tr>
<tr>
<td><code>ACCESS_FINE_LOCATION</code></td>
- <td><code>android.hardware.location.gps</code> <em>and</em>
-<br><code>android.hardware.location</code></td>
+ <td>
+ <p>
+ <code>android.hardware.location</code>
+ </p>
+ <p>
+ <code>android.hardware.location.gps</code>
+ (Only when target API level is 20 orlower.)
+ </p>
+ </td>
+
<!-- <td></td> -->
</tr>
diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd
index 4995a13dda91..383b6c1f32ca 100644
--- a/docs/html/guide/topics/media/camera.jd
+++ b/docs/html/guide/topics/media/camera.jd
@@ -154,10 +154,16 @@ application must request the audio capture permission.
&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
</pre>
</li>
- <li><strong>Location Permission</strong> - If your application tags images with GPS location
-information, you must request location permission:
+ <li>
+ <p><strong>Location Permission</strong> - If your application tags images
+ with GPS location information, you must request the {@code ACCESS_FINE_LOCATION}
+ permission. Note that, if your app targets Android 5.0 (API level 21) or
+ higher, you also need to declare that your app uses the device's GPS:</p>
<pre>
&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
+...
+&lt;!-- Needed only if your app targets Android 5.0 (API level 21) or higher. --&gt;
+&lt;uses-feature android:name="android.hardware.location.gps" /&gt;
</pre>
<p>For more information about getting user location, see
<a href="{@docRoot}guide/topics/location/strategies.html">Location Strategies</a>.</p>
diff --git a/docs/html/images/training/ctl-config.png b/docs/html/images/training/ctl-config.png
index 82f63c85274d..3a4f7385183c 100644
--- a/docs/html/images/training/ctl-config.png
+++ b/docs/html/images/training/ctl-config.png
Binary files differ
diff --git a/docs/html/images/training/tv/playback/onboarding-fragment-diagram.png b/docs/html/images/training/tv/playback/onboarding-fragment-diagram.png
new file mode 100644
index 000000000000..5839a50d572c
--- /dev/null
+++ b/docs/html/images/training/tv/playback/onboarding-fragment-diagram.png
Binary files differ
diff --git a/docs/html/images/training/tv/playback/onboarding-fragment.png b/docs/html/images/training/tv/playback/onboarding-fragment.png
new file mode 100644
index 000000000000..5b7da55c8422
--- /dev/null
+++ b/docs/html/images/training/tv/playback/onboarding-fragment.png
Binary files differ
diff --git a/docs/html/images/training/tv/playback/onboarding-fragment_2x.png b/docs/html/images/training/tv/playback/onboarding-fragment_2x.png
new file mode 100644
index 000000000000..0034be44fbc8
--- /dev/null
+++ b/docs/html/images/training/tv/playback/onboarding-fragment_2x.png
Binary files differ
diff --git a/docs/html/topic/libraries/data-binding/index.jd b/docs/html/topic/libraries/data-binding/index.jd
index ddcc9f2e7ea8..0faa1db1bf60 100644
--- a/docs/html/topic/libraries/data-binding/index.jd
+++ b/docs/html/topic/libraries/data-binding/index.jd
@@ -162,7 +162,9 @@ page.tags="databinding", "layouts"
<p>
To use data binding, Android Plugin for Gradle <strong>1.5.0-alpha1</strong>
- or higher is required.
+ or higher is required. See how to <a
+href="/studio/releases/gradle-plugin.html#updating-plugin">update the Android
+Plugin for Gradle</a>.
</p>
<h2 id="build_environment">
diff --git a/docs/html/topic/libraries/support-library/features.jd b/docs/html/topic/libraries/support-library/features.jd
index 614392e00d44..b5f189a0886e 100755
--- a/docs/html/topic/libraries/support-library/features.jd
+++ b/docs/html/topic/libraries/support-library/features.jd
@@ -108,7 +108,7 @@ page.title=Support Library Features
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:support-compat:24.2.0
+com.android.support:support-compat:24.2.1
</pre>
<h3 id="v4-core-utils">v4 core-utils library</h3>
@@ -124,7 +124,7 @@ com.android.support:support-compat:24.2.0
</p>
<pre>
-com.android.support:support-core-utils:24.2.0
+com.android.support:support-core-utils:24.2.1
</pre>
<h3 id="v4-core-ui">v4 core-ui library</h3>
@@ -141,7 +141,7 @@ com.android.support:support-core-utils:24.2.0
</p>
<pre>
-com.android.support:support-core-ui:24.2.0
+com.android.support:support-core-ui:24.2.1
</pre>
<h3 id="v4-media-compat">v4 media-compat library</h3>
@@ -158,7 +158,7 @@ com.android.support:support-core-ui:24.2.0
</p>
<pre>
-com.android.support:support-media-compat:24.2.0
+com.android.support:support-media-compat:24.2.1
</pre>
<h3 id="v4-fragment">v4 fragment library</h3>
@@ -178,7 +178,7 @@ com.android.support:support-media-compat:24.2.0
</p>
<pre>
-com.android.support:support-fragment:24.2.0
+com.android.support:support-fragment:24.2.1
</pre>
<h2 id="multidex">Multidex Support Library</h2>
@@ -245,7 +245,7 @@ com.android.support:multidex:1.0.0
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:appcompat-v7:24.2.0
+com.android.support:appcompat-v7:24.2.1
</pre>
@@ -260,7 +260,7 @@ implementations, and are used extensively in layouts for TV apps.</p>
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:cardview-v7:24.2.0
+com.android.support:cardview-v7:24.2.1
</pre>
@@ -276,7 +276,7 @@ For detailed information about the v7 gridlayout library APIs, see the
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:gridlayout-v7:24.2.0
+com.android.support:gridlayout-v7:24.2.1
</pre>
@@ -299,7 +299,7 @@ reference.</p>
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:mediarouter-v7:24.2.0
+com.android.support:mediarouter-v7:24.2.1
</pre>
<p class="caution">The v7 mediarouter library APIs introduced in Support Library
@@ -319,7 +319,7 @@ title card.</p>
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:palette-v7:24.2.0
+com.android.support:palette-v7:24.2.1
</pre>
@@ -335,7 +335,7 @@ limited window of data items.</p>
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:recyclerview-v7:24.2.0
+com.android.support:recyclerview-v7:24.2.1
</pre>
@@ -358,7 +358,7 @@ such as {@link android.support.v7.preference.CheckBoxPreference} and
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:preference-v7:24.2.0
+com.android.support:preference-v7:24.2.1
</pre>
<h2 id="v8">v8 Support Library</h2>
@@ -409,7 +409,7 @@ defaultConfig {
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:support-v13:24.2.0
+com.android.support:support-v13:24.2.1
</pre>
@@ -435,7 +435,7 @@ for preference interfaces such as
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:preference-v14:24.2.0
+com.android.support:preference-v14:24.2.1
</pre>
@@ -458,7 +458,7 @@ interface and classes, such as
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:preference-leanback-v17:24.2.0
+com.android.support:preference-leanback-v17:24.2.1
</pre>
@@ -494,7 +494,7 @@ com.android.support:preference-leanback-v17:24.2.0
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:leanback-v17:24.2.0
+com.android.support:leanback-v17:24.2.1
</pre>
@@ -509,7 +509,7 @@ package provides APIs to support adding annotation metadata to your apps. </p>
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:support-annotations:24.2.0
+com.android.support:support-annotations:24.2.1
</pre>
@@ -527,7 +527,7 @@ snackbars, and <a href="{@docRoot}design/building-blocks/tabs.html">tabs</a>. <
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:design:24.2.0
+com.android.support:design:24.2.1
</pre>
@@ -548,7 +548,7 @@ Callback</a>. </p>
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:customtabs:24.2.0
+com.android.support:customtabs:24.2.1
</pre>
@@ -572,7 +572,7 @@ PercentRelativeLayout</a>. </p>
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:percent:24.2.0
+com.android.support:percent:24.2.1
</pre>
@@ -595,5 +595,5 @@ RecommendationExtender</a>. </p>
<p>The Gradle build script dependency identifier for this library is as follows:</p>
<pre>
-com.android.support:recommendation:24.2.0
+com.android.support:recommendation:24.2.1
</pre>
diff --git a/docs/html/topic/libraries/support-library/revisions.jd b/docs/html/topic/libraries/support-library/revisions.jd
index 8947baa9a975..9a24d1540e9b 100644
--- a/docs/html/topic/libraries/support-library/revisions.jd
+++ b/docs/html/topic/libraries/support-library/revisions.jd
@@ -6,9 +6,71 @@ page.metaDescription=This page provides details about the Support Library packag
<p>This page provides details about the Support Library package releases.</p>
<div class="toggle-content opened">
- <p id="rev24-2-0">
+ <p id="rev24-2-1">
<a href="#" onclick="return toggleContent(this)"><img src=
"{@docRoot}assets/images/styles/disclosure_up.png" class=
+ "toggle-content-img" alt="">Android Support Library, revision 24.2.1</a>
+ <em>(September 2016)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <p>Fixed issues:</p>
+
+<ul>
+ <li>{@link android.support.design.widget.FloatingActionButton} can no longer
+ be anchored to indirect children of {@link
+ android.support.design.widget.CoordinatorLayout}. (AOSP issue <a href=
+ "https://code.google.com/p/android/issues/detail?id=220250">220250</a>)
+ </li>
+
+ <li>Image inside {@link
+ android.support.design.widget.CollapsingToolbarLayout} doesn’t scale properly
+ with <code>fitsSystemWindows=true</code>. (AOSP issue <a href=
+ "https://code.google.com/p/android/issues/detail?id=220389">220389</a>)
+ </li>
+
+ <li>{@link android.support.design.widget.CoordinatorLayout} throws {@link
+ java.lang.IndexOutOfBoundsException} when {@link
+ android.support.design.widget.Snackbar} is shown and dismissed. (AOSP issue
+ <a href="https://code.google.com/p/android/issues/detail?id=220762"
+ >220762</a>)
+ </li>
+
+ <li>{@link android.support.design.widget.TextInputLayout} fails to resolve
+ error text color. (AOSP issue <a href=
+ "https://code.google.com/p/android/issues/detail?id=220305">220305</a>)
+ </li>
+
+ <li>{@link android.support.v7.util.SortedList.BatchedCallback#onMoved
+ BatchedCallback.onMoved()} calls {@link
+ android.support.v7.util.SortedList.BatchedCallback#onInserted
+ BatchedCallback.onInserted()}. (AOSP issue <a href=
+ "https://code.google.com/p/android/issues/detail?id=220309">220309</a>)
+ </li>
+
+ <li>{@link android.support.design.widget.TextInputLayout} overrides right
+ compound drawable. (AOSP issue <a href=
+ "https://code.google.com/p/android/issues/detail?id=220728">220728</a>)
+ </li>
+</ul>
+
+<p>
+ A complete list of public bug fixes is available on the <a href=
+ "https://code.google.com/p/android/issues/list?can=1&q=label%3ATarget-Support-24.2.1">
+ AOSP Issue Tracker</a>.
+</p>
+
+
+ </div>
+</div>
+
+<!-- end of collapsible section: 24.2.1 -->
+
+<div class="toggle-content closed">
+ <p id="rev24-2-0">
+ <a href="#" onclick="return toggleContent(this)"><img src=
+ "{@docRoot}assets/images/styles/disclosure_down.png" class=
"toggle-content-img" alt="">Android Support Library, revision 24.2.0</a>
<em>(August 2016)</em>
</p>
diff --git a/docs/html/training/_book.yaml b/docs/html/training/_book.yaml
index 891574fbc6ca..e9635be74ec3 100644
--- a/docs/html/training/_book.yaml
+++ b/docs/html/training/_book.yaml
@@ -695,6 +695,8 @@ toc:
value: 再生中カードを表示する
- title: Adding a Guided Step
path: /training/tv/playback/guided-step.html
+ - title: Introducing First-time Users to Your App
+ path: /training/tv/playback/onboarding.html
- title: Enabling Background Playback
path: /training/tv/playback/options.html
- title: Adding Picture-in-picture
@@ -898,6 +900,11 @@ toc:
value: 順応性のある UI フローの実装
- name: zh-cn-lang
value: 实施自适应用户界面流程
+ - title: Build a Responsive UI with ConstraintLayout
+ path: /training/constraint-layout/index.html
+ path_attributes:
+ - name: description
+ value: How to build a layout using ConstraintLayout and the Android Studio Layout Editor.
- title: Adding the App Bar
path: /training/appbar/index.html
path_attributes:
@@ -1149,6 +1156,8 @@ toc:
value: 维护兼容性
- name: zh-tw-lang
value: 維持相容性
+ - title: Selecting Colors with the Palette API
+ path: /training/material/palette-colors.html
- title: Best Practices for User Input
path: /training/best-user-input.html
diff --git a/docs/html/training/constraint-layout/images/alignment-constraint-offset_2x.png b/docs/html/training/constraint-layout/images/alignment-constraint-offset_2x.png
new file mode 100644
index 000000000000..1e4867e6513a
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/alignment-constraint-offset_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/alignment-constraint_2x.png b/docs/html/training/constraint-layout/images/alignment-constraint_2x.png
new file mode 100644
index 000000000000..afe7d4aed282
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/alignment-constraint_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/baseline-constraint_2x.png b/docs/html/training/constraint-layout/images/baseline-constraint_2x.png
new file mode 100644
index 000000000000..dfc35226fdb5
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/baseline-constraint_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/constraint-fail-fixed_2x.png b/docs/html/training/constraint-layout/images/constraint-fail-fixed_2x.png
new file mode 100644
index 000000000000..be9d54f4fbf5
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/constraint-fail-fixed_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/constraint-fail_2x.png b/docs/html/training/constraint-layout/images/constraint-fail_2x.png
new file mode 100644
index 000000000000..3f28ef7906ab
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/constraint-fail_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/layout-editor-convert-to-constraint_2x.png b/docs/html/training/constraint-layout/images/layout-editor-convert-to-constraint_2x.png
new file mode 100644
index 000000000000..ace31a6105d9
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/layout-editor-convert-to-constraint_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/layout-editor-margin-callout_2-2_2x.png b/docs/html/training/constraint-layout/images/layout-editor-margin-callout_2-2_2x.png
new file mode 100644
index 000000000000..07680227fbb7
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/layout-editor-margin-callout_2-2_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/layout-editor-properties-callouts_2-2_2x.png b/docs/html/training/constraint-layout/images/layout-editor-properties-callouts_2-2_2x.png
new file mode 100644
index 000000000000..b4ffb2cd946a
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/layout-editor-properties-callouts_2-2_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/layout-editor_2-2_2x.png b/docs/html/training/constraint-layout/images/layout-editor_2-2_2x.png
new file mode 100644
index 000000000000..72a4e401a05c
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/layout-editor_2-2_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/parent-constraint_2x.png b/docs/html/training/constraint-layout/images/parent-constraint_2x.png
new file mode 100644
index 000000000000..0414f1d5b34b
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/parent-constraint_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/position-constraint_2x.png b/docs/html/training/constraint-layout/images/position-constraint_2x.png
new file mode 100644
index 000000000000..9f93e72dcd4d
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/position-constraint_2x.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/thumbnail-add-layout-guideline_2-2.png b/docs/html/training/constraint-layout/images/thumbnail-add-layout-guideline_2-2.png
new file mode 100644
index 000000000000..f863e5f99bd1
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/thumbnail-add-layout-guideline_2-2.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/thumbnail-adjust-constraint-bias.png b/docs/html/training/constraint-layout/images/thumbnail-adjust-constraint-bias.png
new file mode 100644
index 000000000000..d61e9b2354f1
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/thumbnail-adjust-constraint-bias.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/thumbnail-studio-constraint-first.png b/docs/html/training/constraint-layout/images/thumbnail-studio-constraint-first.png
new file mode 100644
index 000000000000..97471025b007
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/thumbnail-studio-constraint-first.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/images/thumbnail-studio-constraint-second.png b/docs/html/training/constraint-layout/images/thumbnail-studio-constraint-second.png
new file mode 100644
index 000000000000..940b84955278
--- /dev/null
+++ b/docs/html/training/constraint-layout/images/thumbnail-studio-constraint-second.png
Binary files differ
diff --git a/docs/html/training/constraint-layout/index.html b/docs/html/training/constraint-layout/index.html
new file mode 100644
index 000000000000..62eaf15f62a7
--- /dev/null
+++ b/docs/html/training/constraint-layout/index.html
@@ -0,0 +1,498 @@
+<html devsite>
+<head>
+ <title>Build a Responsive UI with ConstraintLayout</title>
+ <meta name="book_path" value="/training/_book.yaml" />
+ <meta name="top_category" value="develop" />
+ <meta name="subcategory" value="training" />
+</head>
+<body>
+
+<div id="tb-wrapper">
+<div id="tb">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#constraints-overview">Constraints overview</a></li>
+ <li><a href="#add-constraintlayout-to-your-project">Add ConstraintLayout to your project</a></li>
+ <li><a href="#add-a-constraint">Add a constraint</a></li>
+ <li><a href="#use-autoconnect-and-infer-constraints">Use Autoconnect and Infer Constraints</a></li>
+ <li><a href="#adjust-the-view-size">Adjust the view size</a></li>
+ <li><a href="#adjust-the-constraint-bias">Adjust the constraint bias</a></li>
+ <li><a href="#adjust-the-view-margins">Adjust the view margins</a></li>
+ </ol>
+</div>
+</div>
+
+
+<p><code>ConstraintLayout</code> allows you to create large and complex layouts with a flat view
+hierarchy (no nested view groups). It's similar to <code>RelativeLayout</code> in that all views are
+layed out according to relationships between sibling views and the parent layout, but it's more
+flexible than <code>RelativeLayout</code> and easier to use with Android Studio's Layout Editor.
+</p>
+
+<p>Everything you can do with <code>ConstraintLayout</code> is available directly from the Layout Editor's visual
+tools, because the layout API and the Layout Editor were specially built for each other. So you can
+build your layout with <code>ConstraintLayout</code> entirely by drag-and-dropping instead of editing the XML.
+</p>
+
+<img src="/training/constraint-layout/images/layout-editor_2-2_2x.png" alt=""
+ width="640"/>
+<p class="img-caption"><b>Figure 1.</b> A <code>ConstraintLayout</code> in the Layout Editor</p>
+
+
+<p>
+<code>ConstraintLayout</code> is available in an API library that's compatible with Android
+2.3 (API level 9) and higher, and the new layout editor is available in Android
+Studio 2.2 and higher.
+</p>
+
+<p>
+This page provides a guide to building a layout with <code>ConstraintLayout</code> in Android
+Studio. If you'd like more information about the Layout Editor itself, see the
+Android Studio guide to <a href="/studio/write/layout-editor.html">Build a UI with
+Layout Editor</a>.
+</p>
+
+
+<h2 id="constraints-overview">Constraints overview</h2>
+<p>
+To define a view's position in <code>ConstraintLayout</code>, you must add two
+or more <em>constraints</em> for the view. Each constraint represents a connection or
+alignment to another view, the parent layout, or an invisible guideline. Each
+constraint defines the view's position along either the
+vertical or horizontal axis; so each view must have a minimum of one constraint for each
+axis, but often more are necessary.
+</p>
+
+<p>
+When you drop a view into the Layout Editor, it stays where you leave it even if
+it has no constraints. However, this is only to make editing easier; if a view has
+no constraints when you run your layout on a device, it is drawn at
+position [0,0] (the top-left corner).</p>
+
+<p>In figure 2, the layout looks good in the
+editor, but there's no vertical constraint on <code>TextView B</code>. When this
+layout draws on a device, <code>TextView B</code> horizontally aligns with the left and
+right edges of the <code>ImageView</code>, but appears at the top of the screen because
+it has no vertical constraint.
+</p>
+
+<div class="cols">
+<div class="col-1of2">
+<img src="/training/constraint-layout/images/constraint-fail_2x.png" width="100%" alt="" />
+<p class="img-caption"><strong>Figure 2.</strong> <code>TextView B</code> is missing a
+vertical constraint</p>
+</div>
+<div class="col-1of2">
+<img src="/training/constraint-layout/images/constraint-fail-fixed_2x.png" width="100%" alt="" />
+<p class="img-caption"><strong>Figure 3.</strong> <code>TextView B</code> is now vertically
+constrained to the <code>ImageView</code></p>
+</div>
+</div>
+
+<p>
+Although a missing constraint won't cause a compilation error, the Layout Editor
+indicates missing constraints as an error in the toolbar. To view the errors and
+other warnings, click <strong>Show Warnings and Errors</strong>
+<img src="/studio/images/buttons/layout-editor-errors.png" class="inline-icon" alt="" />.
+To help you avoid missing constraints, the Layout Editor can automatically add
+constraints for you with the <a
+href="#use-autoconnect-and-infer-constraints">Autoconnect and infer
+constraints</a> features.
+</p>
+
+
+<h2 id="add-constraintlayout-to-your-project">Add ConstraintLayout to your project</h2>
+<p>
+To use <code>ConstraintLayout</code> in your project, proceed as follows:
+</p>
+
+<ol>
+<li>Ensure you have the latest Constraint Layout library:
+<ol>
+ <li>Click <strong>Tools > Android > SDK Manager</strong>.
+ <li>Click the <strong>SDK Tools</strong> tab.
+ <li>Expand <strong>Support Repository</strong> and then check
+<b>ConstraintLayout for Android</b> and <b>Solver for ConstraintLayout</b>.
+Check <b>Show Package Details</b> and take note of the version you're downloading
+(you'll need this below).</p>
+ <li>Click <strong>OK</strong>.
+<li>Add the ConstraintLayout library as a dependency in your module-level
+ <code>build.gradle</code> file:
+<pre>
+dependencies {
+ compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha8'
+}
+</pre>
+ <p>The library version you download may be higher, so be sure the value you specify
+ here matches the version from step 3.</p>
+</li>
+<li>In the toolbar or sync notification, click <strong>Sync Project with Gradle
+Files</strong>.</li>
+</ol>
+</li>
+</ol>
+
+<p>Now you're ready to build your layout with <code>ConstraintLayout</code>.</p>
+
+<h3 id="convert">Convert a layout</h3>
+
+<div class="figure" style="width:415px">
+<img src="/training/constraint-layout/images/layout-editor-convert-to-constraint_2x.png"
+ width="415" alt="" />
+<p class="img-caption">
+ <b>Figure 4.</b> The menu to convert a layout to <code>ConstraintLayout</code></p>
+</div>
+
+<p>To convert an existing layout to a constraint layout, follow these steps:</p>
+<ol>
+<li>Open your layout in Android Studio and click the <strong>Design</strong> tab
+at the bottom of the editor window.
+<li>In the <strong>Component Tree</strong> window, right-click the layout and
+click <strong>Convert <em>layout</em> to ConstraintLayout</strong>.</li>
+</ol>
+
+<h3 id="createNew">Create a new layout</h3>
+
+<p>To start a new constraint layout file, follow these steps:</p>
+<ol>
+<li>Click anywhere in the <strong>Project</strong> window and then select
+<strong>File > New > XML > Layout XML</strong>.
+<li>Enter a name for the layout file and enter
+"android.support.constraint.ConstraintLayout" for the <b>Root Tag</b>.
+<li>Click <strong>Finish</strong>.</li>
+</ol>
+
+
+<h2 id="add-a-constraint">Add a constraint</h2>
+
+<p>Start by dragging a view from the <b>Palette</b> window into the editor.
+When you add a view in a <code>ConstraintLayout</code>, it displays a bounding box with square
+resizing handles on each corner and circular constraint handles on each side.
+</p>
+
+
+<div class="figure" style="width:460px">
+<div class="video-wrapper">
+<video controls poster="/training/constraint-layout/images/thumbnail-studio-constraint-first.png"
+ onclick="this.play()" width="460">
+ <source src="https://storage.googleapis.com/androiddevelopers/videos/studio/studio-constraint-first.mp4" type="video/mp4">
+ <img src="/training/constraint-layout/images/thumbnail-studio-constraint-first" alt="" />
+</video>
+</div>
+<p class="img-caption">
+<strong>Video 1. </strong>The left side of a view is constrained to the left side of the parent
+</p>
+</div>
+
+<p>
+Click the view to select it. Then click-and-hold one of the
+constraint handles and drag the line to an available anchor point (the edge of
+another view, the edge of the layout, or a guideline). When you release, the
+constraint is made, with <a href="#adjust-the-view-margins">a default margin</a>
+separating the two views.
+</p>
+
+<p>When creating constraints, remember the following rules:</p>
+
+<ul>
+<li>Every view must have at least two constraints: one horizontal and one
+vertical.
+<li>You can create constraints only between a constraint handle and an anchor
+point that share the same plane. So a vertical plane (the left and right sides)
+of a view can be constrained only to another vertical plane; and baselines can
+constrain only to other baselines.
+<li>Each constraint handle can be used for just one constraint, but you can
+create multiple constraints (from different views) to the same anchor
+point.</li>
+</ul>
+
+
+
+<div class="figure" style="width:460px">
+<div class="video-wrapper">
+<video controls poster="/training/constraint-layout/images/thumbnail-studio-constraint-second.png"
+ onclick="this.play()" width="460">
+ <source src="https://storage.googleapis.com/androiddevelopers/videos/studio/studio-constraint-second.mp4" type="video/mp4">
+ <img src="/training/constraint-layout/images/thumbnail-studio-constraint-second.png" alt="" />
+</video>
+</div>
+<p class="img-caption">
+<strong>Video 2. </strong>Adding a constraint that opposes an existing one
+</p>
+</div>
+
+
+
+<p>
+To remove a constraint, select the view and then click the constraint handle.
+</p>
+
+<p>If you add opposing constraints on a view, the constraint lines become squiggly
+like a spring to indicate the opposing forces, as shown in video 2. The effect
+is most visible when the view size is set to "fixed" or "wrap content," in which
+case the view is centered between the constraints. If you instead
+want the view to stretch its size to meet the constraints, <a
+href="#adjust-the-view-size">switch the size to "any size"</a>; or if you want
+to keep the current size but move the view so that it is not centered, <a
+href="#adjust-the-constraint-bias">adjust the constraint bias</a>.
+</p>
+
+
+
+<p>
+There are many ways to constrain a view, but the following constraint types
+provide the basic building blocks.
+</p>
+
+
+
+
+<h3>Parent constraint</h3>
+<div class="cols">
+<div class="col-2of3">
+ <p>
+ Connect the side of a view to the corresponding edge of the layout.
+ <p>
+ In figure 5, the left side of a view is connected to the left edge of the
+ parent layout.
+ <p>
+</div>
+<div class="col-1of3">
+ <img src="/training/constraint-layout/images/parent-constraint_2x.png" width="100%" alt="">
+ <p class="img-caption"><strong>Figure 5. </strong>A horizontal constraint to the parent</p>
+</div>
+</div>
+
+
+<h3>Position constraint</h3>
+<div class="cols">
+<div class="col-2of3">
+<p>Define the order of appearance for two views, either vertically or horizontally.</p>
+<p>In figure 6, a <code>Button</code> is constrained below an <code>ImageView</code> with a 24dp
+margin.</p>
+</div>
+<div class="col-1of3">
+ <img src="/training/constraint-layout/images/position-constraint_2x.png" width="100%" alt="">
+ <p class="img-caption"><strong>Figure 6.</strong> A vertical position constraint</p>
+</div>
+</div>
+
+
+
+<h3>Alignment constraint</h3>
+<div class="cols">
+<div class="col-1of3">
+<p>Align the edge of a view to the same edge of another view.<p>
+<p>In figure 7, the left side of a <code>Button</code> is aligned to the left side of an
+<code>ImageView</code>.</p>
+<p>You can offset the alignment by dragging the view
+inward from the constraint. For example, figure 8 shows the same
+<code>Button</code> with a 24dp offset alignment.
+The offset is defined by the constrained view's margin.</p>
+</div>
+<div class="col-1of3">
+ <img src="/training/constraint-layout/images/alignment-constraint_2x.png" width="100%" alt="">
+ <p class="img-caption"><strong>Figure 7.</strong> A horizontal alignment constraint</p>
+</div>
+<div class="col-1of3">
+ <img src="/training/constraint-layout/images/alignment-constraint-offset_2x.png" width="100%"
+ alt="">
+ <p class="img-caption"><strong>Figure 8.</strong> An offset horizontal alignment constraint</p>
+</div>
+</div>
+
+
+<h3>Baseline alignment constraint</h3>
+<div class="cols">
+<div class="col-2of3">
+<p>Align the text baseline of a view to the text baseline of another view.</p>
+<p>In figure 9, the first line of a <code>TextView</code> is aligned with the text in a
+<code>Button</code>.</p>
+<p>To create a baseline constraint, hover your mouse over the baseline handle for
+two seconds until the handle blinks white. Then click and drag the line to
+another baseline.</p>
+</div>
+<div class="col-1of3">
+ <img src="/training/constraint-layout/images/baseline-constraint_2x.png" width="100%" alt="">
+ <p class="img-caption"><strong>Figure 9.</strong> A baseline alignment constraint</p>
+</div>
+</div>
+
+
+
+
+
+<h3 id="constrain-to-a-guideline">Constrain to a guideline</h3>
+<div class="cols">
+<div class="col-1of2">
+
+<p>
+You can add a vertical or horizontal guideline to which you can attach
+constraints. You can position the guideline within the layout based on either dp
+units or percent, relative to the layout's edge.
+</p>
+
+<p>
+To create a guideline, click <strong>Guidelines</strong>
+<img src="/studio/images/buttons/layout-editor-guidelines.png" class="inline-icon" alt="" />
+in the toolbar, and then click either <strong>Add Vertical Guideline</strong>
+or <strong>Add Horizontal Guideline</strong>.
+</p>
+
+<p>
+Click the circle at the edge of the guideline to toggle the measurements used to
+position the guideline (either percent or dp units from the layout's edge).
+</p>
+
+<p>
+Guidelines are not visible to your users.
+</p>
+</div>
+
+<div class="col-1of2">
+ <div class="video-wrapper">
+ <video controls poster="/training/constraint-layout/images/thumbnail-add-layout-guideline_2-2.png"
+ onclick="this.play()" width="100%">
+ <source src="https://storage.googleapis.com/androiddevelopers/videos/studio/add-layout-guideline_2-2.mp4" type="video/mp4">
+ <img src="/training/constraint-layout/images/thumbnail-add-layout-guideline_2-2.png" alt="" />
+ </video>
+ </div>
+ <p class="img-caption"><strong>Video 3.</strong> Adding a constraint to a guideline</p>
+</div>
+</div>
+
+
+<h2 id="use-autoconnect-and-infer-constraints">Use Autoconnect and Infer Constraints</h2>
+
+<div class="figure" style="width:460px">
+<div class="video-wrapper">
+<video controls poster=""
+ onclick="this.play()" width="460">
+ <source src="https://storage.googleapis.com/androiddevelopers/videos/studio/constraint-autoconnect_2-2.mp4" type="video/mp4">
+</video>
+</div>
+<p class="img-caption"><b>Video 4.</b> Adding a view with Autoconnect enabled</p>
+</div>
+
+<p>
+Autoconnect is a persistent mode that automatically creates two or more
+constraints for each view you add to the layout. Autoconnect is disabled by
+default. You can enable it by clicking <strong>Turn on Autoconnect</strong>
+<img src="/studio/images/buttons/layout-editor-autoconnect-on.png" class="inline-icon" alt="" />
+in the Layout Editor toolbar.
+</p>
+
+<p>While enabled, Autoconnect creates constraints for each view as you add them; it does not create
+constraints for existing views in the layout. If you drag a view once the constraints are made, the
+constraints do not change (though the margins do), so you must delete the constraints if you want to
+significantly reposition the view.</p>
+
+<p>Alternatively, you can click <strong>Infer Constraints</strong>
+<img src="/studio/images/buttons/layout-editor-infer.png" class="inline-icon" alt="" />
+to create constraints for all views in the layout.
+</p>
+
+<p>Infer Constraints is a one-time action that scans the entire layout to determine the most
+effective set of constraints for all views, so it may create constraints between elements that are
+far from each other. Autoconnect, however, creates constraints only for the view you are adding, and
+it creates constraints to only the nearest elements. In either case, you can always modify a
+constraint by clicking the constraint handle to delete it, and then create a new constraint.</p>
+
+
+<h2 id="adjust-the-view-size">Adjust the view size</h2>
+
+<p>
+You can use the handles on each corner of the view to resize it, but doing so
+hard codes the width and height values, which you should avoid for most views
+because hard-coded view sizes cannot adapt to different content and screen
+sizes. To select from one of the dynamic sizing modes or to define more specific
+dimensions, click a view and open the <strong>Properties</strong>
+<img src="/studio/images/buttons/window-properties.png" class="inline-icon" alt="" />
+window on the right side of the editor. At the top of the window is the view
+inspector, as shown in figure 10.
+</p>
+<div class="figure" style="width:287px" >
+<img src="/training/constraint-layout/images/layout-editor-properties-callouts_2-2_2x.png" alt=""
+ width="287" />
+<p class="img-caption"><strong>Figure 10.</strong> The <b>Properties</b> window includes controls for
+<strong>(1)</strong> view size, <strong>(2)</strong> margins, and
+<strong>(3)</strong> constraint bias.</p>
+</div>
+
+<p>
+The grey square represents the selected view. The symbols inside the square
+represent the height and width settings as follows:
+</p>
+
+<ul>
+<li>
+<img src="/studio/images/buttons/layout-width-wrap.png" class="inline-icon" alt="" />
+ <strong>Wrap Content</strong>: The view expands exactly as needed to fit its
+contents.
+<li>
+<img src="/studio/images/buttons/layout-width-match.png" class="inline-icon" alt="" />
+ <strong>Any Size</strong>: The view expands exactly as needed to match the
+constraints. The actual value is 0dp because the view has no desired dimensions, but
+it resizes as needed to meet the constraints. However, if the given dimension
+has only one constraint, then the view expands to fit its contents. Another way
+to think of it is "match constraints" (instead of <code>match_parent</code>) because it
+expands the view as much as possible after accounting for the limits of each
+constraint and its margins.
+<li>
+<img src="/studio/images/buttons/layout-width-fixed.png" class="inline-icon" alt="" />
+ <strong>Fixed</strong>: You specify the dimension in the text box below or by
+resizing the view in the editor.</li>
+</ul>
+
+<p>To toggle between these settings, click the symbols.</p>
+
+<p class="note"><strong>Note</strong>: You should not use <code>match_parent</code> for any view
+in a <code>ConstraintLayout</code>. Instead use "Any Size" (<code>0dp</code>).
+</p>
+
+
+<h2 id="adjust-the-constraint-bias">Adjust the constraint bias</h2>
+
+<p>When you add a constraint to both sides of a view (and the view size for the same dimension is
+either "fixed" or "wrap content"), the view becomes centered between the two anchor points by
+default. When a view is centered, the bias is 50%. You can adjust the bias by dragging the bias
+slider in the <b>Properties</b> window or by dragging the view, as shown in video 5.</p>
+
+<div class="video-wrapper" style="max-width:740px">
+<video controls poster="/training/constraint-layout/images/thumbnail-adjust-constraint-bias.png"
+ onclick="this.play();$(this.parentElement).addClass('playing');">
+ <source src="https://storage.googleapis.com/androiddevelopers/videos/studio/adjust-constraint-bias.mp4" type="video/mp4">
+ <img src="/training/constraint-layout/images/thumbnail-adjust-constraint-bias.png" alt="" />
+</video>
+</div>
+<p class="img-caption"><b>Video 5.</b> Adjusting the constraint bias</p>
+
+<p>If you instead want the view to stretch its size to meet the constraints, <a href="#adjust-the-
+view-size">switch the size to "any size"</a>.</p>
+
+
+<h2 id="adjust-the-view-margins">Adjust the view margins</h2>
+
+<p> To ensure that all your views are evenly spaced, click <strong>Margin</strong> <img
+src="/studio/images/buttons/layout-editor-margin.png" class="inline-icon" alt="" /> in the toolbar
+to select the default margin for each view that you add to the layout. The button changes to show
+your current margin selection. Any change you make to the default margin applies only to the views
+you add from then on. </p>
+
+
+<img src="/training/constraint-layout/images/layout-editor-margin-callout_2-2_2x.png"
+ alt="" width="232"/>
+<p class="img-caption"><strong>Figure 11.</strong> The toolbar's <b>Margin</b> button.
+Click to adjust the default margin.
+</p>
+
+<p> You can control the margin for each view in the <strong>Properties</strong> window by clicking
+the number on the line that represents each constraint (in figure 10, the margins are each set to
+16dp). </p>
+
+<p> All margins offered by the tool are factors of 8dp to help your views align to Material Design's
+<a href="https://material.google.com/layout/metrics-keylines.html">8dp square grid
+recommendations</a>. </p>
+
+</body>
+</html>
diff --git a/docs/html/training/material/images/palette-library-color-profiles_2-1_2x.png b/docs/html/training/material/images/palette-library-color-profiles_2-1_2x.png
new file mode 100644
index 000000000000..d14ec32c7500
--- /dev/null
+++ b/docs/html/training/material/images/palette-library-color-profiles_2-1_2x.png
Binary files differ
diff --git a/docs/html/training/material/images/palette-library-title-text-color_2-1_2x.png b/docs/html/training/material/images/palette-library-title-text-color_2-1_2x.png
new file mode 100644
index 000000000000..883adba6a430
--- /dev/null
+++ b/docs/html/training/material/images/palette-library-title-text-color_2-1_2x.png
Binary files differ
diff --git a/docs/html/training/material/index.jd b/docs/html/training/material/index.jd
index 4001e6b7442f..8baa0659e95b 100644
--- a/docs/html/training/material/index.jd
+++ b/docs/html/training/material/index.jd
@@ -3,7 +3,6 @@ page.type=design
page.image=images/cards/material_2x.png
page.metaDescription=Learn how to apply material design to your apps.
-
@jd:body
<div id="tb-wrapper">
@@ -58,6 +57,9 @@ specification</a> and use the new components and functionality available in Andr
<dt><a href="{@docRoot}training/material/compatibility.html">Maintaining Compatibility</a></dt>
<dd>Learn how to maintain compatibility with platform versions earlier than Android 5.0.</dd>
+
+ <dt><a href="{@docRoot}training/material/palette-colors.html">Selecting Colors with the Palette API</a></dt>
+ <dd>Learn how to select colors for your app using the v7 Palette library.</dd>
</dl>
<h2>Video Training</h2>
diff --git a/docs/html/training/material/palette-colors.html b/docs/html/training/material/palette-colors.html
new file mode 100644
index 000000000000..27485d2decd8
--- /dev/null
+++ b/docs/html/training/material/palette-colors.html
@@ -0,0 +1,310 @@
+<html devsite>
+<head>
+ <title>Selecting Colors with the Palette API</title>
+ <meta name="book_path" value="/training/_book.yaml" />
+ <meta name="top_category" value="develop" />
+ <meta name="subcategory" value="training" />
+</head>
+<body>
+
+<div id="tb-wrapper">
+ <div id="tb">
+ <h2>This lesson teaches you to</h2>
+ <ol>
+ <li><a href="#set-up-the-library">Set up the library</a></li>
+ <li><a href="#create-a-palette">Create a palette</a>
+ <ol>
+ <li><a href="#generate-a-palette-instance">Generate a Palette instance</a></li>
+ <li><a href="#customize-your-palette">Customize your palette</a></li>
+ </ol>
+ </li>
+ <li><a href="#extract-color-profiles">Extract color profiles</a>
+ <ol>
+ <li><a href="#use-swatches">Use swatches to create color schemes</a></li>
+ </ol>
+ </li>
+ </ol>
+ <h2>You should also read</h2>
+ <ul>
+ <li><a href="http://www.google.com/design/spec">Material design specification</a></li>
+ <li><a href="/design/material/index.html">Material design on Android</a></li>
+ </ul>
+ </div>
+</div>
+
+<p>Good visual design is essential for a successful app, and color schemes are a primary component of design. The palette library is a
+<a href="/topic/libraries/support-library/features.html#v7-palette">support library</a>
+that extracts prominent colors from images to help you create visually engaging apps.</p>
+
+<p>You can use the palette library to design layout
+<a href="/guide/topics/ui/themes.html">themes</a> and apply custom colors to visual elements in your app.
+For example, you can use a palette to create a color-coordinated title
+card for a song based on its album cover or to adjust an app’s toolbar color when its
+background image changes. The <code><a
+href="/reference/android/support/v7/graphics/Palette.html">Palette</a></code> object gives
+you access to the colors in a <code><a
+href="/reference/android/graphics/Bitmap.html">Bitmap</a></code>
+image while also providing six main color profiles from the bitmap to help
+inform your <a href="http://material.google.com">design choices</a>.</p>
+
+<h2 id="set-up-the-library">Set up the library</h2>
+
+<p>To use the palette library, install or update the <a
+href="/topic/libraries/support-library/index.html">Android
+Support Library</a> to version 24.0.0 or higher and follow the instructions for <a
+href="/topic/libraries/support-library/setup.html#add-library">Adding
+Support Libraries</a> to add the palette library to your app development project.</p>
+
+<p>Make sure that the version specified in your dependency identifier matches your
+app’s <code>compileSdkVersion</code>, set in the <code>build.gradle</code>
+file:</p>
+
+<pre class="prettyprint">
+android {
+ compileSdkVersion 24
+ ...
+}
+
+dependencies {
+ ...
+ compile 'com.android.support:palette-v7:24.2.1'
+}
+</pre>
+
+<p>For more information about adding the palette dependency, read about the palette
+feature in the <a
+href="/topic/libraries/support-library/features.html#v7-palette">support
+library documentation</a>.</p>
+
+<h2 id="create-a-palette">Create a palette</h2>
+
+<p>A <code>Palette</code> object gives you access to the primary colors in an
+image, as well as the corresponding colors for overlaid text. Use palettes to design
+your app’s style and to dynamically change your app’s color scheme based on a
+given source image.</p>
+
+<p>To create a palette, first instantiate a <code><a
+href="https://developer.android.com/reference/android/support/v7/graphics/Palette.Builder.html">Palette.Builder</a></code>
+from a <code>Bitmap</code>. You can then use the
+<code>Palette.Builder</code> to customize the palette before generating it. This
+section will describe palette generation and customization from a bitmap
+image.</p>
+
+<h3 id="generate-a-palette-instance">Generate a Palette instance</h3>
+
+<p>Generate a <code>Palette</code> instance using <code>Palette</code>’s
+<code><a
+href="/reference/android/support/v7/graphics/Palette.html#from(android.graphics.Bitmap)">from(Bitmap
+bitmap)</a></code> method to first create a <code>Palette.Builder</code>
+from a <code>Bitmap</code>. The builder can then generate the palette either
+synchronously or asynchronously.</p>
+
+<p>Use synchronous palette generation if you want to create the palette on
+the same thread as the method being called. If you generate the palette
+asynchronously on a different thread, use the <code><a
+href="/reference/android/support/v7/graphics/Palette.PaletteAsyncListener.html#onGenerated(android.support.v7.graphics.Palette)">onGenerated()</a></code>
+method to access the palette immediately after it has been created.</p>
+
+<p>The following code snippet provides example methods for both types of palette generation:</p>
+
+<pre class="prettyprint">
+// Generate palette synchronously and return it
+public Palette createPaletteSync(Bitmap bitmap) {
+ Palette p = Palette.from(bitmap).generate();
+ return p;
+}
+
+// Generate palette asynchronously and use it on a different
+// thread using onGenerated()
+public void createPaletteAsync(Bitmap bitmap) {
+ Palette.from(bitmap).generate(new PaletteAsyncListener() {
+ public void onGenerated(Palette p) {
+ // Use generated instance
+ }
+ });
+}
+</pre>
+
+<p>If you need to continuously generate palettes for a sorted list of images
+or objects, consider <a
+href="/reference/android/util/LruCache.html">caching</a>
+the <code>Palette</code> instances to prevent slow UI performance. You also
+should not create the palettes on your <a href="/training/articles/perf-anr.html">main thread</a>.</p>
+
+<h3 id="customize-your-palette">Customize your palette</h3>
+
+<p>The <code>Palette.Builder</code> allows you to customize your palette by
+choosing how many colors are in the resulting palette, what area of your
+image the builder uses to generate the palette, and what colors are allowed in the
+palette. For example, you can filter out the color black or ensure that the
+builder only uses the top half of an image to generate your palette.</p>
+
+<p>Fine-tune your palette’s size and colors with the following methods from
+the <code>Palette.Builder</code> class:</p>
+
+<dl>
+
+ <dt><code><a
+ href="/reference/android/support/v7/graphics/Palette.Builder.html#addFilter(android.support.v7.graphics.Palette.Filter)">addFilter()</a></code></dt>
+ <dd>This method adds a filter that indicates what colors are allowed in the
+ resulting palette. Pass in your own<code> <a
+ href="/reference/android/support/v7/graphics/Palette.Filter.html">Palette.Filter</a></code>
+ and modify its <code>isAllowed()</code> method to determine which colors are
+ filtered from the palette.</dd>
+
+ <dt><code><a
+ href="/reference/android/support/v7/graphics/Palette.Builder.html#maximumColorCount(int)">maximumColorCount()</a></code></dt>
+ <dd>This method sets the maximum number of colors in your palette. The
+ default value is 16, and the optimal value depends on the source image.
+ For landscapes, optimal values range from 8-16 while pictures with faces
+ usually have values that fall between 24-32. The
+ <code>Palette.Builder</code> takes longer to generate palettes with more
+ colors.</dd>
+
+ <dt><code><a
+ href="/reference/android/support/v7/graphics/Palette.Builder.html#setRegion(int,%20int,%20int,%20int)">setRegion()</a></code></dt>
+ <dd>This method indicates what area of the bitmap the builder uses when
+ creating the palette. You can only use this method when generating the palette from
+ a bitmap, and it does not affect the original image.</dd>
+
+ <dt><code><a
+ href="/reference/android/support/v7/graphics/Palette.Builder.html#addTarget(android.support.v7.graphics.Target)">addTarget()</a></code></dt>
+ <dd>This method allows you to perform your own color matching by adding a
+ <code><a
+ href="/reference/android/support/v7/graphics/Target.html">Target</a></code>
+ color profile to the builder. If the default <code>Target</code>s are not
+ sufficient, advanced developers can create their own <code>Target</code>s
+ using a <code><a
+ href="/reference/android/support/v7/graphics/Target.Builder.html">Target.Builder</a></code>.</dd>
+
+</dl>
+
+<h2 id="extract-color-profiles">Extract color profiles</h2>
+
+<p>Based on the <a
+href="https://material.google.com/style/color.html#">standards
+of material design</a>, the palette library extracts commonly used color
+profiles from an image. Each profile is defined by a <code><a
+href="/reference/android/support/v7/graphics/Target.html">Target</a></code>,
+and colors extracted from the bitmap image are scored against each profile
+based on saturation, luminance, and population (number of pixels in the bitmap
+represented by the color). For each profile, the color with the best score
+defines that color profile for the given image.</p>
+
+<p>By default, a <code>Palette</code> object contains 16 primary colors from
+a given image. When generating your palette, you can <a
+href="#customize-your-palette">customize</a> its number of colors using the
+<code>Palette.Builder</code>. Extracting more colors provides more potential
+matches for each color profile but also causes <code>Palette.Builder</code> to
+take longer when generating the palette.</p>
+
+<p>The palette library attempts to extract the following six color
+profiles:</p>
+
+<ul>
+ <li>Light Vibrant</li>
+ <li>Vibrant</li>
+ <li>Dark Vibrant</li>
+ <li>Light Muted</li>
+ <li>Muted</li>
+ <li>Dark Muted</li>
+</ul>
+
+<p>Each of <code>Palette</code>’s <code>get&lt;<em>Profile</em>&gt;Color()</code>
+methods returns the color in the palette associated with that particular profile,
+where <code>&lt;<em>Profile</em>&gt;</code> is replaced by the name of one of the six
+color profiles. For example, the method to get the Dark Vibrant color profile is <code><a
+href="/reference/android/support/v7/graphics/Palette.html#getDarkVibrantColor(int)">getDarkVibrantColor()</a></code>.
+Since not all images will contain all color profiles, you must also provide
+a default color to return.</p>
+
+<p>Figure 1 displays a photo and its corresponding color
+profiles from the <code>get&lt;<em>Profile</em>&gt;Color()</code> methods.</p>
+
+<img src="/training/material/images/palette-library-color-profiles_2-1_2x.png" alt="" width="624"/>
+
+<p class="img-caption"><strong>Figure 1.</strong> An example image and its
+extracted color profiles given the default maximum color count (16) for the palette.</p>
+
+<h3 id="use-swatches">Use swatches to create color schemes</h3>
+
+<p>The <code>Palette</code> class also generates <code><a
+href="/reference/android/support/v7/graphics/Palette.Swatch.html">Palette.Swatch</a></code>
+objects for each color profile. <code>Palette.Swatch</code>
+objects contain the associated color for that profile, as well as the
+color’s population in pixels.</p>
+
+<p>Swatches have additional methods for accessing more information about the color
+profile, such as HSL values and pixel population. You can use swatches to help
+create more comprehensive color schemes and app themes using the <code><a
+href="/reference/android/support/v7/graphics/Palette.Swatch.html#getBodyTextColor()">getBodyTextColor()</a></code>
+and <code><a
+href="/reference/android/support/v7/graphics/Palette.Swatch.html#getTitleTextColor()">getTitleTextColor()</a></code>
+methods. These methods return colors appropriate for use over the swatch’s
+color.</p>
+
+<p>Each of <code>Palette</code>’s <code>get&lt;<em>Profile</em>&gt;Swatch()</code>
+methods returns the swatch associated with that particular profile,
+where <code>&lt;<em>Profile</em>&gt;</code> is replaced by the name of one of the six
+color profiles. Although the palette’s <code>get&lt;<em>Profile</em>&gt;Swatch()</code> methods
+do not require default value parameters, they return <code>null</code> if that
+particular profile does not exist in the image. Therefore, you should check that
+a swatch is not null before using it. For example, the following method
+returns the Vibrant swatch from a palette if the swatch is not null:</p>
+
+<pre class="prettyprint">
+// Return a palette's vibrant swatch after checking that it exists
+private Palette.Swatch checkVibrantSwatch(Palette p) {
+ Palette.Swatch vibrant = p.getVibrantSwatch();
+ if (vibrant != null) {
+ return vibrant;
+ }
+ // Throw error
+}
+</pre>
+
+<p>To access all colors in a palette, the <code><a
+href="/reference/android/support/v7/graphics/Palette.html#getSwatches()">getSwatches()</a></code>
+method returns a list of all swatches generated from an
+image, including the standard six color profiles.</p>
+
+<p>The following snippet of code uses the methods from the above code snippets to
+synchronously generate a palette, get its vibrant swatch, and change the colors of a
+toolbar to match the bitmap image. Figure 2 displays the resulting image and toolbar.</p>
+
+<div class="cols">
+
+ <div class="col-2of3">
+
+<pre class="prettyprint">
+// Set the background and text colors of a toolbar given a
+// bitmap image to match
+public void setToolbarColor(Bitmap bitmap) {
+ // Generate the palette and get the vibrant swatch
+ // See the createPaletteSync() and checkVibrantSwatch() methods
+ // from the code snippets above
+ Palette p = createPaletteSync(bitmap);
+ Palette.Swatch vibrantSwatch = checkVibrantSwatch(p);
+
+ // Set the toolbar background and text colors
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ toolbar.setBackgroundColor(vibrantSwatch.getRgb());
+ toolbar.setTitleTextColor(vibrantSwatch.getTitleTextColor());
+}
+</pre>
+
+ </div>
+
+ <div class="col-1of3">
+
+ <img src="/training/material/images/palette-library-title-text-color_2-1_2x.png" alt="" width="400"/>
+
+ <p class="img-caption"><strong>Figure 2.</strong> An example image with its
+ vibrant-colored toolbar and corresponding title text color.</p>
+
+ </div>
+
+</div>
+
+</body>
+</html>
diff --git a/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd b/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd
index 8fc4dcac25d4..df8b1bc5c9a6 100644
--- a/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd
+++ b/docs/html/training/testing/unit-testing/instrumented-unit-tests.jd
@@ -292,23 +292,21 @@ from the command line. Test results provide test logs and include the details
of any app failures.</p>
<p>
- Before you can start using Firebase Test Lab, you need to:
+ Before you can start using Firebase Test Lab, you need to do the following
+unless you already have a Google account and a Firebase project with the Blaze
+billing plan enabled:
</p>
<ol>
- <li>
- <a href="https://console.developers.google.com/freetrial">Create a
- Google Cloud Platform account</a> to use with active billing.
- </li>
-
- <li>
- <a href="https://support.google.com/cloud/answer/6251787">Create a Google
- Cloud project</a> for your app.
- </li>
-
- <li>
- <a href="https://support.google.com/cloud/answer/6288653">Set up an active
- billing account</a> and associate it with the project you just created.
+ <li><a href="https://accounts.google.com/">Create a Google account</a>,
+ if you don't have one already.</li>
+ <li>In the <a href="https://console.firebase.google.com/">Firebase
+ console</a>, click <b>Create New Project</b>.</li>
+ <li>In the Firebase console, click <b>Upgrade</b>, and then click <b>Select
+Plan</b> in the <b>Blaze</b> plan column.
+ <p class="note"><b>Note</b>: To learn about billing,
+see <a href="https://firebase.google.com/docs/test-lab/overview#billing">Test
+Lab billing</a>.</p>
</li>
</ol>
@@ -318,10 +316,10 @@ Configure a test matrix and run a test
</h4>
<p>
- Android Studio provides integrated tools that allow you to configure how you
- want to deploy your tests to Firebase Test Lab. After you have created a Google
- Cloud project with active billing, you can create a test configuration and
- run your tests:
+Android Studio provides integrated tools that allow you to configure how you
+want to deploy your tests to Firebase Test Lab. After you have created a
+Firebase project with Blaze plan billing, you can create a test configuration
+and run your tests:
</p>
<ol>
@@ -329,7 +327,8 @@ Configure a test matrix and run a test
the main menu.
</li>
- <li>Click <strong>Add New Configuration (+)</strong> and select
+ <li>Click <strong>Add New Configuration</strong> <img
+src="/studio/images/buttons/ic_plus.png" alt="" class="inline-icon"/> and select
<strong>Android Tests</strong>.
</li>
@@ -340,7 +339,7 @@ Configure a test matrix and run a test
</li>
<li>From the <em>Target</em> drop-down menu under <em>Deployment Target
- Options</em>, select <strong>Cloud Test Lab Device Matrix</strong>.
+ Options</em>, select <strong>Firebase Test Lab Device Matrix</strong>.
</li>
<li>If you are not logged in, click <strong>Connect to Google Cloud
@@ -348,9 +347,9 @@ Configure a test matrix and run a test
</li>
<li>Next to <em>Cloud Project</em>, click the <img src=
- "{@docRoot}images/tools/as-wrench.png" alt="wrench and nut" style=
- "vertical-align:bottom;margin:0;"> button and select your Google Cloud
- Platform project from the list.
+ "{@docRoot}images/tools/as-wrench.png" alt="" class="inline-icon"/>
+ button and select your Firebase
+ project from the list.
</li>
</ol>
</li>
@@ -359,7 +358,7 @@ Configure a test matrix and run a test
<ol type="a">
<li>Next to the <em>Matrix Configuration</em> drop-down list, click <strong>
Open Dialog</strong> <img src="{@docRoot}images/tools/as-launchavdm.png"
- alt="ellipses button" style="vertical-align:bottom;margin:0;">.
+ alt="" class="inline-icon">.
</li>
<li>Click <strong>Add New Configuration (+)</strong>.
@@ -385,8 +384,7 @@ Configure a test matrix and run a test
</li>
<li>Run your tests by clicking <strong>Run</strong> <img src=
- "{@docRoot}images/tools/as-run.png" alt="" style=
- "vertical-align:bottom;margin:0;">.
+ "{@docRoot}images/tools/as-run.png" alt="" class="inline-icon"/>.
</li>
</ol>
@@ -404,7 +402,7 @@ Configure a test matrix and run a test
When Firebase Test Lab completes running your tests, the <em>Run</em> window
will open to show the results, as shown in figure 2. You may need to click
<strong>Show Passed</strong> <img src="{@docRoot}images/tools/as-ok.png" alt=
- "" style="vertical-align:bottom;margin:0;"> to see all your executed tests.
+ "" class="inline-icon"/> to see all your executed tests.
</p>
<img src="{@docRoot}images/training/ctl-test-results.png" alt="">
@@ -416,15 +414,7 @@ Configure a test matrix and run a test
<p>
You can also analyze your tests on the web by following the link displayed at
- the beginning of the test execution log in the <em>Run</em> window, as shown
- in figure 3.
-</p>
-
-<img src="{@docRoot}images/training/ctl-exec-log.png" alt="">
-
-<p class="img-caption">
- <strong>Figure 3.</strong> Click the link to view detailed test results on
- the web.
+ the beginning of the test execution log in the <em>Run</em> window.
</p>
<p>
diff --git a/docs/html/training/tv/playback/index.jd b/docs/html/training/tv/playback/index.jd
index d5e4e6712b05..34c6287173ca 100644
--- a/docs/html/training/tv/playback/index.jd
+++ b/docs/html/training/tv/playback/index.jd
@@ -69,6 +69,10 @@ startpage=true
<dd>Learn how to use the Leanback support library to guide a user through a series of
decisions.</dd>
+ <dt><b><a href="onboarding.html">Introducing First-time Users to Your App</a></b></dt>
+ <dd>Learn how to use the Leanback support library to show first-time users
+ how to get the most out of your app.</dd>
+
<dt><b><a href="options.html">Enabling Background Playback</a></b></dt>
<dd>Learn how to continue playback when the user clicks on <strong>Home</strong>.</dd>
</dl>
diff --git a/docs/html/training/tv/playback/onboarding.jd b/docs/html/training/tv/playback/onboarding.jd
new file mode 100644
index 000000000000..bb41bece1d28
--- /dev/null
+++ b/docs/html/training/tv/playback/onboarding.jd
@@ -0,0 +1,377 @@
+page.title=Introducing First-time Users to Your App
+page.tags=tv,onboarding,OnboardingFragment
+page.keywords=tv,onboarding,OnboardingFragment
+helpoutsWidget=true
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+ <h2>This lesson teaches you to</h2>
+ <ol>
+ <li><a href="#addFragment">Add an OnboardingFragment</a></li>
+ <li><a href="#pageContent">Add OnboardingFragment Pages</a></li>
+ <li><a href="#logoScreen">Add an Initial Logo Screen</a></li>
+ <li><a href="#pageAnimations">Customize Page Animations</a></li>
+ <li><a href="#themes">Customize Themes</a></li>
+ </ol>
+ <h2>Try it out</h2>
+ <ul>
+ <li><a class="external-link" href="https://github.com/googlesamples/androidtv-Leanback">Android
+ Leanback sample app</a></li>
+ </ul>
+</div>
+</div>
+
+<p>
+To show a first-time user how to get the most from your app, present
+onboarding information at app startup. Here are some examples of onboarding
+information:
+</p>
+
+<ul>
+<li>Present detailed information on which channels are available when a user
+first accesses a channel app.</li>
+<li>Call attention to noteworthy features in your app.</li>
+<li>Illustrate any required or recommended steps that users should take when
+using the app for the first time.</li>
+</ul>
+
+<p>The <a href=
+"{@docRoot}tools/support-library/features.html#v17-leanback">v17 Leanback
+support library</a> provides the
+{@link android.support.v17.leanback.app.OnboardingFragment} class for
+presenting first-time user information. This lesson describes how to use the
+{@link android.support.v17.leanback.app.OnboardingFragment} class to present
+introductory information that is shown when the app launches for the first
+time. {@link android.support.v17.leanback.app.OnboardingFragment} uses TV UI
+best practices to present the information in a way that matches TV UI styles,
+and is easy to navigate on TV devices.</p>
+
+<img src="{@docRoot}images/training/tv/playback/onboarding-fragment.png"
+srcset="{@docRoot}images/training/tv/playback/onboarding-fragment.png 1x,
+{@docRoot}images/training/tv/playback/onboarding-fragment_2x.png 2x" />
+<p class="img-caption"><strong>Figure 1.</strong> An example
+OnboardingFragment.</p>
+
+<p>Your {@link android.support.v17.leanback.app.OnboardingFragment} should
+not contain UI elements that require user input, such as buttons and fields.
+Similarly, it should not be used as a UI element for a task the user will do
+regularly. If you need to present a multi-page UI that requires
+user input, consider using a
+{@link android.support.v17.leanback.app.GuidedStepFragment}.</p>
+
+<h2 id="addFragment">Add an OnboardingFragment</h2>
+
+<p>To add an {@link android.support.v17.leanback.app.OnboardingFragment}
+to your app, implement a class that extends
+the {@link android.support.v17.leanback.app.OnboardingFragment} class. Add
+this fragment to an activity, either via the activity's layout XML, or
+programmatically. Make sure the activity or
+fragment is using a theme derived from
+{@link android.support.v17.leanback.R.style#Theme_Leanback_Onboarding},
+as described in <a href="#themes">Customize Themes</a>.</p>
+
+<p>In the {@link android.app.Activity#onCreate onCreate()} method of your
+app's main activity, call
+{@link android.app.Activity#startActivity startActivity()}
+with an {@link android.content.Intent} that points to your
+{@link android.support.v17.leanback.app.OnboardingFragment OnboardingFragment's}
+parent activity. This ensures that your
+{@link android.support.v17.leanback.app.OnboardingFragment} appears as
+soon as your app starts.<p>
+
+<p>To ensure that the
+{@link android.support.v17.leanback.app.OnboardingFragment} only appears the
+first time that the user starts your app, use a
+{@link android.content.SharedPreferences} object
+to track whether the user has already viewed the
+{@link android.support.v17.leanback.app.OnboardingFragment}. Define a boolean
+value that changes to true when the user finishes viewing the
+{@link android.support.v17.leanback.app.OnboardingFragment}. Check
+this value in your main activity’s
+{@link android.app.Activity#onCreate onCreate()}, and only start the
+{@link android.support.v17.leanback.app.OnboardingFragment} parent activity if
+the value is false. The following example shows an override of
+{@link android.app.Activity#onCreate onCreate()} that checks for a
+{@link android.content.SharedPreferences} value and, if not set to true, calls
+{@link android.app.Activity#startActivity startActivity()} to
+show the {@link android.support.v17.leanback.app.OnboardingFragment}:</p>
+
+<pre>
+&#64;Override
+protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ SharedPreferences sharedPreferences =
+ PreferenceManager.getDefaultSharedPreferences(this);
+ // Check if we need to display our OnboardingFragment
+ if (!sharedPreferences.getBoolean(
+ MyOnboardingFragment.COMPLETED_ONBOARDING_PREF_NAME, false)) {
+ // The user hasn't seen the OnboardingFragment yet, so show it
+ startActivity(new Intent(this, OnboardingActivity.class));
+ }
+}
+</pre>
+
+<p>After the user views the
+{@link android.support.v17.leanback.app.OnboardingFragment}, mark it as viewed
+using the {@link android.content.SharedPreferences} object. To do this, in your
+{@link android.support.v17.leanback.app.OnboardingFragment}, override
+{@link android.support.v17.leanback.app.OnboardingFragment#onFinishFragment
+onFinishFragment()} and set your {@link android.content.SharedPreferences} value
+to true, as shown in the following example:
+
+<pre>
+&#64;Override
+protected void onFinishFragment() {
+ super.onFinishFragment();
+ // User has seen OnboardingFragment, so mark our SharedPreferences
+ // flag as completed so that we don't show our OnboardingFragment
+ // the next time the user launches the app.
+ SharedPreferences.Editor sharedPreferencesEditor =
+ PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
+ sharedPreferencesEditor.putBoolean(
+ COMPLETED_ONBOARDING_PREF_NAME, true);
+ sharedPreferencesEditor.apply();
+}
+</pre>
+
+<h2 id="pageContent">Add OnboardingFragment Pages</h2>
+
+<p>After you add your
+{@link android.support.v17.leanback.app.OnboardingFragment}, you need to define
+the onboarding pages. An
+{@link android.support.v17.leanback.app.OnboardingFragment} displays content
+in a series of ordered pages. Each page can have a title, description, and
+several sub-views that can contain images or animations.</p>
+
+<img src="{@docRoot}images/training/tv/playback/onboarding-fragment-diagram.png"
+/><p class="img-caption"><strong>Figure 2.</strong> OnboardingFragment
+page elements.
+</p>
+
+<p>Figure 2 shows an example page with callouts marking customizable page
+elements that your {@link android.support.v17.leanback.app.OnboardingFragment}
+can provide. The page elements are:</p>
+
+<ol>
+<li>The page title.</li>
+<li>The page description.</li>
+<li>The page content view, in this case a simple green checkmark in a grey box.
+This view is optional. Use this view to illustrate page details such as a
+screenshot that highlights the app feature that the page describes.</li>
+<li>The page background view, in this case a simple blue gradient. This view
+always renders behind other views on the page. This view is optional.</li>
+<li>The page foreground view, in this case a logo. This view always renders
+in front of all other views on the page. This view is optional.</li>
+</ol>
+
+<p>Initialize page information when your
+{@link android.support.v17.leanback.app.OnboardingFragment} is first created
+or attached to the parent activity, as the system requests page
+information when it creates the fragment's view. You can initialize page
+information in your class constructor or in an override of
+{@link android.app.Fragment#onAttach onAttach()}.</p>
+
+<p>Override each of the following methods that provide page information
+to the system:</p>
+
+<ul>
+<li>{@link android.support.v17.leanback.app.OnboardingFragment#getPageCount
+getPageCount()} returns the number of pages in your
+{@link android.support.v17.leanback.app.OnboardingFragment}.</li>
+<li>{@link android.support.v17.leanback.app.OnboardingFragment#getPageTitle
+getPageTitle()} returns the title for the requested page number.</li>
+<li>{@link android.support.v17.leanback.app.OnboardingFragment#getPageDescription
+getPagedescription()} returns the description for the requested page
+number.</li>
+</ul>
+
+<p>Override each of the following methods to provide optional sub-views used
+to display images or animations:</p>
+
+<ul>
+<li>{@link android.support.v17.leanback.app.OnboardingFragment#onCreateBackgroundView
+onCreateBackgroundView()} returns a {@link android.view.View} that you
+create to act as the background view, or null if no background view is needed.
+<li>{@link android.support.v17.leanback.app.OnboardingFragment#onCreateContentView
+onCreateContentView()} returns a {@link android.view.View} that you
+create to act as the content view, or null if no content view is needed.
+<li>{@link android.support.v17.leanback.app.OnboardingFragment#onCreateForegroundView
+onCreateForegroundView()} returns a {@link android.view.View} that you
+create to act as the foreground view, or null if no foreground view is needed.
+</ul>
+
+<p>The system adds the {@link android.view.View} that you create to the page
+layout. The following example overrides
+{@link android.support.v17.leanback.app.OnboardingFragment#onCreateContentView
+onCreateContentView()} and returns an {@link android.widget.ImageView}:</p>
+
+<pre>
+private ImageView mContentView;
+...
+&#64;Override
+protected View onCreateContentView(LayoutInflater inflater, ViewGroup container) {
+ mContentView = new ImageView(getContext());
+ mContentView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+ mContentView.setImageResource(R.drawable.onboarding_content_view);
+ mContentView.setPadding(0, 32, 0, 32);
+ return mContentView;
+}
+</pre>
+
+<h2 id="logoScreen">Add an Initial Logo Screen</h2>
+
+<p>Your {@link android.support.v17.leanback.app.OnboardingFragment} can start
+with an optional logo screen that introduces your app. If you want to display
+a {@link android.graphics.drawable.Drawable} as your logo screen, in your
+{@link android.support.v17.leanback.app.OnboardingFragment OnboardingFragment's}
+{@link android.app.Fragment#onCreate onCreate()} method, call
+{@link android.support.v17.leanback.app.OnboardingFragment#setLogoResourceId
+setLogoResourceId()} with the ID of your
+{@link android.graphics.drawable.Drawable}. The
+system will fade in and briefly display this
+{@link android.graphics.drawable.Drawable}, and then fade out the
+{@link android.graphics.drawable.Drawable}
+before displaying the first page of your
+{@link android.support.v17.leanback.app.OnboardingFragment}.</p>
+
+<p>If you want to provide a custom animation for your logo screen, instead of
+calling
+{@link android.support.v17.leanback.app.OnboardingFragment#setLogoResourceId
+setLogoResourceId()}, override
+{@link android.support.v17.leanback.app.OnboardingFragment#onCreateLogoAnimation
+onCreateLogoAnimation()} and return an {@link android.animation.Animator}
+object that renders your custom animation, as shown in the following example:
+</p>
+
+<pre>
+&#64;Override
+public Animator onCreateLogoAnimation() {
+ return AnimatorInflater.loadAnimator(mContext,
+ R.animator.onboarding_logo_screen_animation);
+}
+</pre>
+
+<h2 id="pageAnimations">Customize Page Animations</h2>
+
+<p>The system uses default animations when displaying the first page of your
+{@link android.support.v17.leanback.app.OnboardingFragment} and when the user
+navigates to a different page. You can customize these animations by
+overriding methods in your
+{@link android.support.v17.leanback.app.OnboardingFragment}.</p>
+
+<p>To customize the animation that appears on your first page,
+override
+{@link android.support.v17.leanback.app.OnboardingFragment#onCreateEnterAnimation
+onCreateEnterAnimation()} and return an {@link android.animation.Animator}.
+The following example creates an
+{@link android.animation.Animator} that scales the content view
+horizontally:</p>
+
+<pre>
+&#64;Override
+protected Animator onCreateEnterAnimation() {
+ Animator startAnimator = ObjectAnimator.ofFloat(mContentView,
+ View.SCALE_X, 0.2f, 1.0f).setDuration(ANIMATION_DURATION);
+ return startAnimator;
+}
+</pre>
+
+<p>To customize the animation used when the user navigates to a different page,
+override
+{@link android.support.v17.leanback.app.OnboardingFragment#onPageChanged
+onPageChanged()}. In your
+{@link android.support.v17.leanback.app.OnboardingFragment#onPageChanged
+onPageChanged()} method, create {@link android.animation.Animator Animators}
+that remove the previous page and display the next page, add these to an
+{@link android.animation.AnimatorSet}, and play the set. The following
+example uses a fade-out animation to remove the previous page, updates the
+content view image, and uses a fade-in animation to display the next page:</p>
+
+<pre>
+&#64;Override
+protected void onPageChanged(final int newPage, int previousPage) {
+ // Create a fade-out animation used to fade out previousPage and, once
+ // done, swaps the contentView image with the next page's image.
+ Animator fadeOut = ObjectAnimator.ofFloat(mContentView,
+ View.ALPHA, 1.0f, 0.0f).setDuration(ANIMATION_DURATION);
+ fadeOut.addListener(new AnimatorListenerAdapter() {
+ &#64;Override
+ public void onAnimationEnd(Animator animation) {
+ mContentView.setImageResource(pageImages[newPage]);
+ }
+ });
+ // Create a fade-in animation used to fade in nextPage
+ Animator fadeIn = ObjectAnimator.ofFloat(mContentView,
+ View.ALPHA, 0.0f, 1.0f).setDuration(ANIMATION_DURATION);
+ // Create AnimatorSet with our fade-out and fade-in animators, and start it
+ AnimatorSet set = new AnimatorSet();
+ set.playSequentially(fadeOut, fadeIn);
+ set.start();
+}
+</pre>
+
+<p>For more details about how to create
+{@link android.animation.Animator Animators} and
+{@link android.animation.AnimatorSet AnimatorSets}, see
+<a href="https://developer.android.com/guide/topics/graphics/prop-animation.html">
+Property Animations</a>.</p>
+
+<h2 id="themes">Customize Themes</h2>
+
+<p>Any {@link android.support.v17.leanback.app.OnboardingFragment}
+implementation must use either the
+{@link android.support.v17.leanback.R.style#Theme_Leanback_Onboarding} theme
+or a theme that inherits from
+{@link android.support.v17.leanback.R.style#Theme_Leanback_Onboarding}. Set the
+theme for your {@link android.support.v17.leanback.app.OnboardingFragment} by
+doing one of the following:</p>
+
+<ul>
+<li>Set the {@link android.support.v17.leanback.app.OnboardingFragment
+OnboardingFragment's} parent activity to use the desired theme. The following
+example shows how to set an activity to use
+{@link android.support.v17.leanback.R.style#Theme_Leanback_Onboarding} in the
+app manifest:
+<pre>
+&lt;activity
+ android:name=".OnboardingActivity"
+ android:enabled="true"
+ android:exported="true"
+ android:theme="&#64;style/Theme.Leanback.Onboarding"&gt;
+&lt;/activity&gt;
+</pre>
+</li>
+<li>
+Set the theme in the parent activity by using the
+{@link android.support.v17.leanback.R.styleable#LeanbackOnboardingTheme_onboardingTheme}
+attribute in a custom activity theme. Point this attribute to another
+custom theme that only the
+{@link android.support.v17.leanback.app.OnboardingFragment}
+objects in your activity use. Use this approach if your activity already uses
+a custom theme and you don't want to apply
+{@link android.support.v17.leanback.app.OnboardingFragment} styles to other
+views in the activity.
+</li>
+<li>Override
+{@link android.support.v17.leanback.app.OnboardingFragment#onProvideTheme
+onProvideTheme()} and return the desired theme. Use this approach if
+multiple activities use your
+{@link android.support.v17.leanback.app.OnboardingFragment}
+or if the parent activity can't use the desired theme.
+The following example overrides
+{@link android.support.v17.leanback.app.OnboardingFragment#onProvideTheme
+onProvideTheme()} and returns
+{@link android.support.v17.leanback.R.style#Theme_Leanback_Onboarding}:
+<pre>
+&#64;Override
+public int onProvideTheme() {
+ return R.style.Theme_Leanback_Onboarding;
+}
+</pre>
+</li>
+</ul> \ No newline at end of file
diff --git a/docs/html/training/tv/start/hardware.jd b/docs/html/training/tv/start/hardware.jd
index 97cf7ff6626d..063987159b79 100644
--- a/docs/html/training/tv/start/hardware.jd
+++ b/docs/html/training/tv/start/hardware.jd
@@ -227,13 +227,19 @@ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION)
</tr>
<tr>
<td>{@link android.Manifest.permission#ACCESS_COARSE_LOCATION}</td>
- <td>{@code android.hardware.location} <em>and</em> <br>
- {@code android.hardware.location.network}</td>
+ <td>
+ <p>{@code android.hardware.location}</p>
+ <p>{@code android.hardware.location.network} (Target API level 20 or lower
+ only.)</p>
+ </td>
</tr>
<tr>
<td>{@link android.Manifest.permission#ACCESS_FINE_LOCATION}</td>
- <td>{@code android.hardware.location} <em>and</em> <br>
- {@code android.hardware.location.gps}</td>
+ <td>
+ <p>{@code android.hardware.location}</p>
+ <p>{@code android.hardware.location.gps} (Target API level 20 or lower
+ only.)</p>
+ </td>
</tr>
</table>
@@ -246,6 +252,13 @@ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION)
required ({@code android:required="false"}).
</p>
+<p class="note">
+ <strong>Note:</strong> If your app targets Android 5.0 (API level 21) or
+ higher and uses the <code>ACCESS_COARSE_LOCATION</code> or
+ <code>ACCESS_FINE_LOCATION</code> permission, users can still install your
+ app on a TV device, even if the TV device doesn't have a network card or a GPS
+ receiver.
+</p>
<h3 id="check-features">Checking for hardware features</h2>
diff --git a/docs/image_sources/training/tv/playback/onboarding-fragment-diagram.graffle.zip b/docs/image_sources/training/tv/playback/onboarding-fragment-diagram.graffle.zip
new file mode 100644
index 000000000000..89a799bb57c3
--- /dev/null
+++ b/docs/image_sources/training/tv/playback/onboarding-fragment-diagram.graffle.zip
Binary files differ
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 366ef716c109..74b474eef371 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -3,6 +3,7 @@ include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
HWUI_NEW_OPS := true
+BUGREPORT_FONT_CACHE_USAGE := true
# Enables fine-grained GLES error checking
# If set to true, every GLES call is wrapped & error checked
@@ -135,6 +136,13 @@ ifeq (true, $(HWUI_NEW_OPS))
endif
+ifeq (true, $(BUGREPORT_FONT_CACHE_USAGE))
+ hwui_src_files += \
+ font/FontCacheHistoryTracker.cpp
+ hwui_cflags += -DBUGREPORT_FONT_CACHE_USAGE
+endif
+
+
ifndef HWUI_COMPILE_SYMBOLS
hwui_cflags += -fvisibility=hidden
endif
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 949ad450d5f7..a8ced9b2597b 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -21,6 +21,9 @@
#include "Properties.h"
#include "renderstate/RenderState.h"
#include "ShadowTessellator.h"
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+#include "font/FontCacheHistoryTracker.h"
+#endif
#include "utils/GLUtils.h"
#include <cutils/properties.h>
@@ -195,12 +198,7 @@ void Caches::dumpMemoryUsage(String8 &log) {
log.appendFormat(" PatchCache %8d / %8d\n",
patchCache.getSize(), patchCache.getMaxSize());
- const uint32_t sizeA8 = fontRenderer.getFontRendererSize(GL_ALPHA);
- const uint32_t sizeRGBA = fontRenderer.getFontRendererSize(GL_RGBA);
- log.appendFormat(" FontRenderer A8 %8d / %8d\n", sizeA8, sizeA8);
- log.appendFormat(" FontRenderer RGBA %8d / %8d\n", sizeRGBA, sizeRGBA);
- log.appendFormat(" FontRenderer total %8d / %8d\n", sizeA8 + sizeRGBA,
- sizeA8 + sizeRGBA);
+ fontRenderer.dumpMemoryUsage(log);
log.appendFormat("Other:\n");
log.appendFormat(" FboCache %8d / %8d\n",
@@ -213,11 +211,14 @@ void Caches::dumpMemoryUsage(String8 &log) {
total += tessellationCache.getSize();
total += dropShadowCache.getSize();
total += patchCache.getSize();
- total += fontRenderer.getFontRendererSize(GL_ALPHA);
- total += fontRenderer.getFontRendererSize(GL_RGBA);
+ total += fontRenderer.getSize();
log.appendFormat("Total memory usage:\n");
log.appendFormat(" %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
+
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+ fontRenderer.getFontRenderer().historyTracker().dump(log);
+#endif
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 276c18d0d3f9..681cf55066b4 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -168,10 +168,17 @@ void FontRenderer::flushAllAndInvalidate() {
for (uint32_t i = 0; i < mACacheTextures.size(); i++) {
mACacheTextures[i]->init();
+
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+ mHistoryTracker.glyphsCleared(mACacheTextures[i]);
+#endif
}
for (uint32_t i = 0; i < mRGBACacheTextures.size(); i++) {
mRGBACacheTextures[i]->init();
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+ mHistoryTracker.glyphsCleared(mRGBACacheTextures[i]);
+#endif
}
mDrawn = false;
@@ -183,6 +190,9 @@ void FontRenderer::flushLargeCaches(std::vector<CacheTexture*>& cacheTextures) {
CacheTexture* cacheTexture = cacheTextures[i];
if (cacheTexture->getPixelBuffer()) {
cacheTexture->init();
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+ mHistoryTracker.glyphsCleared(cacheTexture);
+#endif
LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts);
while (it.next()) {
it.value()->invalidateTextureCache(cacheTexture);
@@ -385,6 +395,10 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
}
cachedGlyph->mIsValid = true;
+
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+ mHistoryTracker.glyphUploaded(cacheTexture, startX, startY, glyph.fWidth, glyph.fHeight);
+#endif
}
CacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format,
@@ -747,19 +761,68 @@ static uint32_t calculateCacheSize(const std::vector<CacheTexture*>& cacheTextur
return size;
}
-uint32_t FontRenderer::getCacheSize(GLenum format) const {
+static uint32_t calculateFreeCacheSize(const std::vector<CacheTexture*>& cacheTextures) {
+ uint32_t size = 0;
+ for (uint32_t i = 0; i < cacheTextures.size(); i++) {
+ CacheTexture* cacheTexture = cacheTextures[i];
+ if (cacheTexture && cacheTexture->getPixelBuffer()) {
+ size += cacheTexture->calculateFreeMemory();
+ }
+ }
+ return size;
+}
+
+const std::vector<CacheTexture*>& FontRenderer::cacheTexturesForFormat(GLenum format) const {
switch (format) {
case GL_ALPHA: {
- return calculateCacheSize(mACacheTextures);
+ return mACacheTextures;
}
case GL_RGBA: {
- return calculateCacheSize(mRGBACacheTextures);
+ return mRGBACacheTextures;
}
default: {
- return 0;
+ LOG_ALWAYS_FATAL("Unsupported format: %d", format);
+ // Impossible to hit this, but the compiler doesn't know that
+ return *(new std::vector<CacheTexture*>());
}
}
}
+static void dumpTextures(String8& log, const char* tag,
+ const std::vector<CacheTexture*>& cacheTextures) {
+ for (uint32_t i = 0; i < cacheTextures.size(); i++) {
+ CacheTexture* cacheTexture = cacheTextures[i];
+ if (cacheTexture && cacheTexture->getPixelBuffer()) {
+ uint32_t free = cacheTexture->calculateFreeMemory();
+ uint32_t total = cacheTexture->getPixelBuffer()->getSize();
+ log.appendFormat(" %-4s texture %d %8d / %8d\n", tag, i, total - free, total);
+ }
+ }
+}
+
+void FontRenderer::dumpMemoryUsage(String8& log) const {
+ const uint32_t sizeA8 = getCacheSize(GL_ALPHA);
+ const uint32_t usedA8 = sizeA8 - getFreeCacheSize(GL_ALPHA);
+ const uint32_t sizeRGBA = getCacheSize(GL_RGBA);
+ const uint32_t usedRGBA = sizeRGBA - getFreeCacheSize(GL_RGBA);
+ log.appendFormat(" FontRenderer A8 %8d / %8d\n", usedA8, sizeA8);
+ dumpTextures(log, "A8", cacheTexturesForFormat(GL_ALPHA));
+ log.appendFormat(" FontRenderer RGBA %8d / %8d\n", usedRGBA, sizeRGBA);
+ dumpTextures(log, "RGBA", cacheTexturesForFormat(GL_RGBA));
+ log.appendFormat(" FontRenderer total %8d / %8d\n", usedA8 + usedRGBA, sizeA8 + sizeRGBA);
+}
+
+uint32_t FontRenderer::getCacheSize(GLenum format) const {
+ return calculateCacheSize(cacheTexturesForFormat(format));
+}
+
+uint32_t FontRenderer::getFreeCacheSize(GLenum format) const {
+ return calculateFreeCacheSize(cacheTexturesForFormat(format));
+}
+
+uint32_t FontRenderer::getSize() const {
+ return getCacheSize(GL_ALPHA) + getCacheSize(GL_RGBA);
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index e10a81b8ccd8..504dce862f71 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -21,8 +21,12 @@
#include "font/CacheTexture.h"
#include "font/CachedGlyphInfo.h"
#include "font/Font.h"
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+#include "font/FontCacheHistoryTracker.h"
+#endif
#include <utils/LruCache.h>
+#include <utils/String8.h>
#include <utils/StrongPointer.h>
#include <SkPaint.h>
@@ -132,7 +136,12 @@ public:
mLinearFiltering = linearFiltering;
}
- uint32_t getCacheSize(GLenum format) const;
+ uint32_t getSize() const;
+ void dumpMemoryUsage(String8& log) const;
+
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+ FontCacheHistoryTracker& historyTracker() { return mHistoryTracker; }
+#endif
private:
friend class Font;
@@ -175,6 +184,10 @@ private:
mUploadTexture = true;
}
+ const std::vector<CacheTexture*>& cacheTexturesForFormat(GLenum format) const;
+ uint32_t getCacheSize(GLenum format) const;
+ uint32_t getFreeCacheSize(GLenum format) const;
+
uint32_t mSmallCacheWidth;
uint32_t mSmallCacheHeight;
uint32_t mLargeCacheWidth;
@@ -199,6 +212,10 @@ private:
bool mLinearFiltering;
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+ FontCacheHistoryTracker mHistoryTracker;
+#endif
+
#ifdef ANDROID_ENABLE_RENDERSCRIPT
// RS constructs
RSC::sp<RSC::RS> mRs;
diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h
index 5813e7f717ee..bd27a1a72060 100644
--- a/libs/hwui/GammaFontRenderer.h
+++ b/libs/hwui/GammaFontRenderer.h
@@ -22,6 +22,8 @@
#include <SkPaint.h>
+#include <utils/String8.h>
+
namespace android {
namespace uirenderer {
@@ -46,8 +48,16 @@ public:
return *mRenderer;
}
- uint32_t getFontRendererSize(GLenum format) const {
- return mRenderer ? mRenderer->getCacheSize(format) : 0;
+ void dumpMemoryUsage(String8& log) const {
+ if (mRenderer) {
+ mRenderer->dumpMemoryUsage(log);
+ } else {
+ log.appendFormat("FontRenderer doesn't exist.\n");
+ }
+ }
+
+ uint32_t getSize() const {
+ return mRenderer ? mRenderer->getSize() : 0;
}
void endPrecaching();
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index ce67554645d1..c7289fce1fbf 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -329,9 +329,10 @@ void SkiaCanvas::restoreToCount(int restoreCount) {
static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) {
SkCanvas::SaveLayerFlags layerFlags = 0;
- if (!(flags & SaveFlags::HasAlphaLayer)) {
- layerFlags |= SkCanvas::kIsOpaque_SaveLayerFlag;
- }
+ // We intentionally ignore the SaveFlags::HasAlphaLayer and
+ // SkCanvas::kIsOpaque_SaveLayerFlag flags because HWUI ignores it
+ // and our Android client may use it incorrectly.
+ // In Skia, this flag is purely for performance optimization.
if (!(flags & SaveFlags::ClipToLayer)) {
layerFlags |= SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag;
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
index 8ba4761c1b2e..4b13814bfdc6 100644
--- a/libs/hwui/font/CacheTexture.cpp
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -324,5 +324,17 @@ bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_
return false;
}
+uint32_t CacheTexture::calculateFreeMemory() const {
+ CacheBlock* cacheBlock = mCacheBlocks;
+ uint32_t free = 0;
+ // currently only two formats are supported: GL_ALPHA or GL_RGBA;
+ uint32_t bpp = mFormat == GL_RGBA ? 4 : 1;
+ while (cacheBlock) {
+ free += bpp * cacheBlock->mWidth * cacheBlock->mHeight;
+ cacheBlock = cacheBlock->mNext;
+ }
+ return free;
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h
index 4dfb41dafcc7..6750a8ae11cf 100644
--- a/libs/hwui/font/CacheTexture.h
+++ b/libs/hwui/font/CacheTexture.h
@@ -178,6 +178,8 @@ public:
return mCurrentQuad == mMaxQuadCount;
}
+ uint32_t calculateFreeMemory() const;
+
private:
void setDirty(bool dirty);
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 8e04c8715f62..a95454a4c010 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -408,9 +408,15 @@ void Font::render(const SkPaint* paint, const glyph_t* glyphs,
if (cachedGlyph->mIsValid && cachedGlyph->mCacheTexture) {
int penX = x + (int) roundf(positions[(glyphsCount << 1)]);
int penY = y + (int) roundf(positions[(glyphsCount << 1) + 1]);
-
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+ mState->historyTracker().glyphRendered(cachedGlyph, penX, penY);
+#endif
(*this.*render)(cachedGlyph, penX, penY,
bitmap, bitmapW, bitmapH, bounds, positions);
+ } else {
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+ mState->historyTracker().glyphRendered(cachedGlyph, -1, -1);
+#endif
}
glyphsCount++;
diff --git a/libs/hwui/font/FontCacheHistoryTracker.cpp b/libs/hwui/font/FontCacheHistoryTracker.cpp
new file mode 100644
index 000000000000..a2bfb27535e5
--- /dev/null
+++ b/libs/hwui/font/FontCacheHistoryTracker.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FontCacheHistoryTracker.h"
+
+#include "CachedGlyphInfo.h"
+#include "CacheTexture.h"
+
+namespace android {
+namespace uirenderer {
+
+void FontCacheHistoryTracker::dumpCachedGlyph(String8& log, const CachedGlyph& glyph) {
+ log.appendFormat("glyph (texture %p, position: (%d, %d), size: %dx%d, gen: %d)", glyph.texture,
+ glyph.startX, glyph.startY, glyph.bitmapW, glyph.bitmapH, glyph.generation);
+}
+
+void FontCacheHistoryTracker::dumpRenderEntry(String8& log, const RenderEntry& entry) {
+ if (entry.penX == -1 && entry.penY == -1) {
+ log.appendFormat(" glyph skipped in gen: %d\n", entry.glyph.generation);
+ } else {
+ log.appendFormat(" rendered ");
+ dumpCachedGlyph(log, entry.glyph);
+ log.appendFormat(" at (%d, %d)\n", entry.penX, entry.penY);
+ }
+}
+
+void FontCacheHistoryTracker::dumpUploadEntry(String8& log, const CachedGlyph& glyph) {
+ if (glyph.bitmapW == 0 && glyph.bitmapH == 0) {
+ log.appendFormat(" cleared cachetexture %p in gen %d\n", glyph.texture,
+ glyph.generation);
+ } else {
+ log.appendFormat(" uploaded ");
+ dumpCachedGlyph(log, glyph);
+ log.appendFormat("\n");
+ }
+}
+
+void FontCacheHistoryTracker::dump(String8& log) const {
+ log.appendFormat("FontCacheHistory: \n");
+ log.appendFormat(" Upload history: \n");
+ for (size_t i = 0; i < mUploadHistory.size(); i++) {
+ dumpUploadEntry(log, mUploadHistory[i]);
+ }
+ log.appendFormat(" Render history: \n");
+ for (size_t i = 0; i < mRenderHistory.size(); i++) {
+ dumpRenderEntry(log, mRenderHistory[i]);
+ }
+}
+
+void FontCacheHistoryTracker::glyphRendered(CachedGlyphInfo* glyphInfo, int penX, int penY) {
+ RenderEntry& entry = mRenderHistory.next();
+ entry.glyph.generation = generation;
+ entry.glyph.texture = glyphInfo->mCacheTexture;
+ entry.glyph.startX = glyphInfo->mStartX;
+ entry.glyph.startY = glyphInfo->mStartY;
+ entry.glyph.bitmapW = glyphInfo->mBitmapWidth;
+ entry.glyph.bitmapH = glyphInfo->mBitmapHeight;
+ entry.penX = penX;
+ entry.penY = penY;
+}
+
+void FontCacheHistoryTracker::glyphUploaded(CacheTexture* texture, uint32_t x, uint32_t y,
+ uint16_t glyphW, uint16_t glyphH) {
+ CachedGlyph& glyph = mUploadHistory.next();
+ glyph.generation = generation;
+ glyph.texture = texture;
+ glyph.startX = x;
+ glyph.startY = y;
+ glyph.bitmapW = glyphW;
+ glyph.bitmapH = glyphH;
+}
+
+void FontCacheHistoryTracker::glyphsCleared(CacheTexture* texture) {
+ CachedGlyph& glyph = mUploadHistory.next();
+ glyph.generation = generation;
+ glyph.texture = texture;
+ glyph.startX = 0;
+ glyph.startY = 0;
+ glyph.bitmapW = 0;
+ glyph.bitmapH = 0;
+}
+
+void FontCacheHistoryTracker::frameCompleted() {
+ generation++;
+}
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/font/FontCacheHistoryTracker.h b/libs/hwui/font/FontCacheHistoryTracker.h
new file mode 100644
index 000000000000..f1d9b9f10dc0
--- /dev/null
+++ b/libs/hwui/font/FontCacheHistoryTracker.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include "../utils/RingBuffer.h"
+
+#include <utils/String8.h>
+
+namespace android {
+namespace uirenderer {
+
+class CacheTexture;
+struct CachedGlyphInfo;
+
+// Tracks glyph uploads and recent rendered/skipped glyphs, so it can give an idea
+// what a missing character is: skipped glyph, wrong coordinates in cache texture etc.
+class FontCacheHistoryTracker {
+public:
+ void glyphRendered(CachedGlyphInfo*, int penX, int penY);
+ void glyphUploaded(CacheTexture*, uint32_t x, uint32_t y, uint16_t glyphW, uint16_t glyphH);
+ void glyphsCleared(CacheTexture*);
+ void frameCompleted();
+
+ void dump(String8& log) const;
+private:
+ struct CachedGlyph {
+ void* texture;
+ uint16_t generation;
+ uint16_t startX;
+ uint16_t startY;
+ uint16_t bitmapW;
+ uint16_t bitmapH;
+ };
+
+ struct RenderEntry {
+ CachedGlyph glyph;
+ int penX;
+ int penY;
+ };
+
+ static void dumpCachedGlyph(String8& log, const CachedGlyph& glyph);
+ static void dumpRenderEntry(String8& log, const RenderEntry& entry);
+ static void dumpUploadEntry(String8& log, const CachedGlyph& glyph);
+
+ RingBuffer<RenderEntry, 300> mRenderHistory;
+ RingBuffer<CachedGlyph, 120> mUploadHistory;
+ uint16_t generation = 0;
+};
+
+}; // namespace uirenderer
+}; // namespace android \ No newline at end of file
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 70b9a436dee2..975ac8368e3d 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -608,6 +608,10 @@ void CanvasContext::draw() {
}
GpuMemoryTracker::onFrameCompleted();
+#ifdef BUGREPORT_FONT_CACHE_USAGE
+ caches.fontRenderer.getFontRenderer().historyTracker().frameCompleted();
+#endif
+
}
// Called by choreographer to do an RT-driven animation
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 5286f8fa5ad3..89709ee6b95a 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -24,6 +24,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseIntArray;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -170,6 +171,66 @@ public final class AudioAttributes implements Parcelable {
public final static int USAGE_VIRTUAL_SOURCE = 15;
/**
+ * IMPORTANT: when adding new usage types, add them to SDK_USAGES and update SUPPRESSIBLE_USAGES
+ * if applicable.
+ */
+
+ /**
+ * @hide
+ * Denotes a usage for notifications that do not expect immediate intervention from the user,
+ * will be muted when the Zen mode disables notifications
+ * @see #SUPPRESSIBLE_USAGES
+ */
+ public final static int SUPPRESSIBLE_NOTIFICATION = 1;
+ /**
+ * @hide
+ * Denotes a usage for notifications that do expect immediate intervention from the user,
+ * will be muted when the Zen mode disables calls
+ * @see #SUPPRESSIBLE_USAGES
+ */
+ public final static int SUPPRESSIBLE_CALL = 2;
+
+ /**
+ * @hide
+ * Array of all usage types for calls and notifications to assign the suppression behavior,
+ * used by the Zen mode restrictions.
+ * @see com.android.server.notification.ZenModeHelper
+ */
+ public static final SparseIntArray SUPPRESSIBLE_USAGES;
+
+ static {
+ SUPPRESSIBLE_USAGES = new SparseIntArray();
+ SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION, SUPPRESSIBLE_NOTIFICATION);
+ SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_RINGTONE, SUPPRESSIBLE_CALL);
+ SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_REQUEST,SUPPRESSIBLE_CALL);
+ SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION);
+ SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION);
+ SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, SUPPRESSIBLE_NOTIFICATION);
+ }
+
+ /**
+ * @hide
+ * Array of all usage types exposed in the SDK that applications can use.
+ */
+ public final static int[] SDK_USAGES = {
+ USAGE_UNKNOWN,
+ USAGE_MEDIA,
+ USAGE_VOICE_COMMUNICATION,
+ USAGE_VOICE_COMMUNICATION_SIGNALLING,
+ USAGE_ALARM,
+ USAGE_NOTIFICATION,
+ USAGE_NOTIFICATION_RINGTONE,
+ USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
+ USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
+ USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
+ USAGE_NOTIFICATION_EVENT,
+ USAGE_ASSISTANCE_ACCESSIBILITY,
+ USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ USAGE_ASSISTANCE_SONIFICATION,
+ USAGE_GAME
+ };
+
+ /**
* Flag defining a behavior where the audibility of the sound will be ensured by the system.
*/
public final static int FLAG_AUDIBILITY_ENFORCED = 0x1 << 0;
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 2cbeb3a260be..ed718493bd78 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -241,6 +241,10 @@ public class ImageReader implements AutoCloseable {
* same {@link Surface} can be reused with a different API once the first source is
* disconnected from the {@link Surface}.</p>
*
+ * <p>Please note that holding on to the Surface object returned by this method is not enough
+ * to keep its parent ImageReader from being reclaimed. In that sense, a Surface acts like a
+ * {@link java.lang.ref.WeakReference weak reference} to the ImageReader that provides it.</p>
+ *
* @return A {@link Surface} to use for a drawing target for various APIs.
*/
public Surface getSurface() {
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 6f5199b6959c..c8aedd09d60c 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -496,6 +496,11 @@ final public class MediaExtractor {
/**
* Advance to the next sample. Returns false if no more sample data
* is available (end of stream).
+ *
+ * When extracting a local file, the behaviors of {@link #advance} and
+ * {@link #readSampleData} are undefined in presence of concurrent
+ * writes to the same local file; more specifically, end of stream
+ * could be signalled earlier than expected.
*/
public native boolean advance();
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 31c7a3249542..e5f7527c9db2 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1641,7 +1641,8 @@ public class MediaPlayer extends PlayerBase
* (i.e. reaches the end of the stream).
* The media framework will attempt to transition from this player to
* the next as seamlessly as possible. The next player can be set at
- * any time before completion. The next player must be prepared by the
+ * any time before completion, but shall be after setDataSource has been
+ * called successfully. The next player must be prepared by the
* app, and the application should not call start() on it.
* The next MediaPlayer must be different from 'this'. An exception
* will be thrown if next == this.
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index c8ab5f9bc429..0fafe4b19a42 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -21,12 +21,14 @@ import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.SQLException;
import android.drm.DrmManagerClient;
import android.graphics.BitmapFactory;
import android.mtp.MtpConstants;
import android.net.Uri;
+import android.os.Build;
import android.os.Environment;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -153,6 +155,11 @@ public class MediaScanner implements AutoCloseable {
private static final String MUSIC_DIR = "/music/";
private static final String PODCAST_DIR = "/podcasts/";
+ public static final String SCANNED_BUILD_PREFS_NAME = "MediaScanBuild";
+ public static final String LAST_INTERNAL_SCAN_FINGERPRINT = "lastScanFingerprint";
+ private static final String SYSTEM_SOUNDS_DIR = "/system/media/audio";
+ private static String sLastInternalScanFingerprint;
+
private static final String[] ID3_GENRES = {
// ID3v1 Genres
"Blues",
@@ -402,6 +409,13 @@ public class MediaScanner implements AutoCloseable {
mMediaProvider = mContext.getContentResolver()
.acquireContentProviderClient(MediaStore.AUTHORITY);
+ if (sLastInternalScanFingerprint == null) {
+ final SharedPreferences scanSettings =
+ mContext.getSharedPreferences(SCANNED_BUILD_PREFS_NAME, Context.MODE_PRIVATE);
+ sLastInternalScanFingerprint =
+ scanSettings.getString(LAST_INTERNAL_SCAN_FINGERPRINT, new String());
+ }
+
mAudioUri = Audio.Media.getContentUri(volumeName);
mVideoUri = Video.Media.getContentUri(volumeName);
mImagesUri = Images.Media.getContentUri(volumeName);
@@ -585,16 +599,24 @@ public class MediaScanner implements AutoCloseable {
entry.mRowId = 0;
}
- if (entry.mPath != null &&
- ((!mDefaultNotificationSet &&
+ if (entry.mPath != null) {
+ if (((!mDefaultNotificationSet &&
doesPathHaveFilename(entry.mPath, mDefaultNotificationFilename))
|| (!mDefaultRingtoneSet &&
doesPathHaveFilename(entry.mPath, mDefaultRingtoneFilename))
|| (!mDefaultAlarmSet &&
doesPathHaveFilename(entry.mPath, mDefaultAlarmAlertFilename)))) {
- Log.w(TAG, "forcing rescan of " + entry.mPath +
- "since ringtone setting didn't finish");
- scanAlways = true;
+ Log.w(TAG, "forcing rescan of " + entry.mPath +
+ "since ringtone setting didn't finish");
+ scanAlways = true;
+ } else if (isSystemSoundWithMetadata(entry.mPath)
+ && !Build.FINGERPRINT.equals(sLastInternalScanFingerprint)) {
+ // file is located on the system partition where the date cannot be trusted:
+ // rescan if the build fingerprint has changed since the last scan.
+ Log.i(TAG, "forcing rescan of " + entry.mPath
+ + " since build fingerprint changed");
+ scanAlways = true;
+ }
}
// rescan for metadata if file was modified since last scan
@@ -1128,6 +1150,15 @@ public class MediaScanner implements AutoCloseable {
}; // end of anonymous MediaScannerClient instance
+ private static boolean isSystemSoundWithMetadata(String path) {
+ if (path.startsWith(SYSTEM_SOUNDS_DIR + ALARMS_DIR)
+ || path.startsWith(SYSTEM_SOUNDS_DIR + RINGTONES_DIR)
+ || path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR)) {
+ return true;
+ }
+ return false;
+ }
+
private String settingSetIndicatorName(String base) {
return base + "_set";
}
@@ -1252,16 +1283,6 @@ public class MediaScanner implements AutoCloseable {
}
}
- private boolean inScanDirectory(String path, String[] directories) {
- for (int i = 0; i < directories.length; i++) {
- String directory = directories[i];
- if (path.startsWith(directory)) {
- return true;
- }
- }
- return false;
- }
-
private void pruneDeadThumbnailFiles() {
HashSet<String> existingFiles = new HashSet<String>();
String directory = "/sdcard/DCIM/.thumbnails";
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index f1a8c6fbdb29..aec31f0479c2 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -435,11 +435,12 @@ setup_failure:
// ----------------------------------------------------------------------------
static void android_media_visualizer_native_release(JNIEnv *env, jobject thiz) {
- sp<Visualizer> lpVisualizer = setVisualizer(env, thiz, 0);
- if (lpVisualizer == 0) {
- return;
+ { //limit scope so that lpVisualizer is deleted before JNI storage data.
+ sp<Visualizer> lpVisualizer = setVisualizer(env, thiz, 0);
+ if (lpVisualizer == 0) {
+ return;
+ }
}
-
// delete the JNI data
VisualizerJniStorage* lpJniStorage =
(VisualizerJniStorage *)env->GetLongField(thiz, fields.fidJniData);
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
index 32e335843016..808ec361fb4f 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
@@ -102,6 +102,14 @@ public class NekoService extends JobService {
return false;
}
+ public static void registerJobIfNeeded(Context context, long intervalMinutes) {
+ JobScheduler jss = context.getSystemService(JobScheduler.class);
+ JobInfo info = jss.getPendingJob(JOB_ID);
+ if (info == null) {
+ registerJob(context, intervalMinutes);
+ }
+ }
+
public static void registerJob(Context context, long intervalMinutes) {
JobScheduler jss = context.getSystemService(JobScheduler.class);
jss.cancel(JOB_ID);
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java b/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java
index 8a3ec8fa19e9..159b40a3e5af 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java
@@ -68,6 +68,9 @@ public class NekoTile extends TileService implements PrefsListener {
Tile tile = getQsTile();
int foodState = mPrefs.getFoodState();
Food food = new Food(foodState);
+ if (foodState != 0) {
+ NekoService.registerJobIfNeeded(this, food.getInterval(this));
+ }
tile.setIcon(food.getIcon(this));
tile.setLabel(food.getName(this));
tile.setState(foodState != 0 ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
diff --git a/packages/EasterEgg/src/com/android/egg/neko/PrefState.java b/packages/EasterEgg/src/com/android/egg/neko/PrefState.java
index 5f54180bc2e0..bf71b197d3cb 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/PrefState.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/PrefState.java
@@ -43,13 +43,11 @@ public class PrefState implements OnSharedPreferenceChangeListener {
public void addCat(Cat cat) {
mPrefs.edit()
.putString(CAT_KEY_PREFIX + String.valueOf(cat.getSeed()), cat.getName())
- .commit();
+ .apply();
}
public void removeCat(Cat cat) {
- mPrefs.edit()
- .remove(CAT_KEY_PREFIX + String.valueOf(cat.getSeed()))
- .commit();
+ mPrefs.edit().remove(CAT_KEY_PREFIX + String.valueOf(cat.getSeed())).apply();
}
public List<Cat> getCats() {
@@ -71,7 +69,7 @@ public class PrefState implements OnSharedPreferenceChangeListener {
}
public void setFoodState(int foodState) {
- mPrefs.edit().putInt(FOOD_STATE, foodState).commit();
+ mPrefs.edit().putInt(FOOD_STATE, foodState).apply();
}
public void setListener(PrefsListener listener) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index e169c0d072db..dccb1a921489 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -141,6 +141,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private static final int MSG_SERVICE_STATE_CHANGE = 330;
private static final int MSG_SCREEN_TURNED_ON = 331;
private static final int MSG_SCREEN_TURNED_OFF = 332;
+ private static final int MSG_DREAMING_STATE_CHANGED = 333;
/** Fingerprint state: Not listening to fingerprint. */
private static final int FINGERPRINT_STATE_STOPPED = 0;
@@ -293,6 +294,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
handleScreenTurnedOff();
Trace.endSection();
break;
+ case MSG_DREAMING_STATE_CHANGED:
+ handleDreamingStateChanged(msg.arg1);
+ break;
}
}
};
@@ -990,6 +994,17 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
+ private void handleDreamingStateChanged(int dreamStart) {
+ final int count = mCallbacks.size();
+ boolean showingDream = dreamStart == 1;
+ for (int i = 0; i < count; i++) {
+ KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+ if (cb != null) {
+ cb.onDreamingStateChanged(showingDream);
+ }
+ }
+ }
+
/**
* IMPORTANT: Must be called from UI thread.
*/
@@ -1736,6 +1751,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_OFF);
}
+ public void dispatchDreamingStarted() {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_DREAMING_STATE_CHANGED, 1, 0));
+ }
+
+ public void dispatchDreamingStopped() {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_DREAMING_STATE_CHANGED, 0, 0));
+ }
+
public boolean isDeviceInteractive() {
return mDeviceInteractive;
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 4a2d356b6ddd..eb29d9b550e3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -245,4 +245,10 @@ public class KeyguardUpdateMonitorCallback {
* Called when the state whether we have a lockscreen wallpaper has changed.
*/
public void onHasLockscreenWallpaperChanged(boolean hasLockscreenWallpaper) { }
+
+ /**
+ * Called when the dream's window state is changed.
+ * @param dreaming true if the dream's window has been created and is visible
+ */
+ public void onDreamingStateChanged(boolean dreaming) { }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index 0e3e0d584e97..5c577f8aa83c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -126,6 +126,13 @@ public class StorageMeasurement {
* internal storage. Key is {@link UserHandle}.
*/
public SparseLongArray usersSize = new SparseLongArray();
+
+ @Override
+ public String toString() {
+ return "MeasurementDetails: [totalSize: " + totalSize + " availSize: " + availSize
+ + " cacheSize: " + cacheSize + " mediaSize: " + mediaSize
+ + " miscSize: " + miscSize + "usersSize: " + usersSize + "]";
+ }
}
public interface MeasurementReceiver {
@@ -435,7 +442,7 @@ public class StorageMeasurement {
private static long getDirectorySize(IMediaContainerService imcs, File path) {
try {
final long size = imcs.calculateDirectorySize(path.toString());
- Log.d(TAG, "getDirectorySize(" + path + ") returned " + size);
+ if (LOGV) Log.v(TAG, "getDirectorySize(" + path + ") returned " + size);
return size;
} catch (Exception e) {
Log.w(TAG, "Could not read memory from default container service for " + path, e);
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 458672a41b77..e6e0243c53e1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -32,6 +32,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.support.v4.widget.DrawerLayout;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
@@ -58,6 +59,7 @@ public class SettingsDrawerActivity extends Activity {
protected static final boolean DEBUG_TIMING = false;
private static final String TAG = "SettingsDrawerActivity";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final String EXTRA_SHOW_MENU = "show_drawer_menu";
@@ -111,7 +113,7 @@ public class SettingsDrawerActivity extends Activity {
public void onItemClick(android.widget.AdapterView<?> parent, View view, int position,
long id) {
onTileClicked(mDrawerAdapter.getTile(position));
- };
+ }
});
mUserManager = UserManager.get(this);
@@ -143,8 +145,16 @@ public class SettingsDrawerActivity extends Activity {
new CategoriesUpdater().execute();
}
- if (getIntent() != null && getIntent().getBooleanExtra(EXTRA_SHOW_MENU, false)) {
- showMenuIcon();
+ final Intent intent = getIntent();
+ if (intent != null) {
+ if (intent.hasExtra(EXTRA_SHOW_MENU)) {
+ if (intent.getBooleanExtra(EXTRA_SHOW_MENU, false)) {
+ // Intent explicitly set to show menu.
+ showMenuIcon();
+ }
+ } else if (isTopLevelTile(intent)) {
+ showMenuIcon();
+ }
}
}
@@ -157,6 +167,30 @@ public class SettingsDrawerActivity extends Activity {
super.onPause();
}
+ private boolean isTopLevelTile(Intent intent) {
+ final ComponentName componentName = intent.getComponent();
+ if (componentName == null) {
+ return false;
+ }
+ // Look for a tile that has the same component as incoming intent
+ final List<DashboardCategory> categories = getDashboardCategories();
+ for (DashboardCategory category : categories) {
+ for (Tile tile : category.tiles) {
+ if (TextUtils.equals(tile.intent.getComponent().getClassName(),
+ componentName.getClassName())) {
+ if (DEBUG) {
+ Log.d(TAG, "intent is for top level tile: " + tile.title);
+ }
+ return true;
+ }
+ }
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Intent is not for top level settings " + intent);
+ }
+ return false;
+ }
+
public void addCategoryListener(CategoryListener listener) {
mCategoryListeners.add(listener);
}
@@ -287,9 +321,9 @@ public class SettingsDrawerActivity extends Activity {
private void updateUserHandlesIfNeeded(Tile tile) {
List<UserHandle> userHandles = tile.userHandle;
- for (int i = userHandles.size()-1; i >= 0; i--) {
+ for (int i = userHandles.size() - 1; i >= 0; i--) {
if (mUserManager.getUserInfo(userHandles.get(i).getIdentifier()) == null) {
- if (DEBUG_TIMING) {
+ if (DEBUG) {
Log.d(TAG, "Delete the user: " + userHandles.get(i).getIdentifier());
}
userHandles.remove(i);
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
index f63dfb12e203..b78d3bf1c35d 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_0.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,17 +15,15 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="32dp"
- android:height="32dp"
+ android:width="32.0dp"
+ android:height="32.0dp"
android:viewportWidth="24.0"
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="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+ android:fillAlpha="0.3"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
- <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:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+ android:fillColor="#FFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
index 7fb423e5fc84..e055de77ebe5 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_1.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,20 +15,18 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="32dp"
- android:height="32dp"
+ android:width="32.0dp"
+ android:height="32.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/>
+ android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/>
+ android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+ android:fillAlpha="0.3"
+ android:fillColor="#FFFFFF"/>
<path
- 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:fillColor="#FFFFFFFF"
- android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
+ android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+ android:fillColor="#FFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
index 3358d65b68e6..8a488170e438 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_2.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,20 +15,18 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="32dp"
- android:height="32dp"
+ android:width="32.0dp"
+ android:height="32.0dp"
android:viewportWidth="24.0"
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="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+ android:fillAlpha="0.3"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M13.900000,10.000000l-11.900000,12.000000 11.900000,0.000000z"/>
- <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:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+ android:fillColor="#FFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
index 63838a93c686..39cc94cad4db 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_3.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,20 +15,18 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="32dp"
- android:height="32dp"
+ android:width="32.0dp"
+ android:height="32.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.700001,19.900000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+ android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+ android:fillAlpha="0.3"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.700001,9.900000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M16.700001,7.200000l-14.700001,14.700000 14.700001,0.000000z"/>
- <path
- android:pathData="M17.700001,7.900000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
- android:fillColor="#4DFFFFFF"/>
+ android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z"
+ android:fillColor="#FFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
index 76690cc2adce..012e95e985ce 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,17 +15,14 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="32dp"
- android:height="32dp"
+ android:width="32.0dp"
+ android:height="32.0dp"
android:viewportWidth="24.0"
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="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M2.000000,22.000000l15.700001,0.000000 0.000000,-14.000000 4.299999,0.000000 0.000000,-6.000000z"/>
+ android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+ android:fillColor="#FFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
index 50c427e24c9b..e6f929265709 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_0.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,17 +14,15 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32.0dp"
- android:height="29.5dp"
- android:viewportWidth="26.0"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#4DFFFFFF"
- android:pathData="M19.000000,8.000000l5.300000,0.000000l1.200000,-1.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillAlpha="0.3"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
+ android:fillColor="#FFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
index a2d11a09aab8..d423ccb2d5e2 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_1.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,20 +14,18 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32.0dp"
- android:height="29.5dp"
- android:viewportWidth="26.0"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#4DFFFFFF"
- android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+ android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M13.000000,22.000000l5.500000,-6.800000c-0.200000,-0.200000 -2.300000,-1.900000 -5.500000,-1.900000s-5.300000,1.800000 -5.500000,1.900000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillAlpha="0.3"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
+ android:fillColor="#FFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
index f2043fc4bcaf..1982130fb1c6 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_2.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,20 +14,18 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32.0dp"
- android:height="29.5dp"
- android:viewportWidth="26.0"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#4DFFFFFF"
- android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+ android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.000000,11.600000c-1.300000,-0.700000 -3.400000,-1.600000 -6.000000,-1.600000c-4.400000,0.000000 -7.300000,2.400000 -7.600000,2.700000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,11.600000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillAlpha="0.3"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.800001,1.9 -1.800001,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+ android:fillColor="#FFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
index b7a4f4c81ec8..b35011181a86 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_3.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,20 +14,18 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32.0dp"
- android:height="29.5dp"
- android:viewportWidth="26.0"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#4DFFFFFF"
- android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.000000,8.600000c-1.600000,-0.700000 -3.600000,-1.300000 -6.000000,-1.300000c-5.300000,0.000000 -8.900000,3.000000 -9.200000,3.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.600000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillAlpha="0.3"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+ android:fillColor="#FFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
index 35a9138b31d2..136a00435430 100644
--- a/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_wifi_4.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,17 +14,14 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32.0dp"
- android:height="29.5dp"
- android:viewportWidth="26.0"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillColor="#FFFFFF"/>
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+ android:fillColor="#FFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
index 643c4f919d1b..8bc872a99951 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_0.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,17 +15,14 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="17dp"
- android:height="17dp"
+ android:width="17.0dp"
+ android:height="17.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
- <path
- android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
+ android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
android:fillColor="?attr/backgroundColor"/>
+ <path
+ android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+ android:fillColor="?attr/fillColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
index 64781c367227..8fa7630b0fae 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_1.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,20 +15,17 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="17dp"
- android:height="17dp"
+ android:width="17.0dp"
+ android:height="17.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.7,20.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/>
+ android:pathData="M10.0,14.6l-8.0,8.0l8.0,0.0l0,-8z"
+ android:fillColor="?attr/fillColor"/>
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.7,10.0l2.0,0.0l0.0,8.1l-2.0,0.0z"/>
+ android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+ android:fillColor="?attr/backgroundColor"/>
<path
- android:fillColor="?attr/backgroundColor"
- android:pathData="M17.7,8.0l4.299999,0.0 0.0,-6.0 -20.0,20.0 15.700001,0.0z"/>
- <path
- android:fillColor="?attr/fillColor"
- android:pathData="M10.1,13.9l-8.1,8.1 8.1,0.0z"/>
+ android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+ android:fillColor="?attr/fillColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
index eb2be08af5f1..2a660a39d510 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_2.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,20 +15,17 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="17dp"
- android:height="17dp"
+ android:width="17.0dp"
+ android:height="17.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
+ android:pathData="M14.0,10.6l-12.0,12.0l12.0,0.0L14.0,10.6z"
+ android:fillColor="?attr/fillColor"/>
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
- <path
- android:fillColor="?attr/fillColor"
- android:pathData="M13.900000,10.000000l-11.900000,12.000000 11.900000,0.000000z"/>
- <path
- android:pathData="M17.700001,8.000000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
+ android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
android:fillColor="?attr/backgroundColor"/>
+ <path
+ android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+ android:fillColor="?attr/fillColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
index 22afad085231..9e0a43353eea 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_3.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,20 +15,17 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="17dp"
- android:height="17dp"
+ android:width="17.0dp"
+ android:height="17.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.700001,19.900000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.700001,9.900000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+ android:fillColor="?attr/backgroundColor"/>
<path
- android:fillColor="?attr/fillColor"
- android:pathData="M16.700001,7.200000l-14.700001,14.700000 14.700001,0.000000z"/>
+ android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+ android:fillColor="?attr/fillColor"/>
<path
- android:pathData="M17.700001,7.900000l4.299999,0.000000 0.000000,-6.000000 -20.000000,20.000000 15.700001,0.000000z"
- android:fillColor="?attr/backgroundColor"/>
+ android:pathData="M14.1,14.1l2.9,0.0 0.0,-6.5 -15.0,15.0 12.1,0.0z"
+ android:fillColor="?attr/fillColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
index d1e866dfefb3..01f670311750 100644
--- a/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_signal_4.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,18 +15,14 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="17dp"
- android:height="17dp"
+ android:width="17.0dp"
+ android:height="17.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
-
- <path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.700001,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.700001,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M14.1,14.1l7.9,0.0 0.0,-11.5 -20.0,20.0 12.1,0.0z"
+ android:fillColor="?attr/fillColor"/>
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M2.000000,22.000000l15.700001,0.000000 0.000000,-14.000000 4.299999,0.000000 0.000000,-6.000000z"/>
+ android:pathData="M21.9,17.0l-1.1,-1.1 -1.9,1.9 -1.9,-1.9 -1.1,1.1 1.9,1.9 -1.9,1.9 1.1,1.1 1.9,-1.9 1.9,1.9 1.1,-1.1 -1.9,-1.9z"
+ android:fillColor="?attr/fillColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
index 7f1b715e9a78..2de2e3640879 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_0.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,16 +15,13 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18.41dp"
- android:height="17dp"
- android:viewportWidth="26.0"
+ android:height="18.41dp"
+ android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="?attr/backgroundColor"
- android:pathData="M19.000000,8.000000l5.300000,0.000000l1.200000,-1.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillColor="?attr/backgroundColor"/>
<path
- android:fillColor="?attr/fillColor"
- android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="?attr/fillColor"
- android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
+ android:fillColor="?attr/fillColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
index acd89bea9ea8..144a7c1074e0 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_1.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,19 +15,16 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18.41dp"
- android:height="17dp"
- android:viewportWidth="26.0"
+ android:height="18.41dp"
+ android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="?attr/backgroundColor"
- android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+ android:pathData="M13.8,13.2c-0.1,0.0 -0.3,-0.1 -0.4,-0.1c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,0.0 -0.6,-0.1 -0.9,-0.1c0.0,0.0 0.0,0.0 -0.1,0.0c0.0,0.0 0.0,0.0 0.0,0.0s0.0,0.0 0.0,0.0c0.0,0.0 0.0,0.0 -0.1,0.0c-0.3,0.0 -0.6,0.0 -0.9,0.1c-0.1,0.0 -0.3,0.0 -0.4,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.2,0.0 -0.3,0.1 -0.5,0.1c-0.1,0.0 -0.1,0.0 -0.2,0.1c-1.6,0.5 -2.7,1.3 -2.8,1.5l5.3,6.6l0.0,0.0l0.0,0.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.700002,13.2z"
+ android:fillColor="?attr/fillColor"/>
<path
- android:fillColor="?attr/fillColor"
- android:pathData="M13.000000,22.000000l5.500000,-6.800000c-0.200000,-0.200000 -2.300000,-1.900000 -5.500000,-1.900000s-5.300000,1.800000 -5.500000,1.900000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillColor="?attr/backgroundColor"/>
<path
- android:fillColor="?attr/fillColor"
- android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="?attr/fillColor"
- android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.799999,-1.800001z"
+ android:fillColor="?attr/fillColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
index f33b25c6261b..6b7f71268162 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_2.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,19 +15,16 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18.41dp"
- android:height="17dp"
- android:viewportWidth="26.0"
+ android:height="18.41dp"
+ android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="?attr/backgroundColor"
- android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+ android:pathData="M13.8,12.2l4.9,0.0c-1.0,-0.7 -3.4,-2.2 -6.7,-2.2c-4.1,0.0 -6.9,2.2 -7.2,2.5l7.2,9.0l0.0,0.0l0.0,0.0l1.8,-2.2L13.800001,12.2z"
+ android:fillColor="?attr/fillColor"/>
<path
- android:fillColor="?attr/fillColor"
- android:pathData="M19.000000,11.600000c-1.300000,-0.700000 -3.400000,-1.600000 -6.000000,-1.600000c-4.400000,0.000000 -7.300000,2.400000 -7.600000,2.700000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,11.600000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillColor="?attr/backgroundColor"/>
<path
- android:fillColor="?attr/fillColor"
- android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="?attr/fillColor"
- android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.800001,1.9 -1.800001,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+ android:fillColor="?attr/fillColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
index 09d2e5037bc9..d34b4debc5ee 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_3.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,19 +15,16 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18.41dp"
- android:height="17dp"
- android:viewportWidth="26.0"
+ android:height="18.41dp"
+ android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="?attr/backgroundColor"
- android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0l1.0,-1.2C20.0,10.6 16.8,8.0 12.0,8.0s-8.0,2.6 -8.5,3.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillColor="?attr/fillColor"/>
<path
- android:fillColor="?attr/fillColor"
- android:pathData="M19.000000,8.600000c-1.600000,-0.700000 -3.600000,-1.300000 -6.000000,-1.300000c-5.300000,0.000000 -8.900000,3.000000 -9.200000,3.200000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.600000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillColor="?attr/backgroundColor"/>
<path
- android:fillColor="?attr/fillColor"
- android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="?attr/fillColor"
- android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+ android:fillColor="?attr/fillColor"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
index fb1f584250e4..570135639183 100644
--- a/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_wifi_signal_4.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,16 +15,13 @@ Copyright (C) 2014 The Android Open Source Project
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="18.41dp"
- android:height="17dp"
- android:viewportWidth="26.0"
+ android:height="18.41dp"
+ android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M19.000000,8.000000l5.300000,0.000000l1.300000,-1.600000C25.100000,6.000000 20.299999,2.000000 13.000000,2.000000S0.900000,6.000000 0.400000,6.400000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.000000,-7.400000L19.000000,8.000000z"/>
+ android:pathData="M13.8,12.2l5.7,0.0L23.6,7.0C23.2,6.7 18.7,3.0 12.0,3.0C5.3,3.0 0.8,6.7 0.4,7.0L12.0,21.5l0.0,0.0l0.0,0.0l1.8,-2.2L13.8,12.2z"
+ android:fillColor="?attr/fillColor"/>
<path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M21.000000,20.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000z"/>
- <path
- android:fillColor="?attr/singleToneColor"
- android:pathData="M21.000000,10.000000l2.000000,0.000000l0.000000,8.100000l-2.000000,0.000000z"/>
+ android:pathData="M21.9,15.4l-1.1,-1.2 -1.9,1.900001 -1.9,-1.900001 -1.1,1.2 1.9,1.9 -1.9,1.800001 1.1,1.199999 1.9,-1.9 1.9,1.9 1.1,-1.199999 -1.9,-1.800001z"
+ android:fillColor="?attr/fillColor"/>
</vector>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 7a0b666113d9..dcc30e2495b3 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -347,8 +347,8 @@
<string name="description_direction_left" msgid="7207478719805562165">"لغزاندن به چپ برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="zen_priority_introduction" msgid="3070506961866919502">"صداها و لرزش‌هایی به جز هشدارها، یادآوری‌ها، رویدادها و تماس‌گیرنده‌هایی که مشخص می‌کنید، مزاحم شما نمی‌شوند."</string>
<string name="zen_priority_customize_button" msgid="7948043278226955063">"سفارشی کردن"</string>
- <string name="zen_silence_introduction_voice" msgid="2284540992298200729">"این کار «همه» صداها و لرزش‌ها از جمله هشدارها، موسیقی، ویدیوها و بازی‌ها را مسدود می‌کند. همچنان می‌توانید تماس تلفنی برقرار کنید."</string>
- <string name="zen_silence_introduction" msgid="3137882381093271568">"این کار «همه» صداها و لرزش‌ها از جمله هشدارها، موسیقی، ویدیوها و بازی‌ها را مسدود می‌کند."</string>
+ <string name="zen_silence_introduction_voice" msgid="2284540992298200729">"این کار «همه» صداها و لرزش‌ها از جمله هشدارها، موسیقی، ویدئوها و بازی‌ها را مسدود می‌کند. همچنان می‌توانید تماس تلفنی برقرار کنید."</string>
+ <string name="zen_silence_introduction" msgid="3137882381093271568">"این کار «همه» صداها و لرزش‌ها از جمله هشدارها، موسیقی، ویدئوها و بازی‌ها را مسدود می‌کند."</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"اعلان‌های کمتر فوری در زیر"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"دوباره ضربه بزنید تا باز شود"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 33e7ec00b4ac..62ece3c10e47 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -404,7 +404,7 @@
<string name="device_owned_footer" msgid="3802752663326030053">"डिवाइस को मॉनीटर किया जा सकता है"</string>
<string name="profile_owned_footer" msgid="8021888108553696069">"प्रोफ़ाइल को मॉनीटर किया जा सकता है"</string>
<string name="vpn_footer" msgid="2388611096129106812">"नेटवर्क को मॉनीटर किया जा सकता है"</string>
- <string name="branded_vpn_footer" msgid="2168111859226496230">"नेटवर्क को मॉनीटर किया जा सकता है"</string>
+ <string name="branded_vpn_footer" msgid="2168111859226496230">"नेटवर्क को मॉनिटर किया जा सकता है"</string>
<string name="monitoring_title_device_owned" msgid="7121079311903859610">"डिवाइस को मॉनीटर करना"</string>
<string name="monitoring_title_profile_owned" msgid="6790109874733501487">"प्रोफ़ाइल को मॉनीटर करना"</string>
<string name="monitoring_title" msgid="169206259253048106">"नेटवर्क को मॉनीटर करना"</string>
@@ -417,7 +417,7 @@
<string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
<string name="monitoring_description_app" msgid="6259179342284742878">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्‍स और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
<string name="monitoring_description_app_personal" msgid="484599052118316268">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्‍स और वेबसाइटों सहित आपकी व्‍यक्‍तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
- <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइट सहित आपकी व्‍यक्‍तिगत नेटवर्क गतिविधि को मॉनीटर कर सकता है."</string>
+ <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइट सहित आपकी व्‍यक्‍तिगत नेटवर्क गतिविधि को मॉनिटर कर सकता है."</string>
<string name="monitoring_description_app_work" msgid="1754325860918060897">"आपकी कार्य प्रोफ़ाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> के द्वारा प्रबंधित है. वह <xliff:g id="APPLICATION">%2$s</xliff:g> से कनेक्‍ट है, जो ईमेल, ऐप्‍स और वेबसाइटों सहित आपकी कार्य नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nअधिक जानकारी के लिए, अपने नियंत्रक से संपर्क करें."</string>
<string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"आपकी कार्य प्रोफ़ाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> के द्वारा प्रबंधित है. वह <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> से कनेक्‍ट है, जो ईमेल, ऐप्‍स और वेबसाइटों सहित आपकी कार्य नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nआप <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> से भी कनेक्‍ट हैं, जो आपकी व्‍यक्‍तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
<string name="monitoring_description_vpn_app_device_owned" msgid="4970443827043261703">"आपका डिवाइस <xliff:g id="ORGANIZATION">%1$s</xliff:g> के द्वारा प्रबंधित है.\n\nआपका नियंत्रक सेटिंग, कॉर्पोरेट ऐक्‍सेस, ऐप्स, आपके डिवाइस से संबद्ध डेटा और आपके डिवाइस की स्‍थान जानकारी की निगरानी और उसका प्रबंधन कर सकता है.\n\nआप <xliff:g id="APPLICATION">%2$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्‍स और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nअधिक जानकारी के लिए, अपने नियंत्रक से संपर्क करें."</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 733812790d0e..f4f525a3e346 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -417,7 +417,7 @@
<string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
<string name="monitoring_description_app" msgid="6259179342284742878">"Сіз желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына қосылғансыз."</string>
<string name="monitoring_description_app_personal" msgid="484599052118316268">"Сіз жеке желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына қосылғансыз."</string>
- <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Жеке желідегі әрекеттеріңізді, соның ішінде электрондық пошта хабарларын, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына қосылғансыз."</string>
+ <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Жеке желідегі әрекеттеріңізді, соның ішінде электрондық пошта хабарларын, қолданбаларды және вебсайттарды бақылай алатын <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына қосылғансыз."</string>
<string name="monitoring_description_app_work" msgid="1754325860918060897">"Жұмыс профиліңізді <xliff:g id="ORGANIZATION">%1$s</xliff:g> басқарады. Ол жұмыс кезінде желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION">%2$s</xliff:g> қолданбасына қосылған.\n\nҚосымша ақпарат алу үшін әкімшіге хабарласыңыз."</string>
<string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Жұмыс профиліңізді <xliff:g id="ORGANIZATION">%1$s</xliff:g> басқарады. Ол желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> қолданбасына қосылған.\n\nСондай-ақ сіз желідегі жеке белсенділігіңізді бақылай алатын <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> қолданбасына қосылғансыз."</string>
<string name="monitoring_description_vpn_app_device_owned" msgid="4970443827043261703">"Құрылғыңызды <xliff:g id="ORGANIZATION">%1$s</xliff:g> басқарады.\n\nӘкімші параметрлерді, корпоративтік рұқсатты, қолданбаларды, құрылғыңызбен байланысты деректерді және құрылғының орны туралы ақпаратты бақылай және басқара алады.\n\nСіз желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және евб-сайттарды бақылай алатын <xliff:g id="APPLICATION">%2$s</xliff:g> қолданбасына қосылғансыз.\n\nҚосымша ақпарат алу үшін әкімшіге хабарласыңыз."</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index d77e51705b63..2f0e77243896 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -404,7 +404,7 @@
<string name="device_owned_footer" msgid="3802752663326030053">"ਡੀਵਾਈਸ ਦਾ ਨਿਰੀਖਣ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ"</string>
<string name="profile_owned_footer" msgid="8021888108553696069">"ਪ੍ਰੋਫਾਈਲ ਦਾ ਨਿਰੀਖਣ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ"</string>
<string name="vpn_footer" msgid="2388611096129106812">"ਨੈੱਟਵਰਕ ਦਾ ਨਿਰੀਖਣ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ"</string>
- <string name="branded_vpn_footer" msgid="2168111859226496230">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਨੈੱਟਵਰਕ ਦੀ ਨਿਗਰਾਨੀ ਹੋ ਰਹੀ ਹੋਵੇ"</string>
+ <string name="branded_vpn_footer" msgid="2168111859226496230">"ਹੋ ਸਕਦਾ ਹੈ ਨੈੱਟਵਰਕ ਦੀ ਨਿਗਰਾਨੀ ਹੋ ਰਹੀ ਹੋਵੇ"</string>
<string name="monitoring_title_device_owned" msgid="7121079311903859610">"ਡੀਵਾਈਸ ਦਾ ਨਿਰੀਖਣ ਕਰਨਾ"</string>
<string name="monitoring_title_profile_owned" msgid="6790109874733501487">"ਪ੍ਰੋਫਾਈਲ ਦਾ ਨਿਰੀਖਣ ਕਰਨਾ"</string>
<string name="monitoring_title" msgid="169206259253048106">"ਨੈੱਟਵਰਕ ਨਿਰੀਖਣ ਕਰ ਰਿਹਾ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 1e3b8419de99..c659acfaf14e 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -217,7 +217,7 @@
<style name="Animation.StatusBar">
</style>
- <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault" />
+ <style name="systemui_theme" parent="@*android:style/Theme.DeviceDefault.Settings.Dark" />
<style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
<item name="android:colorAccent">@color/remote_input_accent</item>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4449435dde40..6103355a568e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -964,6 +964,7 @@ public class KeyguardViewMediator extends SystemUI {
* if there is a secure lock pattern.
*/
public void onDreamingStarted() {
+ KeyguardUpdateMonitor.getInstance(mContext).dispatchDreamingStarted();
synchronized (this) {
if (mDeviceInteractive
&& mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
@@ -976,6 +977,7 @@ public class KeyguardViewMediator extends SystemUI {
* A dream stopped.
*/
public void onDreamingStopped() {
+ KeyguardUpdateMonitor.getInstance(mContext).dispatchDreamingStopped();
synchronized (this) {
if (mDeviceInteractive) {
cancelDoKeyguardLaterLocked();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index a1854fa06562..98957ddd5c00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -113,8 +113,11 @@ import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackStateAnimator;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
@@ -268,6 +271,8 @@ public abstract class BaseStatusBar extends SystemUI implements
protected boolean mVrMode;
+ private Set<String> mNonBlockablePkgs;
+
@Override // NotificationData.Environment
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
@@ -824,6 +829,9 @@ public abstract class BaseStatusBar extends SystemUI implements
Slog.e(TAG, "Failed to register VR mode state listener: " + e);
}
+ mNonBlockablePkgs = new HashSet<String>();
+ Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_nonBlockableNotificationPackages));
}
protected void notifyUserAboutHiddenNotifications() {
@@ -1104,7 +1112,8 @@ public abstract class BaseStatusBar extends SystemUI implements
settingsButton.setVisibility(View.GONE);
}
- guts.bindImportance(pmUser, sbn, mNotificationData.getImportance(sbn.getKey()));
+ guts.bindImportance(pmUser, sbn, mNonBlockablePkgs,
+ mNotificationData.getImportance(sbn.getKey()));
final TextView doneButton = (TextView) guts.findViewById(R.id.done);
doneButton.setText(R.string.notification_done);
@@ -1944,9 +1953,18 @@ public abstract class BaseStatusBar extends SystemUI implements
.getIdentifier();
if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
&& mKeyguardManager.isDeviceLocked(userId)) {
- if (startWorkChallengeIfNecessary(userId,
- intent.getIntentSender(), notificationKey)) {
- // Show work challenge, do not run pendingintent and
+ boolean canBypass = false;
+ try {
+ canBypass = ActivityManagerNative.getDefault()
+ .canBypassWorkChallenge(intent);
+ } catch (RemoteException e) {
+ }
+ // For direct-boot aware activities, they can be shown when
+ // the device is still locked without triggering the work
+ // challenge.
+ if ((!canBypass) && startWorkChallengeIfNecessary(userId,
+ intent.getIntentSender(), notificationKey)) {
+ // Show work challenge, do not run PendingIntent and
// remove notification
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
index 2045ec8dfa2d..1d7bede962d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
@@ -56,6 +56,8 @@ public class DismissView extends StackScrollerDecorView {
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDismissButton.setText(R.string.clear_all_notifications_text);
+ mDismissButton.setContentDescription(
+ mContext.getString(R.string.accessibility_clear_all));
}
public boolean isButtonVisible() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 68de16b2af21..caf5447d9d26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -905,6 +905,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
}
public void resetTranslation() {
+ if (mTranslateAnim != null) {
+ mTranslateAnim.cancel();
+ }
if (mTranslateableViews != null) {
for (int i = 0; i < mTranslateableViews.size(); i++) {
mTranslateableViews.get(i).setTranslationX(0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 88f37a320926..8b4225a8ab0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -174,7 +174,10 @@ public class KeyguardAffordanceView extends ImageView {
private void drawBackgroundCircle(Canvas canvas) {
if (mCircleRadius > 0 || mFinishing) {
- if (mFinishing && mSupportHardware) {
+ if (mFinishing && mSupportHardware && mHwCenterX != null) {
+ // Our hardware drawing proparties can be null if the finishing started but we have
+ // never drawn before. In that case we are not doing a render thread animation
+ // anyway, so we need to use the normal drawing.
DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
displayListCanvas.drawCircle(mHwCenterX, mHwCenterY, mHwCircleRadius,
mHwCirclePaint);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 9fd09d92162c..78e56c04ce9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -205,7 +205,7 @@ public class NotificationContentView extends FrameLayout {
&& MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) {
singleLineWidthSpec = MeasureSpec.makeMeasureSpec(
width - mSingleLineWidthIndention + mSingleLineView.getPaddingEnd(),
- MeasureSpec.AT_MOST);
+ MeasureSpec.EXACTLY);
}
mSingleLineView.measure(singleLineWidthSpec,
MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.AT_MOST));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index c497cfdf88d8..62d730a42732 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -50,6 +50,8 @@ import com.android.systemui.R;
import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.tuner.TunerService;
+import java.util.Set;
+
/**
* The guts of a notification revealed when performing a long press.
*/
@@ -173,7 +175,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
}
void bindImportance(final PackageManager pm, final StatusBarNotification sbn,
- final int importance) {
+ final Set<String> nonBlockablePkgs, final int importance) {
mINotificationManager = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
mStartingUserImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
@@ -182,24 +184,26 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
} catch (RemoteException e) {}
mNotificationImportance = importance;
- boolean systemApp = false;
+ boolean nonBlockable = false;
try {
final PackageInfo info =
pm.getPackageInfo(sbn.getPackageName(), PackageManager.GET_SIGNATURES);
- systemApp = Utils.isSystemPackage(getResources(), pm, info);
+ nonBlockable = Utils.isSystemPackage(getResources(), pm, info);
} catch (PackageManager.NameNotFoundException e) {
// unlikely.
}
+ if (nonBlockablePkgs != null) {
+ nonBlockable |= nonBlockablePkgs.contains(sbn.getPackageName());
+ }
final View importanceSlider = findViewById(R.id.importance_slider);
final View importanceButtons = findViewById(R.id.importance_buttons);
if (mShowSlider) {
- bindSlider(importanceSlider, systemApp);
+ bindSlider(importanceSlider, nonBlockable);
importanceSlider.setVisibility(View.VISIBLE);
importanceButtons.setVisibility(View.GONE);
} else {
-
- bindToggles(importanceButtons, mStartingUserImportance, systemApp);
+ bindToggles(importanceButtons, mStartingUserImportance, nonBlockable);
importanceButtons.setVisibility(View.VISIBLE);
importanceSlider.setVisibility(View.GONE);
}
@@ -239,7 +243,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
}
private void bindToggles(final View importanceButtons, final int importance,
- final boolean systemApp) {
+ final boolean nonBlockable) {
((RadioGroup) importanceButtons).setOnCheckedChangeListener(
new RadioGroup.OnCheckedChangeListener() {
@Override
@@ -250,7 +254,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
mBlock = (RadioButton) importanceButtons.findViewById(R.id.block_importance);
mSilent = (RadioButton) importanceButtons.findViewById(R.id.silent_importance);
mReset = (RadioButton) importanceButtons.findViewById(R.id.reset_importance);
- if (systemApp) {
+ if (nonBlockable) {
mBlock.setVisibility(View.GONE);
mReset.setText(mContext.getString(R.string.do_not_silence));
} else {
@@ -265,7 +269,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
}
}
- private void bindSlider(final View importanceSlider, final boolean systemApp) {
+ private void bindSlider(final View importanceSlider, final boolean nonBlockable) {
mActiveSliderTint = ColorStateList.valueOf(Utils.getColorAccent(mContext));
mInactiveSliderTint = loadColorStateList(R.color.notification_guts_disabled_slider_color);
@@ -273,7 +277,7 @@ public class NotificationGuts extends LinearLayout implements TunerService.Tunab
mImportanceTitle = ((TextView) importanceSlider.findViewById(R.id.title));
mSeekBar = (SeekBar) importanceSlider.findViewById(R.id.seekbar);
- final int minProgress = systemApp ?
+ final int minProgress = nonBlockable ?
NotificationListenerService.Ranking.IMPORTANCE_MIN
: NotificationListenerService.Ranking.IMPORTANCE_NONE;
mSeekBar.setMax(NotificationListenerService.Ranking.IMPORTANCE_MAX);
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 b1bea0287ddb..9251f32099a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -664,6 +664,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private boolean mNoAnimationOnNextBarModeChange;
private FalsingManager mFalsingManager;
+ private KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onDreamingStateChanged(boolean dreaming) {
+ if (dreaming) {
+ maybeEscalateHeadsUp();
+ }
+ }
+ };
+
@Override
public void start() {
mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
@@ -701,8 +710,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mUnlockMethodCache.addListener(this);
startKeyguard();
+ KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback);
mDozeServiceHost = new DozeServiceHost();
- KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mDozeServiceHost);
putComponent(DozeHost.class, mDozeServiceHost);
putComponent(PhoneStatusBar.class, this);
@@ -4445,6 +4454,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
if (state == StatusBarState.KEYGUARD) {
removeRemoteInputEntriesKeptUntilCollapsed();
+ maybeEscalateHeadsUp();
}
mState = state;
mGroupManager.setStatusBarState(state);
@@ -4964,7 +4974,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
- private final class DozeServiceHost extends KeyguardUpdateMonitorCallback implements DozeHost {
+ private final class DozeServiceHost implements DozeHost {
// Amount of time to allow to update the time shown on the screen before releasing
// the wakelock. This timeout is design to compensate for the fact that we don't
// currently have a way to know when time display contents have actually been
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index d3ae54984e99..f6c0942d7ed0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -381,7 +381,7 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL
}
public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
- if (mIsExpanded) {
+ if (mIsExpanded || mBar.isBouncerShowing()) {
// The touchable region is always the full area when expanded
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index 3c9373bd46a2..d7920a9b1e7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -123,8 +123,10 @@ public class NotificationChildrenContainer extends ViewGroup {
mDividers.get(i).layout(0, 0, getWidth(), mDividerHeight);
}
if (mOverflowNumber != null) {
- mOverflowNumber.layout(getWidth() - mOverflowNumber.getMeasuredWidth(), 0, getWidth(),
- mOverflowNumber.getMeasuredHeight());
+ boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ int left = (isRtl ? 0 : getWidth() - mOverflowNumber.getMeasuredWidth());
+ int right = left + mOverflowNumber.getMeasuredWidth();
+ mOverflowNumber.layout(left, 0, right, mOverflowNumber.getMeasuredHeight());
}
if (mNotificationHeader != null) {
mNotificationHeader.layout(0, 0, mNotificationHeader.getMeasuredWidth(),
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 d1de38c7b9e4..5f4bd1d7c240 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -3900,6 +3900,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private class NotificationSwipeHelper extends SwipeHelper {
private static final long SHOW_GEAR_DELAY = 60;
private static final long COVER_GEAR_DELAY = 4000;
+ private static final long SWIPE_GEAR_TIMING = 200;
private CheckForDrag mCheckForDrag;
private Runnable mFalsingCheck;
private Handler mHandler;
@@ -4016,6 +4017,9 @@ public class NotificationStackScrollLayout extends ViewGroup
boolean gestureTowardsGear = isTowardsGear(velocity, mCurrIconRow.isIconOnLeft());
boolean gestureFastEnough = Math.abs(velocity) > getEscapeVelocity();
+ final double timeForGesture = ev.getEventTime() - ev.getDownTime();
+ final boolean showGearForSlowOnGoing = !canChildBeDismissed(animView)
+ && timeForGesture >= SWIPE_GEAR_TIMING;
if (mGearSnappedTo && mCurrIconRow.isVisible()) {
if (mGearSnappedOnLeft == mCurrIconRow.isIconOnLeft()) {
@@ -4040,7 +4044,8 @@ public class NotificationStackScrollLayout extends ViewGroup
} else {
dismissOrSnapBack(animView, velocity, ev);
}
- } else if ((!gestureFastEnough && swipedEnoughToShowGear(animView))
+ } else if (((!gestureFastEnough || showGearForSlowOnGoing)
+ && swipedEnoughToShowGear(animView))
|| gestureTowardsGear) {
// Gear has not been snapped to previously and this is gear revealing gesture
snapToGear(animView, velocity);
@@ -4092,13 +4097,9 @@ public class NotificationStackScrollLayout extends ViewGroup
final float multiplier = canChildBeDismissed(animView) ? 0.4f : 0.2f;
final float snapBackThreshold = getSpaceForGear(animView) * multiplier;
final float translation = getTranslation(animView);
- final boolean fromLeft = translation > 0;
- final float absTrans = Math.abs(translation);
- final float notiThreshold = getSize(mTranslatingParentView) * 0.4f;
-
- return mCurrIconRow.isVisible() && (mCurrIconRow.isIconOnLeft()
- ? (translation > snapBackThreshold && translation <= notiThreshold)
- : (translation < -snapBackThreshold && translation >= -notiThreshold));
+ return !swipedFarEnough() && mCurrIconRow.isVisible() && (mCurrIconRow.isIconOnLeft()
+ ? translation > snapBackThreshold
+ : translation < -snapBackThreshold);
}
@Override
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 8dca14f13202..e00178f8ea41 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3683,13 +3683,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
Rect boundsInScreen = mTempRect;
focus.getBoundsInScreen(boundsInScreen);
- // Clip to the window bounds.
- Rect windowBounds = mTempRect1;
- getWindowBounds(focus.getWindowId(), windowBounds);
- if (!boundsInScreen.intersect(windowBounds)) {
- return false;
- }
-
// Apply magnification if needed.
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
if (spec != null && !spec.isNop()) {
@@ -3697,6 +3690,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
boundsInScreen.scale(1 / spec.scale);
}
+ // Clip to the window bounds.
+ Rect windowBounds = mTempRect1;
+ getWindowBounds(focus.getWindowId(), windowBounds);
+ if (!boundsInScreen.intersect(windowBounds)) {
+ return false;
+ }
+
// Clip to the screen bounds.
Point screenSize = mTempPoint;
mDefaultDisplay.getRealSize(screenSize);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index eddc4f40949e..ae61a7e10dd0 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -24,6 +24,7 @@ import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
@@ -397,6 +398,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
private static final int EVENT_REQUEST_LINKPROPERTIES = 32;
private static final int EVENT_REQUEST_NETCAPABILITIES = 33;
+ /**
+ * Used internally to (re)configure avoid bad wifi setting.
+ */
+ private static final int EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI = 34;
+
/** Handler thread used for both of the handlers below. */
@VisibleForTesting
protected final HandlerThread mHandlerThread;
@@ -851,6 +857,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
+
+ intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+ mContext.registerReceiverAsUser(new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ mHandler.sendEmptyMessage(EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI);
+ }
+ }, UserHandle.ALL, intentFilter, null, null);
+ updateAvoidBadWifi();
}
private NetworkRequest createInternetRequestForTransport(
@@ -901,6 +916,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
mSettingsObserver.observe(
Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
+
+ // Watch for whether to automatically switch away from wifi networks that lose Internet
+ // access.
+ mSettingsObserver.observe(
+ Settings.Global.getUriFor(Settings.Global.NETWORK_AVOID_BAD_WIFI),
+ EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI);
}
private synchronized int nextNetworkRequestId() {
@@ -2139,15 +2160,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) ||
- networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
+ networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED) ||
+ networkCapabilities.hasCapability(NET_CAPABILITY_FOREGROUND)) {
Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
}
- if (nai.everConnected && !nai.networkCapabilities.equalImmutableCapabilities(
- networkCapabilities)) {
- Slog.wtf(TAG, "BUG: " + nai + " changed immutable capabilities: "
- + nai.networkCapabilities + " -> " + networkCapabilities);
- }
- updateCapabilities(nai, networkCapabilities);
+ updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
break;
}
case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: {
@@ -2218,13 +2235,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (nai != null) {
final boolean valid =
(msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
+ final boolean wasValidated = nai.lastValidated;
if (DBG) log(nai.name() + " validation " + (valid ? "passed" : "failed") +
(msg.obj == null ? "" : " with redirect to " + (String)msg.obj));
if (valid != nai.lastValidated) {
final int oldScore = nai.getCurrentScore();
nai.lastValidated = valid;
nai.everValidated |= valid;
- updateCapabilities(nai, nai.networkCapabilities);
+ updateCapabilities(oldScore, nai, nai.networkCapabilities);
// If score has changed, rebroadcast to NetworkFactories. b/17726566
if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
}
@@ -2236,6 +2254,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkAgent.CMD_REPORT_NETWORK_STATUS,
(valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK),
0, redirectUrlBundle);
+ if (wasValidated && !nai.lastValidated) {
+ handleNetworkUnvalidated(nai);
+ }
}
break;
}
@@ -2248,9 +2269,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
// If captive portal status has changed, update capabilities.
if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
+ final int oldScore = nai.getCurrentScore();
nai.lastCaptivePortalDetected = visible;
nai.everCaptivePortalDetected |= visible;
- updateCapabilities(nai, nai.networkCapabilities);
+ updateCapabilities(oldScore, nai, nai.networkCapabilities);
}
if (!visible) {
mNotifier.clearNotification(netId);
@@ -2604,6 +2626,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
boolean wasKept = false;
NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
if (nai != null) {
+ boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
nai.removeRequest(nri.request.requestId);
if (VDBG) {
log(" Removing from current network " + nai.name() +
@@ -2619,6 +2642,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
wasKept = true;
}
mNetworkForRequestId.remove(nri.request.requestId);
+ if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) {
+ // Went from foreground to background.
+ updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
+ }
}
// TODO: remove this code once we know that the Slog.wtf is never hit.
@@ -2732,6 +2759,56 @@ public class ConnectivityService extends IConnectivityManager.Stub
PROMPT_UNVALIDATED_DELAY_MS);
}
+ private boolean mAvoidBadWifi;
+
+ public boolean avoidBadWifi() {
+ return mAvoidBadWifi;
+ }
+
+ @VisibleForTesting
+ public boolean updateAvoidBadWifi() {
+ // There are two modes: either we always automatically avoid unvalidated wifi, or we show a
+ // dialog and don't switch to it. The behaviour is controlled by the NETWORK_AVOID_BAD_WIFI
+ // setting. If the setting has no value, then the value is taken from the config value,
+ // which can be changed via OEM/carrier overlays.
+ //
+ // The only valid values for NETWORK_AVOID_BAD_WIFI are null and unset. Currently, the unit
+ // test uses 0 in order to avoid having to mock out fetching the carrier setting.
+ int defaultAvoidBadWifi =
+ mContext.getResources().getInteger(R.integer.config_networkAvoidBadWifi);
+ int avoid = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.NETWORK_AVOID_BAD_WIFI, defaultAvoidBadWifi);
+
+ boolean prev = mAvoidBadWifi;
+ mAvoidBadWifi = (avoid == 1);
+ return mAvoidBadWifi != prev;
+ }
+
+ private void showValidationNotification(NetworkAgentInfo nai, NotificationType type) {
+ final String action;
+ switch (type) {
+ case NO_INTERNET:
+ action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
+ break;
+ case LOST_INTERNET:
+ action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
+ break;
+ default:
+ Slog.wtf(TAG, "Unknown notification type " + type);
+ return;
+ }
+
+ Intent intent = new Intent(action);
+ intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setClassName("com.android.settings",
+ "com.android.settings.wifi.WifiNoInternetDialog");
+
+ PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
+ mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
+ mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, true);
+ }
+
private void handlePromptUnvalidated(Network network) {
if (VDBG) log("handlePromptUnvalidated " + network);
NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
@@ -2743,18 +2820,22 @@ public class ConnectivityService extends IConnectivityManager.Stub
!nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated) {
return;
}
+ showValidationNotification(nai, NotificationType.NO_INTERNET);
+ }
- Intent intent = new Intent(ConnectivityManager.ACTION_PROMPT_UNVALIDATED);
- intent.setData(Uri.fromParts("netId", Integer.toString(network.netId), null));
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setClassName("com.android.settings",
- "com.android.settings.wifi.WifiNoInternetDialog");
+ // TODO: Delete this like updateMobileDataAlwaysOn above.
+ @VisibleForTesting
+ void updateNetworkAvoidBadWifi() {
+ mHandler.sendEmptyMessage(EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI);
+ }
- PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
- mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
+ private void handleNetworkUnvalidated(NetworkAgentInfo nai) {
+ NetworkCapabilities nc = nai.networkCapabilities;
+ if (DBG) log("handleNetworkUnvalidated " + nai.name() + " cap=" + nc);
- mNotifier.showNotification(nai.network.netId, NotificationType.NO_INTERNET, nai, null,
- pendingIntent, true);
+ if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && !avoidBadWifi()) {
+ showValidationNotification(nai, NotificationType.LOST_INTERNET);
+ }
}
private class InternalHandler extends Handler {
@@ -2838,6 +2919,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
handleMobileDataAlwaysOn();
break;
}
+ case EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI: {
+ if (updateAvoidBadWifi()) {
+ rematchAllNetworksAndRequests(null, 0);
+ }
+ break;
+ }
case EVENT_REQUEST_LINKPROPERTIES:
handleRequestLinkProperties((NetworkRequest) msg.obj, msg.arg1);
break;
@@ -4488,10 +4575,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
* augmented with any stateful capabilities implied from {@code networkAgent}
* (e.g., validated status and captive portal status).
*
+ * @param oldScore score of the network before any of the changes that prompted us
+ * to call this function.
* @param nai the network having its capabilities updated.
* @param networkCapabilities the new network capabilities.
*/
- private void updateCapabilities(NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) {
+ private void updateCapabilities(
+ int oldScore, NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) {
+ if (nai.everConnected && !nai.networkCapabilities.equalImmutableCapabilities(
+ networkCapabilities)) {
+ Slog.wtf(TAG, "BUG: " + nai + " changed immutable capabilities: "
+ + nai.networkCapabilities + " -> " + networkCapabilities);
+ }
+
// Don't modify caller's NetworkCapabilities.
networkCapabilities = new NetworkCapabilities(networkCapabilities);
if (nai.lastValidated) {
@@ -4504,21 +4600,39 @@ public class ConnectivityService extends IConnectivityManager.Stub
} else {
networkCapabilities.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
}
- if (!Objects.equals(nai.networkCapabilities, networkCapabilities)) {
- final int oldScore = nai.getCurrentScore();
- if (nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) !=
- networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
- try {
- mNetd.setNetworkPermission(nai.network.netId,
- networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) ?
- null : NetworkManagementService.PERMISSION_SYSTEM);
- } catch (RemoteException e) {
- loge("Exception in setNetworkPermission: " + e);
- }
- }
- synchronized (nai) {
- nai.networkCapabilities = networkCapabilities;
+ if (nai.isBackgroundNetwork()) {
+ networkCapabilities.removeCapability(NET_CAPABILITY_FOREGROUND);
+ } else {
+ networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
+ }
+
+ if (Objects.equals(nai.networkCapabilities, networkCapabilities)) return;
+
+ if (nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) !=
+ networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
+ try {
+ mNetd.setNetworkPermission(nai.network.netId,
+ networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) ?
+ null : NetworkManagementService.PERMISSION_SYSTEM);
+ } catch (RemoteException e) {
+ loge("Exception in setNetworkPermission: " + e);
}
+ }
+
+ final NetworkCapabilities prevNc = nai.networkCapabilities;
+ synchronized (nai) {
+ nai.networkCapabilities = networkCapabilities;
+ }
+ if (nai.getCurrentScore() == oldScore &&
+ networkCapabilities.equalRequestableCapabilities(prevNc)) {
+ // If the requestable capabilities haven't changed, and the score hasn't changed, then
+ // the change we're processing can't affect any requests, it can only affect the listens
+ // on this network. We might have been called by rematchNetworkAndRequests when a
+ // network changed foreground state.
+ processListenRequests(nai, true);
+ } else {
+ // If the requestable capabilities have changed or the score changed, we can't have been
+ // called by rematchNetworkAndRequests, so it's safe to start a rematch.
rematchAllNetworksAndRequests(nai, oldScore);
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
@@ -4642,7 +4756,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
oldNetwork.clearLingerState();
if (unneeded(oldNetwork, UnneededFor.TEARDOWN)) {
+ // Tear the network down.
teardownUnneededNetwork(oldNetwork);
+ } else {
+ // Put the network in the background.
+ updateCapabilities(oldNetwork.getCurrentScore(), oldNetwork,
+ oldNetwork.networkCapabilities);
}
}
@@ -4660,7 +4779,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
}
- private void processListenRequests(NetworkAgentInfo nai) {
+ private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
// For consistency with previous behaviour, send onLost callbacks before onAvailable.
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
NetworkRequest nr = nri.request;
@@ -4671,6 +4790,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ if (capabilitiesChanged) {
+ notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
+ }
+
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
NetworkRequest nr = nri.request;
if (!nr.isListen()) continue;
@@ -4714,12 +4837,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
boolean keep = newNetwork.isVPN();
boolean isNewDefault = false;
NetworkAgentInfo oldDefaultNetwork = null;
+
+ final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork();
+ final int score = newNetwork.getCurrentScore();
+
if (VDBG) log("rematching " + newNetwork.name());
+
// Find and migrate to this Network any NetworkRequests for
// which this network is now the best.
ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<NetworkAgentInfo>();
ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<NetworkRequestInfo>();
- if (VDBG) log(" network has: " + newNetwork.networkCapabilities);
+ NetworkCapabilities nc = newNetwork.networkCapabilities;
+ if (VDBG) log(" network has: " + nc);
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
// Process requests in the first pass and listens in the second pass. This allows us to
// change a network's capabilities depending on which requests it has. This is only
@@ -4746,10 +4875,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (VDBG) {
log("currentScore = " +
(currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
- ", newScore = " + newNetwork.getCurrentScore());
+ ", newScore = " + score);
}
- if (currentNetwork == null ||
- currentNetwork.getCurrentScore() < newNetwork.getCurrentScore()) {
+ if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
if (VDBG) log("rematch for " + newNetwork.name());
if (currentNetwork != null) {
if (VDBG) log(" accepting network in place of " + currentNetwork.name());
@@ -4771,7 +4899,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// TODO - this could get expensive if we have alot of requests for this
// network. Think about if there is a way to reduce this. Push
// netid->request mapping to each factory?
- sendUpdatedScoreToFactories(nri.request, newNetwork.getCurrentScore());
+ sendUpdatedScoreToFactories(nri.request, score);
if (isDefaultRequest(nri)) {
isNewDefault = true;
oldDefaultNetwork = currentNetwork;
@@ -4783,7 +4911,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
} else if (newNetwork.isSatisfyingRequest(nri.request.requestId)) {
// If "newNetwork" is listed as satisfying "nri" but no longer satisfies "nri",
// mark it as no longer satisfying "nri". Because networks are processed by
- // rematchAllNetworkAndRequests() in descending score order, "currentNetwork" will
+ // rematchAllNetworksAndRequests() in descending score order, "currentNetwork" will
// match "newNetwork" before this loop will encounter a "currentNetwork" with higher
// score than "newNetwork" and where "currentNetwork" no longer satisfies "nri".
// This means this code doesn't have to handle the case where "currentNetwork" no
@@ -4829,8 +4957,27 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ if (!newNetwork.networkCapabilities.equalRequestableCapabilities(nc)) {
+ Slog.wtf(TAG, String.format(
+ "BUG: %s changed requestable capabilities during rematch: %s -> %s",
+ nc, newNetwork.networkCapabilities));
+ }
+ if (newNetwork.getCurrentScore() != score) {
+ Slog.wtf(TAG, String.format(
+ "BUG: %s changed score during rematch: %d -> %d",
+ score, newNetwork.getCurrentScore()));
+ }
+
// Second pass: process all listens.
- processListenRequests(newNetwork);
+ if (wasBackgroundNetwork != newNetwork.isBackgroundNetwork()) {
+ // If the network went from background to foreground or vice versa, we need to update
+ // its foreground state. It is safe to do this after rematching the requests because
+ // NET_CAPABILITY_FOREGROUND does not affect requests, as is not a requestable
+ // capability and does not affect the network's score (see the Slog.wtf call above).
+ updateCapabilities(score, newNetwork, newNetwork.networkCapabilities);
+ } else {
+ processListenRequests(newNetwork, false);
+ }
// do this after the default net is switched, but
// before LegacyTypeTracker sends legacy broadcasts
@@ -5023,6 +5170,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (!networkAgent.created
&& (state == NetworkInfo.State.CONNECTED
|| (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {
+
+ // A network that has just connected has zero requests and is thus a foreground network.
+ networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
+
try {
// This should never fail. Specifying an already in use NetID will cause failure.
if (networkAgent.isVPN()) {
@@ -5184,6 +5335,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkRequest nr = networkAgent.requestAt(i);
NetworkRequestInfo nri = mNetworkRequests.get(nr);
if (VDBG) log(" sending notification for " + nr);
+ // TODO: if we're in the middle of a rematch, can we send a CAP_CHANGED callback for
+ // a network that no longer satisfies the listen?
if (nri.mPendingIntent == null) {
callCallbackForRequest(nri, networkAgent, notifyType, arg1);
} else {
@@ -5318,6 +5471,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
}
+
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 8ae491707542..df1b6f51bc33 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -3077,8 +3077,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (DEBUG) {
Slog.d(TAG, "Found an input method " + p);
}
- } catch (XmlPullParserException | IOException e) {
- Slog.w(TAG, "Unable to load input method " + compName, e);
+ } catch (Exception e) {
+ Slog.wtf(TAG, "Unable to load input method " + compName, e);
}
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index bee7fdb39813..b69750794761 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2852,10 +2852,9 @@ public class AccountManagerService
boolean isPasswordForwardingAllowed = isPermitted(
callerPkg, uid, Manifest.permission.GET_PASSWORD);
- int usrId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
- UserAccounts accounts = getUserAccounts(usrId);
+ UserAccounts accounts = getUserAccounts(userId);
logRecordWithUid(accounts, DebugDbHelper.ACTION_CALLED_START_ACCOUNT_ADD,
TABLE_ACCOUNTS, uid);
new StartAccountSession(
@@ -2916,10 +2915,6 @@ public class AccountManagerService
checkKeyIntent(
Binder.getCallingUid(),
intent);
- // Omit passwords if the caller isn't permitted to see them.
- if (!mIsPasswordForwardingAllowed) {
- result.remove(AccountManager.KEY_PASSWORD);
- }
}
IAccountManagerResponse response;
if (mExpectActivityLaunch && result != null
@@ -2949,6 +2944,11 @@ public class AccountManagerService
return;
}
+ // Omit passwords if the caller isn't permitted to see them.
+ if (!mIsPasswordForwardingAllowed) {
+ result.remove(AccountManager.KEY_PASSWORD);
+ }
+
// Strip auth token from result.
result.remove(AccountManager.KEY_AUTHTOKEN);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ab33dbf9f80b..f65fab8d98aa 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -641,7 +641,8 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean mDoingSetFocusedActivity;
public boolean canShowErrorDialogs() {
- return mShowDialogs && !mSleeping && !mShuttingDown;
+ return mShowDialogs && !mSleeping && !mShuttingDown
+ && mLockScreenShown != LOCK_SCREEN_SHOWN;
}
private static final class PriorityState {
@@ -22197,4 +22198,22 @@ public final class ActivityManagerService extends ActivityManagerNative
Binder.restoreCallingIdentity(callingId);
}
}
+
+ @Override
+ public boolean canBypassWorkChallenge(PendingIntent intent) throws RemoteException {
+ final int userId = intent.getCreatorUserHandle().getIdentifier();
+ if (!mUserController.isUserRunningLocked(userId, ActivityManager.FLAG_AND_LOCKED)) {
+ return false;
+ }
+ IIntentSender target = intent.getTarget();
+ if (!(target instanceof PendingIntentRecord)) {
+ return false;
+ }
+ final PendingIntentRecord record = (PendingIntentRecord) target;
+ final ResolveInfo rInfo = mStackSupervisor.resolveIntent(record.key.requestIntent,
+ record.key.requestResolvedType, userId, PackageManager.MATCH_DIRECT_BOOT_AWARE);
+ // For direct boot aware activities, they can be shown without triggering a work challenge
+ // before the profile user is unlocked.
+ return rInfo != null && rInfo.activityInfo != null;
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index f374c09db285..589563333dfa 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.app.ActivityManager.StackId;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
@@ -946,21 +947,29 @@ final class ActivityRecord {
// The activity now gets access to the data associated with this Intent.
service.grantUriPermissionFromIntentLocked(callingUid, packageName,
intent, getUriPermissionsLocked(), userId);
- // We want to immediately deliver the intent to the activity if
- // it is currently the top resumed activity... however, if the
- // device is sleeping, then all activities are stopped, so in that
- // case we will deliver it if this is the current top activity on its
- // stack.
final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
boolean unsent = true;
- if ((state == ActivityState.RESUMED
- || (service.isSleepingLocked() && task.stack != null
- && task.stack.topRunningActivityLocked() == this))
- && app != null && app.thread != null) {
+ final ActivityStack stack = task.stack;
+ final boolean isTopActivityInStack =
+ stack != null && stack.topRunningActivityLocked() == this;
+ final boolean isTopActivityWhileSleeping =
+ service.isSleepingLocked() && isTopActivityInStack;
+ final boolean isTopActivityInMinimizedDockedStack = isTopActivityInStack
+ && stack.mStackId == DOCKED_STACK_ID && mStackSupervisor.mIsDockMinimized
+ && state == ActivityState.PAUSED;
+
+ // We want to immediately deliver the intent to the activity if:
+ // - It is the resumed activity.
+ // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
+ // - It is the top activity in a minimized docked stack. In this case the activity will be
+ // temporarily resumed then paused again on the client side.
+ if ((state == ActivityState.RESUMED || isTopActivityWhileSleeping
+ || isTopActivityInMinimizedDockedStack) && app != null && app.thread != null) {
try {
ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
ar.add(rintent);
- app.thread.scheduleNewIntent(ar, appToken);
+ app.thread.scheduleNewIntent(
+ ar, appToken, isTopActivityInMinimizedDockedStack /* andPause */);
unsent = false;
} catch (RemoteException e) {
Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index b4303c50296c..60d3d1ec349b 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1308,7 +1308,9 @@ final class ActivityStack {
// It is possible the activity was freezing the screen before it was paused.
// In that case go ahead and remove the freeze this activity has on the screen
// since it is no longer visible.
- prev.stopFreezingScreenLocked(true /*force*/);
+ if (prev != null) {
+ prev.stopFreezingScreenLocked(true /*force*/);
+ }
mPausingActivity = null;
}
@@ -2493,7 +2495,8 @@ final class ActivityStack {
break;
}
}
- next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
+ next.app.thread.scheduleNewIntent(
+ next.newIntents, next.appToken, false /* andPause */);
}
// Well the app will no longer be stopped.
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index f26e47e934c4..d719c586f6c5 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -29,6 +29,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManagerInternal;
@@ -210,6 +211,11 @@ class ActivityStartInterceptor {
if (!mService.mUserController.shouldConfirmCredentials(userId)) {
return null;
}
+ // Allow direct boot aware activity to be displayed before the user is unlocked.
+ if (aInfo.directBootAware && mService.mUserController.isUserRunningLocked(userId,
+ ActivityManager.FLAG_AND_LOCKED)) {
+ return null;
+ }
final IIntentSender target = mService.getIntentSenderLocked(
INTENT_SENDER_ACTIVITY, callingPackage,
Binder.getCallingUid(), userId, null, null, 0, new Intent[]{ intent },
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 576f2b27f111..0c67c75dc3e8 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -22,7 +22,6 @@ import com.android.internal.logging.MetricsProto;
import com.android.internal.os.ProcessCpuTracker;
import com.android.server.Watchdog;
-import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityThread;
@@ -33,10 +32,7 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.PackageManager;
import android.os.Binder;
-import android.os.Bundle;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
@@ -59,7 +55,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Set;
-import java.util.concurrent.Semaphore;
import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
@@ -359,7 +354,7 @@ class AppErrors {
return;
}
- Message msg = Message.obtain();
+ final Message msg = Message.obtain();
msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;
task = data.task;
diff --git a/services/core/java/com/android/server/am/UriPermission.java b/services/core/java/com/android/server/am/UriPermission.java
index 6e371c1138ca..0aa54d910ea7 100644
--- a/services/core/java/com/android/server/am/UriPermission.java
+++ b/services/core/java/com/android/server/am/UriPermission.java
@@ -19,6 +19,7 @@ package com.android.server.am;
import android.content.Intent;
import android.os.UserHandle;
import android.util.ArraySet;
+import android.util.Log;
import android.util.Slog;
import com.android.server.am.ActivityManagerService.GrantUri;
@@ -93,7 +94,16 @@ final class UriPermission {
}
private void updateModeFlags() {
+ final int oldModeFlags = modeFlags;
modeFlags = ownedModeFlags | globalModeFlags | persistableModeFlags | persistedModeFlags;
+
+ if (Log.isLoggable(TAG, Log.VERBOSE) && (modeFlags != oldModeFlags)) {
+ Slog.d(TAG,
+ "Permission for " + targetPkg + " to " + uri + " is changing from 0x"
+ + Integer.toHexString(oldModeFlags) + " to 0x"
+ + Integer.toHexString(modeFlags),
+ new Throwable());
+ }
}
/**
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index da0c05eefb92..b4606bb652cf 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -510,8 +510,11 @@ public class AudioService extends IAudioService.Stub {
private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
// Request to override default use of A2DP for media.
- // FIXME: remove when MediaRouter does not use setBluetoothA2dpOn() anymore
private boolean mBluetoothA2dpEnabled;
+ // FIXME: remove when MediaRouter does not use setBluetoothA2dpOn() anymore
+ // state of bluetooth A2DP enable request sen by deprecated APIs setBluetoothA2dpOn() and
+ // isBluettohA2dpOn()
+ private boolean mBluetoothA2dpEnabledExternal;
private final Object mBluetoothA2dpEnabledLock = new Object();
// Monitoring of audio routes. Protected by mCurAudioRoutes.
@@ -840,6 +843,12 @@ public class AudioService extends IAudioService.Stub {
RotationHelper.updateOrientation();
}
+ synchronized (mBluetoothA2dpEnabledLock) {
+ AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
+ mBluetoothA2dpEnabled ?
+ AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
+ }
+
synchronized (mSettingsLock) {
AudioSystem.setForceUse(AudioSystem.FOR_DOCK,
mDockAudioMediaEnabled ?
@@ -2706,7 +2715,7 @@ public class AudioService extends IAudioService.Stub {
* @deprecated
* */
public void setBluetoothA2dpOn(boolean on) {
- mBluetoothA2dpEnabled = on;
+ mBluetoothA2dpEnabledExternal = on;
Log.e(TAG, "setBluetoothA2dpOn() is deprecated, now a no-op",
new Exception("Deprecated use of setBluetoothA2dpOn()"));
}
@@ -2716,7 +2725,7 @@ public class AudioService extends IAudioService.Stub {
* @deprecated
* */
public boolean isBluetoothA2dpOn() {
- return mBluetoothA2dpEnabled;
+ return mBluetoothA2dpEnabledExternal;
}
/** @see AudioManager#startBluetoothSco() */
@@ -3787,6 +3796,11 @@ public class AudioService extends IAudioService.Stub {
Slog.i(TAG, "setWiredDeviceConnectionState(" + state + " nm: " + name + " addr:"
+ address + ")");
}
+ if ((state == 0) && ((type == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
+ (type == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
+ (type == AudioSystem.DEVICE_OUT_LINE))) {
+ setBluetoothA2dpOnInt(true);
+ }
int delay = checkSendBecomingNoisyIntent(type, state);
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
@@ -4767,6 +4781,7 @@ public class AudioService extends IAudioService.Stub {
VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0);
+ setBluetoothA2dpOnInt(true);
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_AVAILABLE, address, name);
// Reset A2DP suspend state each time a new sink is connected
@@ -5004,6 +5019,7 @@ public class AudioService extends IAudioService.Stub {
devices |= dev;
}
}
+
if (devices == device) {
sendMsg(mAudioHandler,
MSG_BROADCAST_AUDIO_BECOMING_NOISY,
@@ -5107,6 +5123,11 @@ public class AudioService extends IAudioService.Stub {
return;
}
if (state != 0) {
+ if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
+ (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) ||
+ (device == AudioSystem.DEVICE_OUT_LINE)) {
+ setBluetoothA2dpOnInt(false);
+ }
if ((device & mSafeMediaVolumeDevices) != 0) {
sendMsg(mAudioHandler,
MSG_CHECK_MUSIC_ACTIVE,
@@ -5572,9 +5593,26 @@ public class AudioService extends IAudioService.Stub {
}
}
+ // Handles request to override default use of A2DP for media.
+ // Must be called synchronized on mConnectedDevices
+ public void setBluetoothA2dpOnInt(boolean on) {
+ synchronized (mBluetoothA2dpEnabledLock) {
+ mBluetoothA2dpEnabled = on;
+ setForceUseInt_SyncDevices(AudioSystem.FOR_MEDIA,
+ mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
+ }
+ }
+
// Must be called synchronized on mConnectedDevices
private void setForceUseInt_SyncDevices(int usage, int config) {
switch (usage) {
+ case AudioSystem.FOR_MEDIA:
+ if (config == AudioSystem.FORCE_NO_BT_A2DP) {
+ mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ALL_A2DP;
+ } else { // config == AudioSystem.FORCE_NONE
+ mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ALL_A2DP;
+ }
+ break;
case AudioSystem.FOR_DOCK:
if (config == AudioSystem.FORCE_ANALOG_DOCK) {
mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET;
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java
index 49be879b93c7..cc18114120eb 100644
--- a/services/core/java/com/android/server/audio/FocusRequester.java
+++ b/services/core/java/com/android/server/audio/FocusRequester.java
@@ -40,9 +40,9 @@ public class FocusRequester {
private static final String TAG = "MediaFocusControl";
private static final boolean DEBUG = false;
- private AudioFocusDeathHandler mDeathHandler;
- private final IAudioFocusDispatcher mFocusDispatcher; // may be null
- private final IBinder mSourceRef;
+ private AudioFocusDeathHandler mDeathHandler; // may be null
+ private IAudioFocusDispatcher mFocusDispatcher; // may be null
+ private final IBinder mSourceRef; // may be null
private final String mClientId;
private final String mPackageName;
private final int mCallingUid;
@@ -205,6 +205,7 @@ public class FocusRequester {
if (mSourceRef != null && mDeathHandler != null) {
mSourceRef.unlinkToDeath(mDeathHandler, 0);
mDeathHandler = null;
+ mFocusDispatcher = null;
}
} catch (java.util.NoSuchElementException e) {
Log.e(TAG, "FocusRequester.release() hit ", e);
@@ -275,12 +276,13 @@ public class FocusRequester {
mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
mFocusController.notifyExtPolicyFocusGrant_syncAf(toAudioFocusInfo(),
AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
- if (mFocusDispatcher != null) {
+ final IAudioFocusDispatcher fd = mFocusDispatcher;
+ if (fd != null) {
if (DEBUG) {
Log.v(TAG, "dispatching " + focusChangeToString(focusGain) + " to "
+ mClientId);
}
- mFocusDispatcher.dispatchAudioFocusChange(focusGain, mClientId);
+ fd.dispatchAudioFocusChange(focusGain, mClientId);
}
} catch (android.os.RemoteException e) {
Log.e(TAG, "Failure to signal gain of audio focus due to: ", e);
@@ -311,14 +313,15 @@ public class FocusRequester {
toAudioFocusInfo(), false /* wasDispatched */);
return;
}
- if (mFocusDispatcher != null) {
+ final IAudioFocusDispatcher fd = mFocusDispatcher;
+ if (fd != null) {
if (DEBUG) {
Log.v(TAG, "dispatching " + focusChangeToString(mFocusLossReceived) + " to "
+ mClientId);
}
mFocusController.notifyExtPolicyFocusLoss_syncAf(
toAudioFocusInfo(), true /* wasDispatched */);
- mFocusDispatcher.dispatchAudioFocusChange(mFocusLossReceived, mClientId);
+ fd.dispatchAudioFocusChange(mFocusLossReceived, mClientId);
}
}
} catch (android.os.RemoteException e) {
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 278d70b2226d..206834e9adc4 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -160,6 +160,7 @@ public class MediaFocusControl {
Log.i(TAG, "AudioFocus removeFocusStackEntry(): removing entry for "
+ clientToRemove);
stackIterator.remove();
+ // stack entry not used anymore, clear references
fr.release();
}
}
@@ -171,7 +172,7 @@ public class MediaFocusControl {
* Called synchronized on mAudioFocusLock
* Remove focus listeners from the focus stack for a particular client when it has died.
*/
- private void removeFocusStackEntryForClient(IBinder cb) {
+ private void removeFocusStackEntryOnDeath(IBinder cb) {
// is the owner of the audio focus part of the client to remove?
boolean isTopOfStackForClientToRemove = !mFocusStack.isEmpty() &&
mFocusStack.peek().hasSameBinder(cb);
@@ -181,9 +182,10 @@ public class MediaFocusControl {
while(stackIterator.hasNext()) {
FocusRequester fr = stackIterator.next();
if(fr.hasSameBinder(cb)) {
- Log.i(TAG, "AudioFocus removeFocusStackEntry(): removing entry for " + cb);
+ Log.i(TAG, "AudioFocus removeFocusStackEntryOnDeath(): removing entry for " + cb);
stackIterator.remove();
- // the client just died, no need to unlink to its death
+ // stack entry not used anymore, clear references
+ fr.release();
}
}
if (isTopOfStackForClientToRemove) {
@@ -257,14 +259,9 @@ public class MediaFocusControl {
public void binderDied() {
synchronized(mAudioFocusLock) {
- Log.w(TAG, " AudioFocus audio focus client died");
- removeFocusStackEntryForClient(mCb);
+ removeFocusStackEntryOnDeath(mCb);
}
}
-
- public IBinder getBinder() {
- return mCb;
- }
}
/**
@@ -420,6 +417,7 @@ public class MediaFocusControl {
// (premature death == death before abandoning focus)
// Register for client death notification
AudioFocusDeathHandler afdh = new AudioFocusDeathHandler(cb);
+
try {
cb.linkToDeath(afdh, 0);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 7044e60ece92..cb4bb8840b5a 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -115,6 +115,7 @@ import java.util.TreeSet;
// is satisfying one or more background NetworkRequests it is kept up in the background. If it is
// not, ConnectivityService disconnects the NetworkAgent's AsyncChannel.
public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
+
public NetworkInfo networkInfo;
// This Network object should always be used if possible, so as to encourage reuse of the
// enclosed socket factory and connection pool. Avoid creating other Network objects.
@@ -380,7 +381,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
* it might satisfy a request if it validated).
*/
public boolean isBackgroundNetwork() {
- return numForegroundNetworkRequests() == 0 && mNumBackgroundNetworkRequests > 0;
+ return !isVPN() && numForegroundNetworkRequests() == 0 && mNumBackgroundNetworkRequests > 0;
}
// Does this network satisfy request?
@@ -415,16 +416,20 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
}
int score = currentScore;
- // Use NET_CAPABILITY_VALIDATED here instead of lastValidated, this allows
- // ConnectivityService.updateCapabilities() to compute the old score prior to updating
- // networkCapabilities (with a potentially different validated state).
- if (!networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED) && !pretendValidated) {
+ if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty()) {
score -= UNVALIDATED_SCORE_PENALTY;
}
if (score < 0) score = 0;
return score;
}
+ // Return true on devices configured to ignore score penalty for wifi networks
+ // that become unvalidated (b/31075769).
+ private boolean ignoreWifiUnvalidationPenalty() {
+ boolean isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
+ return isWifi && !mConnService.avoidBadWifi() && everValidated;
+ }
+
// Get the current score for this Network. This may be modified from what the
// NetworkAgent sent, as it has modifiers applied to it.
public int getCurrentScore() {
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 99926a971bec..f7b01be48d88 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -35,7 +35,7 @@ import static android.net.NetworkCapabilities.*;
public class NetworkNotificationManager {
- public static enum NotificationType { SIGN_IN, NO_INTERNET, NETWORK_SWITCH };
+ public static enum NotificationType { SIGN_IN, NO_INTERNET, LOST_INTERNET, NETWORK_SWITCH };
private static final String NOTIFICATION_ID = "Connectivity.Notification";
@@ -91,8 +91,8 @@ public class NetworkNotificationManager {
* @param id an identifier that uniquely identifies this notification. This must match
* between show and hide calls. We use the NetID value but for legacy callers
* we concatenate the range of types with the range of NetIDs.
- * @param nai the network with which the notification is associated. For a SIGN_IN or
- * NO_INTERNET notification, this is the network we're connecting to. For a
+ * @param nai the network with which the notification is associated. For a SIGN_IN, NO_INTERNET,
+ * or LOST_INTERNET notification, this is the network we're connecting to. For a
* NETWORK_SWITCH notification it's the network that we switched from. When this network
* disconnects the notification is removed.
* @param switchToNai for a NETWORK_SWITCH notification, the network we are switching to. Null
@@ -126,6 +126,10 @@ public class NetworkNotificationManager {
if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) {
title = r.getString(R.string.wifi_no_internet, 0);
details = r.getString(R.string.wifi_no_internet_detailed);
+ } else if (notifyType == NotificationType.LOST_INTERNET &&
+ transportType == TRANSPORT_WIFI) {
+ title = r.getString(R.string.wifi_no_internet, 0);
+ details = r.getString(R.string.wifi_no_internet_detailed);
} else if (notifyType == NotificationType.SIGN_IN) {
switch (transportType) {
case TRANSPORT_WIFI:
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 7d1da01b8ca6..58c76ec7674a 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -27,6 +27,7 @@ import android.content.ServiceConnection;
import android.net.ProxyInfo;
import android.net.Uri;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -39,10 +40,10 @@ import com.android.internal.annotations.GuardedBy;
import com.android.net.IProxyCallback;
import com.android.net.IProxyPortListener;
import com.android.net.IProxyService;
-import com.android.server.IoThread;
import libcore.io.Streams;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
@@ -66,6 +67,7 @@ public class PacManager {
private static final int DELAY_1 = 0;
private static final int DELAY_4 = 3;
private static final int DELAY_LONG = 4;
+ private static final long MAX_PAC_SIZE = 20 * 1000 * 1000;
/** Keep these values up-to-date with ProxyService.java */
public static final String KEY_PROXY = "keyProxy";
@@ -123,15 +125,21 @@ public class PacManager {
}
};
+ private final HandlerThread mNetThread = new HandlerThread("android.pacmanager",
+ android.os.Process.THREAD_PRIORITY_DEFAULT);
+ private final Handler mNetThreadHandler;
+
class PacRefreshIntentReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
- IoThread.getHandler().post(mPacDownloader);
+ mNetThreadHandler.post(mPacDownloader);
}
}
public PacManager(Context context, Handler handler, int proxyMessage) {
mContext = context;
mLastPort = -1;
+ mNetThread.start();
+ mNetThreadHandler = new Handler(mNetThread.getLooper());
mPacRefreshIntent = PendingIntent.getBroadcast(
context, 0, new Intent(ACTION_PAC_REFRESH), 0);
@@ -199,7 +207,25 @@ public class PacManager {
private static String get(Uri pacUri) throws IOException {
URL url = new URL(pacUri.toString());
URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY);
- return new String(Streams.readFully(urlConnection.getInputStream()));
+ long contentLength = -1;
+ try {
+ contentLength = Long.parseLong(urlConnection.getHeaderField("Content-Length"));
+ } catch (NumberFormatException e) {
+ // Ignore
+ }
+ if (contentLength > MAX_PAC_SIZE) {
+ throw new IOException("PAC too big: " + contentLength + " bytes");
+ }
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int count;
+ while ((count = urlConnection.getInputStream().read(buffer)) != -1) {
+ bytes.write(buffer, 0, count);
+ if (bytes.size() > MAX_PAC_SIZE) {
+ throw new IOException("PAC too big");
+ }
+ }
+ return bytes.toString();
}
private int getNextDelay(int currentDelay) {
@@ -267,7 +293,7 @@ public class PacManager {
intent.setClassName(PAC_PACKAGE, PAC_SERVICE);
if ((mProxyConnection != null) && (mConnection != null)) {
// Already bound no need to bind again, just download the new file.
- IoThread.getHandler().post(mPacDownloader);
+ mNetThreadHandler.post(mPacDownloader);
return;
}
mConnection = new ServiceConnection() {
@@ -297,7 +323,7 @@ public class PacManager {
} catch (RemoteException e) {
Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e);
}
- IoThread.getHandler().post(mPacDownloader);
+ mNetThreadHandler.post(mPacDownloader);
}
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 30e839d3ead1..3efcf5954a64 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1442,8 +1442,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
+ "; generating default policy");
// Build default mobile policy, and assume usage cycle starts today
- final long warningBytes = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_networkPolicyDefaultWarning) * MB_IN_BYTES;
+ final int dataWarningConfig = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_networkPolicyDefaultWarning);
+ final long warningBytes;
+ if (dataWarningConfig == WARNING_DISABLED) {
+ warningBytes = WARNING_DISABLED;
+ } else {
+ warningBytes = dataWarningConfig * MB_IN_BYTES;
+ }
final Time time = new Time();
time.setToNow();
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index c22bfb321a5c..afd42ea67c0f 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -35,6 +35,7 @@ import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.database.ContentObserver;
+import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioSystem;
@@ -736,13 +737,14 @@ public class ZenModeHelper {
// total silence restrictions
final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
- for (int i = USAGE_UNKNOWN; i <= USAGE_VIRTUAL_SOURCE; i++) {
- if (i == USAGE_NOTIFICATION) {
- applyRestrictions(muteNotifications || muteEverything, i);
- } else if (i == USAGE_NOTIFICATION_RINGTONE) {
- applyRestrictions(muteCalls || muteEverything, i);
+ for (int usage : AudioAttributes.SDK_USAGES) {
+ final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
+ if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
+ applyRestrictions(muteNotifications || muteEverything, usage);
+ } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
+ applyRestrictions(muteCalls || muteEverything, usage);
} else {
- applyRestrictions(muteEverything, i);
+ applyRestrictions(muteEverything, usage);
}
}
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 72c549f7bec6..2e18b1c417fe 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -230,6 +230,11 @@ public final class Installer extends SystemService {
mInstaller.execute("move_ab", apkPath, instructionSet, outputPath);
}
+ public void deleteOdex(String apkPath, String instructionSet, String outputPath)
+ throws InstallerException {
+ mInstaller.execute("delete_odex", apkPath, instructionSet, outputPath);
+ }
+
private static void assertValidInstructionSet(String instructionSet)
throws InstallerException {
for (String abi : Build.SUPPORTED_ABIS) {
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 53e328c7ee5f..4387e769c7bb 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -631,17 +631,20 @@ public class LauncherAppsService extends SystemService {
public void onPackageAdded(String packageName, int uid) {
UserHandle user = new UserHandle(getChangingUserId());
final int n = mListeners.beginBroadcast();
- for (int i = 0; i < n; i++) {
- IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
- BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackageAdded")) continue;
- try {
- listener.onPackageAdded(user, packageName);
- } catch (RemoteException re) {
- Slog.d(TAG, "Callback failed ", re);
+ try {
+ for (int i = 0; i < n; i++) {
+ IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+ BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+ if (!isEnabledProfileOf(user, cookie.user, "onPackageAdded")) continue;
+ try {
+ listener.onPackageAdded(user, packageName);
+ } catch (RemoteException re) {
+ Slog.d(TAG, "Callback failed ", re);
+ }
}
+ } finally {
+ mListeners.finishBroadcast();
}
- mListeners.finishBroadcast();
super.onPackageAdded(packageName, uid);
}
@@ -650,17 +653,20 @@ public class LauncherAppsService extends SystemService {
public void onPackageRemoved(String packageName, int uid) {
UserHandle user = new UserHandle(getChangingUserId());
final int n = mListeners.beginBroadcast();
- for (int i = 0; i < n; i++) {
- IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
- BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackageRemoved")) continue;
- try {
- listener.onPackageRemoved(user, packageName);
- } catch (RemoteException re) {
- Slog.d(TAG, "Callback failed ", re);
+ try {
+ for (int i = 0; i < n; i++) {
+ IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+ BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+ if (!isEnabledProfileOf(user, cookie.user, "onPackageRemoved")) continue;
+ try {
+ listener.onPackageRemoved(user, packageName);
+ } catch (RemoteException re) {
+ Slog.d(TAG, "Callback failed ", re);
+ }
}
+ } finally {
+ mListeners.finishBroadcast();
}
- mListeners.finishBroadcast();
super.onPackageRemoved(packageName, uid);
}
@@ -669,17 +675,20 @@ public class LauncherAppsService extends SystemService {
public void onPackageModified(String packageName) {
UserHandle user = new UserHandle(getChangingUserId());
final int n = mListeners.beginBroadcast();
- for (int i = 0; i < n; i++) {
- IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
- BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackageModified")) continue;
- try {
- listener.onPackageChanged(user, packageName);
- } catch (RemoteException re) {
- Slog.d(TAG, "Callback failed ", re);
+ try {
+ for (int i = 0; i < n; i++) {
+ IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+ BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+ if (!isEnabledProfileOf(user, cookie.user, "onPackageModified")) continue;
+ try {
+ listener.onPackageChanged(user, packageName);
+ } catch (RemoteException re) {
+ Slog.d(TAG, "Callback failed ", re);
+ }
}
+ } finally {
+ mListeners.finishBroadcast();
}
- mListeners.finishBroadcast();
super.onPackageModified(packageName);
}
@@ -688,17 +697,20 @@ public class LauncherAppsService extends SystemService {
public void onPackagesAvailable(String[] packages) {
UserHandle user = new UserHandle(getChangingUserId());
final int n = mListeners.beginBroadcast();
- for (int i = 0; i < n; i++) {
- IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
- BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackagesAvailable")) continue;
- try {
- listener.onPackagesAvailable(user, packages, isReplacing());
- } catch (RemoteException re) {
- Slog.d(TAG, "Callback failed ", re);
+ try {
+ for (int i = 0; i < n; i++) {
+ IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+ BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+ if (!isEnabledProfileOf(user, cookie.user, "onPackagesAvailable")) continue;
+ try {
+ listener.onPackagesAvailable(user, packages, isReplacing());
+ } catch (RemoteException re) {
+ Slog.d(TAG, "Callback failed ", re);
+ }
}
+ } finally {
+ mListeners.finishBroadcast();
}
- mListeners.finishBroadcast();
super.onPackagesAvailable(packages);
}
@@ -707,17 +719,20 @@ public class LauncherAppsService extends SystemService {
public void onPackagesUnavailable(String[] packages) {
UserHandle user = new UserHandle(getChangingUserId());
final int n = mListeners.beginBroadcast();
- for (int i = 0; i < n; i++) {
- IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
- BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnavailable")) continue;
- try {
- listener.onPackagesUnavailable(user, packages, isReplacing());
- } catch (RemoteException re) {
- Slog.d(TAG, "Callback failed ", re);
+ try {
+ for (int i = 0; i < n; i++) {
+ IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+ BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+ if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnavailable")) continue;
+ try {
+ listener.onPackagesUnavailable(user, packages, isReplacing());
+ } catch (RemoteException re) {
+ Slog.d(TAG, "Callback failed ", re);
+ }
}
+ } finally {
+ mListeners.finishBroadcast();
}
- mListeners.finishBroadcast();
super.onPackagesUnavailable(packages);
}
@@ -726,17 +741,20 @@ public class LauncherAppsService extends SystemService {
public void onPackagesSuspended(String[] packages) {
UserHandle user = new UserHandle(getChangingUserId());
final int n = mListeners.beginBroadcast();
- for (int i = 0; i < n; i++) {
- IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
- BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackagesSuspended")) continue;
- try {
- listener.onPackagesSuspended(user, packages);
- } catch (RemoteException re) {
- Slog.d(TAG, "Callback failed ", re);
+ try {
+ for (int i = 0; i < n; i++) {
+ IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+ BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+ if (!isEnabledProfileOf(user, cookie.user, "onPackagesSuspended")) continue;
+ try {
+ listener.onPackagesSuspended(user, packages);
+ } catch (RemoteException re) {
+ Slog.d(TAG, "Callback failed ", re);
+ }
}
+ } finally {
+ mListeners.finishBroadcast();
}
- mListeners.finishBroadcast();
super.onPackagesSuspended(packages);
}
@@ -745,17 +763,20 @@ public class LauncherAppsService extends SystemService {
public void onPackagesUnsuspended(String[] packages) {
UserHandle user = new UserHandle(getChangingUserId());
final int n = mListeners.beginBroadcast();
- for (int i = 0; i < n; i++) {
- IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
- BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
- if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnsuspended")) continue;
- try {
- listener.onPackagesUnsuspended(user, packages);
- } catch (RemoteException re) {
- Slog.d(TAG, "Callback failed ", re);
+ try {
+ for (int i = 0; i < n; i++) {
+ IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+ BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+ if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnsuspended")) continue;
+ try {
+ listener.onPackagesUnsuspended(user, packages);
+ } catch (RemoteException re) {
+ Slog.d(TAG, "Callback failed ", re);
+ }
}
+ } finally {
+ mListeners.finishBroadcast();
}
- mListeners.finishBroadcast();
super.onPackagesUnsuspended(packages);
}
@@ -768,10 +789,10 @@ public class LauncherAppsService extends SystemService {
private void onShortcutChangedInner(@NonNull String packageName,
@UserIdInt int userId) {
+ final int n = mListeners.beginBroadcast();
try {
final UserHandle user = UserHandle.of(userId);
- final int n = mListeners.beginBroadcast();
for (int i = 0; i < n; i++) {
IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
@@ -803,10 +824,11 @@ public class LauncherAppsService extends SystemService {
Slog.d(TAG, "Callback failed ", re);
}
}
- mListeners.finishBroadcast();
} catch (RuntimeException e) {
// When the user is locked we get IllegalState, so just catch all.
Log.w(TAG, e.getMessage(), e);
+ } finally {
+ mListeners.finishBroadcast();
}
}
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index bff6d2d4786e..42079fb0df1b 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -31,7 +31,7 @@ import android.os.ServiceManager;
import android.os.storage.StorageManager;
import android.util.Log;
import android.util.Slog;
-
+import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.InstallerConnection;
import com.android.internal.os.InstallerConnection.InstallerException;
@@ -40,6 +40,7 @@ import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.concurrent.TimeUnit;
/**
* A service for A/B OTA dexopting.
@@ -53,6 +54,10 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
// The synthetic library dependencies denoting "no checks."
private final static String[] NO_LIBRARIES = new String[] { "&" };
+ // The amount of "available" (free - low threshold) space necessary at the start of an OTA to
+ // not bulk-delete unused apps' odex files.
+ private final static long BULK_DELETE_THRESHOLD = 1024 * 1024 * 1024; // 1GB.
+
private final Context mContext;
private final PackageManagerService mPackageManagerService;
@@ -65,6 +70,25 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
private int completeSize;
+ // MetricsLogger properties.
+
+ // Space before and after.
+ private long availableSpaceBefore;
+ private long availableSpaceAfterBulkDelete;
+ private long availableSpaceAfterDexopt;
+
+ // Packages.
+ private int importantPackageCount;
+ private int otherPackageCount;
+
+ // Number of dexopt commands. This may be different from the count of packages.
+ private int dexoptCommandCountTotal;
+ private int dexoptCommandCountExecuted;
+
+ // For spent time.
+ private long otaDexoptTimeStart;
+
+
public OtaDexoptService(Context context, PackageManagerService packageManagerService) {
this.mContext = context;
this.mPackageManagerService = packageManagerService;
@@ -128,6 +152,18 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
generatePackageDexopts(p, PackageManagerService.REASON_FIRST_BOOT));
}
completeSize = mDexoptCommands.size();
+
+ long spaceAvailable = getAvailableSpace();
+ if (spaceAvailable < BULK_DELETE_THRESHOLD) {
+ Log.i(TAG, "Low on space, deleting oat files in an attempt to free up space: "
+ + PackageManagerServiceUtils.packagesToString(others));
+ for (PackageParser.Package pkg : others) {
+ deleteOatArtifactsOfPackage(pkg);
+ }
+ }
+ long spaceAvailableNow = getAvailableSpace();
+
+ prepareMetricsLogging(important.size(), others.size(), spaceAvailable, spaceAvailableNow);
}
@Override
@@ -136,6 +172,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
Log.i(TAG, "Cleaning up OTA Dexopt state.");
}
mDexoptCommands = null;
+
+ performMetricsLogging();
}
@Override
@@ -169,28 +207,67 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
String next = mDexoptCommands.remove(0);
- if (IsFreeSpaceAvailable()) {
+ if (getAvailableSpace() > 0) {
+ dexoptCommandCountExecuted++;
+
return next;
} else {
+ if (DEBUG_DEXOPT) {
+ Log.w(TAG, "Not enough space for OTA dexopt, stopping with "
+ + (mDexoptCommands.size() + 1) + " commands left.");
+ }
mDexoptCommands.clear();
return "(no free space)";
}
}
- /**
- * Check for low space. Returns true if there's space left.
- */
- private boolean IsFreeSpaceAvailable() {
- // TODO: If apps are not installed in the internal /data partition, we should compare
- // against that storage's free capacity.
+ private long getMainLowSpaceThreshold() {
File dataDir = Environment.getDataDirectory();
@SuppressWarnings("deprecation")
long lowThreshold = StorageManager.from(mContext).getStorageLowBytes(dataDir);
if (lowThreshold == 0) {
throw new IllegalStateException("Invalid low memory threshold");
}
+ return lowThreshold;
+ }
+
+ /**
+ * Returns the difference of free space to the low-storage-space threshold. Positive values
+ * indicate free bytes.
+ */
+ private long getAvailableSpace() {
+ // TODO: If apps are not installed in the internal /data partition, we should compare
+ // against that storage's free capacity.
+ long lowThreshold = getMainLowSpaceThreshold();
+
+ File dataDir = Environment.getDataDirectory();
long usableSpace = dataDir.getUsableSpace();
- return (usableSpace >= lowThreshold);
+
+ return usableSpace - lowThreshold;
+ }
+
+ private static String getOatDir(PackageParser.Package pkg) {
+ if (!pkg.canHaveOatDir()) {
+ return null;
+ }
+ File codePath = new File(pkg.codePath);
+ if (codePath.isDirectory()) {
+ return PackageDexOptimizer.getOatDir(codePath).getAbsolutePath();
+ }
+ return null;
+ }
+
+ private void deleteOatArtifactsOfPackage(PackageParser.Package pkg) {
+ String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo);
+ for (String codePath : pkg.getAllCodePaths()) {
+ for (String isa : instructionSets) {
+ try {
+ mPackageManagerService.mInstaller.deleteOdex(codePath, isa, getOatDir(pkg));
+ } catch (InstallerException e) {
+ Log.e(TAG, "Failed deleting oat files for " + codePath, e);
+ }
+ }
+ }
}
/**
@@ -271,6 +348,55 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
}
}
+ /**
+ * Initialize logging fields.
+ */
+ private void prepareMetricsLogging(int important, int others, long spaceBegin, long spaceBulk) {
+ availableSpaceBefore = spaceBegin;
+ availableSpaceAfterBulkDelete = spaceBulk;
+ availableSpaceAfterDexopt = 0;
+
+ importantPackageCount = important;
+ otherPackageCount = others;
+
+ dexoptCommandCountTotal = mDexoptCommands.size();
+ dexoptCommandCountExecuted = 0;
+
+ otaDexoptTimeStart = System.nanoTime();
+ }
+
+ private static int inMegabytes(long value) {
+ long in_mega_bytes = value / (1024 * 1024);
+ if (in_mega_bytes > Integer.MAX_VALUE) {
+ Log.w(TAG, "Recording " + in_mega_bytes + "MB of free space, overflowing range");
+ return Integer.MAX_VALUE;
+ }
+ return (int)in_mega_bytes;
+ }
+
+ private void performMetricsLogging() {
+ long finalTime = System.nanoTime();
+
+ MetricsLogger.histogram(mContext, "ota_dexopt_available_space_before_mb",
+ inMegabytes(availableSpaceBefore));
+ MetricsLogger.histogram(mContext, "ota_dexopt_available_space_after_bulk_delete_mb",
+ inMegabytes(availableSpaceAfterBulkDelete));
+ MetricsLogger.histogram(mContext, "ota_dexopt_available_space_after_dexopt_mb",
+ inMegabytes(availableSpaceAfterDexopt));
+
+ MetricsLogger.histogram(mContext, "ota_dexopt_num_important_packages",
+ importantPackageCount);
+ MetricsLogger.histogram(mContext, "ota_dexopt_num_other_packages", otherPackageCount);
+
+ MetricsLogger.histogram(mContext, "ota_dexopt_num_commands", dexoptCommandCountTotal);
+ MetricsLogger.histogram(mContext, "ota_dexopt_num_commands_executed",
+ dexoptCommandCountExecuted);
+
+ final int elapsedTimeSeconds =
+ (int) TimeUnit.NANOSECONDS.toSeconds(finalTime - otaDexoptTimeStart);
+ MetricsLogger.histogram(mContext, "ota_dexopt_time_s", elapsedTimeSeconds);
+ }
+
private static class OTADexoptPackageDexOptimizer extends
PackageDexOptimizer.ForcedUpdatePackageDexOptimizer {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7d3658a989fd..783db051f8de 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -366,8 +366,8 @@ public class PackageManagerService extends IPackageManager.Stub {
static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false;
- // STOPSHIP; b/30256615
- private static final boolean DISABLE_EPHEMERAL_APPS = !Build.IS_DEBUGGABLE;
+ private static final boolean DISABLE_EPHEMERAL_APPS = false;
+ private static final boolean HIDE_EPHEMERAL_APIS = true;
private static final int RADIO_UID = Process.PHONE_UID;
private static final int LOG_UID = Process.LOG_UID;
@@ -6283,7 +6283,7 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public ParceledListSlice<EphemeralApplicationInfo> getEphemeralApplications(int userId) {
- if (isEphemeralDisabled()) {
+ if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
return null;
}
@@ -6307,7 +6307,7 @@ public class PackageManagerService extends IPackageManager.Stub {
enforceCrossUserPermission(Binder.getCallingUid(), userId,
true /* requireFullPermission */, false /* checkShell */,
"isEphemeral");
- if (isEphemeralDisabled()) {
+ if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
return false;
}
@@ -6325,7 +6325,7 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public byte[] getEphemeralApplicationCookie(String packageName, int userId) {
- if (isEphemeralDisabled()) {
+ if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
return null;
}
@@ -6343,7 +6343,7 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public boolean setEphemeralApplicationCookie(String packageName, byte[] cookie, int userId) {
- if (isEphemeralDisabled()) {
+ if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
return true;
}
@@ -6361,7 +6361,7 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public Bitmap getEphemeralApplicationIcon(String packageName, int userId) {
- if (isEphemeralDisabled()) {
+ if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
return null;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 9a8ebedf105e..cfd0af7635e8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -168,23 +168,8 @@ public class PackageManagerServiceUtils {
packageManagerService);
if (DEBUG_DEXOPT) {
- StringBuilder sb = new StringBuilder();
- for (PackageParser.Package pkg : result) {
- if (sb.length() > 0) {
- sb.append(", ");
- }
- sb.append(pkg.packageName);
- }
- Log.i(TAG, "Packages to be dexopted: " + sb.toString());
-
- sb.setLength(0);
- for (PackageParser.Package pkg : remainingPkgs) {
- if (sb.length() > 0) {
- sb.append(", ");
- }
- sb.append(pkg.packageName);
- }
- Log.i(TAG, "Packages skipped from dexopt: " + sb.toString());
+ Log.i(TAG, "Packages to be dexopted: " + packagesToString(result));
+ Log.i(TAG, "Packages skipped from dexopt: " + packagesToString(remainingPkgs));
}
return result;
@@ -201,4 +186,15 @@ public class PackageManagerServiceUtils {
throw ee.rethrowAsIOException();
}
}
+
+ public static String packagesToString(Collection<PackageParser.Package> c) {
+ StringBuilder sb = new StringBuilder();
+ for (PackageParser.Package pkg : c) {
+ if (sb.length() > 0) {
+ sb.append(", ");
+ }
+ sb.append(pkg.packageName);
+ }
+ return sb.toString();
+ }
}
diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java
index df51923c97d3..2af1bcb425ec 100644
--- a/services/core/java/com/android/server/pm/ShortcutLauncher.java
+++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java
@@ -17,6 +17,7 @@ package com.android.server.pm;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
+import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -151,6 +152,16 @@ class ShortcutLauncher extends ShortcutPackageItem {
return mPinnedShortcuts.remove(PackageWithUser.of(packageUserId, packageName)) != null;
}
+ public void ensureVersionInfo() {
+ final PackageInfo pi = mShortcutUser.mService.getPackageInfoWithSignatures(
+ getPackageName(), getPackageUserId());
+ if (pi == null) {
+ Slog.w(TAG, "Package not found: " + getPackageName());
+ return;
+ }
+ getPackageInfo().updateVersionInfo(pi);
+ }
+
/**
* Persist.
*/
@@ -202,7 +213,7 @@ class ShortcutLauncher extends ShortcutPackageItem {
fromBackup ? ownerUserId
: ShortcutService.parseIntAttribute(parser, ATTR_LAUNCHER_USER_ID, ownerUserId);
- final ShortcutLauncher ret = new ShortcutLauncher(shortcutUser, launcherUserId,
+ final ShortcutLauncher ret = new ShortcutLauncher(shortcutUser, ownerUserId,
launcherPackageName, launcherUserId);
ArraySet<String> ids = null;
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 1acc9552c0a1..d558b07a7a70 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -23,7 +23,6 @@ import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
-import android.os.Bundle;
import android.os.PersistableBundle;
import android.text.format.Formatter;
import android.util.ArrayMap;
@@ -145,30 +144,6 @@ class ShortcutPackage extends ShortcutPackageItem {
return mPackageUid;
}
- /**
- * Called when a shortcut is about to be published. At this point we know the publisher
- * package
- * exists (as opposed to Launcher trying to fetch shortcuts from a non-existent package), so
- * we do some initialization for the package.
- */
- private void ensurePackageVersionInfo() {
- // Make sure we have the version code for the app. We need the version code in
- // handlePackageUpdated().
- if (getPackageInfo().getVersionCode() < 0) {
- final ShortcutService s = mShortcutUser.mService;
-
- final PackageInfo pi = s.getPackageInfo(getPackageName(), getOwnerUserId());
- if (pi != null) {
- if (ShortcutService.DEBUG) {
- Slog.d(TAG, String.format("Package %s version = %d", getPackageName(),
- pi.versionCode));
- }
- getPackageInfo().updateVersionInfo(pi);
- s.scheduleSaveUser(getOwnerUserId());
- }
- }
- }
-
@Nullable
public Resources getPackageResources() {
return mShortcutUser.mService.injectGetResourcesForApplicationAsUser(
@@ -251,8 +226,6 @@ class ShortcutPackage extends ShortcutPackageItem {
Preconditions.checkArgument(newShortcut.isEnabled(),
"add/setDynamicShortcuts() cannot publish disabled shortcuts");
- ensurePackageVersionInfo();
-
newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
index e7b66fca684b..4de15de9ff71 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
@@ -20,6 +20,7 @@ import android.annotation.UserIdInt;
import android.content.pm.PackageInfo;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.backup.BackupUtils;
import libcore.io.Base64;
@@ -89,6 +90,7 @@ class ShortcutPackageInfo {
return mLastUpdateTime;
}
+ /** Set {@link #mVersionCode} and {@link #mLastUpdateTime} from a {@link PackageInfo}. */
public void updateVersionInfo(@NonNull PackageInfo pi) {
if (pi != null) {
mVersionCode = pi.versionCode;
@@ -119,7 +121,8 @@ class ShortcutPackageInfo {
return true;
}
- public static ShortcutPackageInfo generateForInstalledPackage(
+ @VisibleForTesting
+ public static ShortcutPackageInfo generateForInstalledPackageForTest(
ShortcutService s, String packageName, @UserIdInt int packageUserId) {
final PackageInfo pi = s.getPackageInfoWithSignatures(packageName, packageUserId);
if (pi.signatures == null || pi.signatures.length == 0) {
@@ -132,7 +135,7 @@ class ShortcutPackageInfo {
return ret;
}
- public void refresh(ShortcutService s, ShortcutPackageItem pkg) {
+ public void refreshSignature(ShortcutService s, ShortcutPackageItem pkg) {
if (mIsShadow) {
s.wtf("Attempted to refresh package info for shadow package " + pkg.getPackageName()
+ ", user=" + pkg.getOwnerUserId());
@@ -145,8 +148,6 @@ class ShortcutPackageInfo {
Slog.w(TAG, "Package not found: " + pkg.getPackageName());
return;
}
- mVersionCode = pi.versionCode;
- mLastUpdateTime = pi.lastUpdateTime;
mSigHashes = BackupUtils.hashSignatureArray(pi.signatures);
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 178005840ab1..1f195a7a544b 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -65,8 +65,7 @@ abstract class ShortcutPackageItem {
/**
* ID of the user who actually has this package running on. For {@link ShortcutPackage},
* this is the same thing as {@link #getOwnerUserId}, but if it's a {@link ShortcutLauncher} and
- * {@link #getOwnerUserId} is of a work profile, then this ID could be the user who owns the
- * profile.
+ * {@link #getOwnerUserId} is of work profile, then this ID is of the primary user.
*/
public int getPackageUserId() {
return mPackageUserId;
@@ -86,12 +85,12 @@ abstract class ShortcutPackageItem {
return mPackageInfo;
}
- public void refreshPackageInfoAndSave() {
+ public void refreshPackageSignatureAndSave() {
if (mPackageInfo.isShadow()) {
return; // Don't refresh for shadow user.
}
final ShortcutService s = mShortcutUser.mService;
- mPackageInfo.refresh(s, this);
+ mPackageInfo.refreshSignature(s, this);
s.scheduleSaveUser(getOwnerUserId());
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 2c61f75bd426..13f558e3dd13 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1158,7 +1158,10 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
- /** Return the per-user per-package state. */
+ /**
+ * Return the per-user per-package state. If the caller is a publisher, use
+ * {@link #getPackageShortcutsForPublisherLocked} instead.
+ */
@GuardedBy("mLock")
@NonNull
ShortcutPackage getPackageShortcutsLocked(
@@ -1166,6 +1169,16 @@ public class ShortcutService extends IShortcutService.Stub {
return getUserShortcutsLocked(userId).getPackageShortcuts(packageName);
}
+ /** Return the per-user per-package state. Use this when the caller is a publisher. */
+ @GuardedBy("mLock")
+ @NonNull
+ ShortcutPackage getPackageShortcutsForPublisherLocked(
+ @NonNull String packageName, @UserIdInt int userId) {
+ final ShortcutPackage ret = getUserShortcutsLocked(userId).getPackageShortcuts(packageName);
+ ret.getUser().onCalledByPublisher(packageName);
+ return ret;
+ }
+
@GuardedBy("mLock")
@NonNull
ShortcutLauncher getLauncherShortcutsLocked(
@@ -1634,8 +1647,7 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
@@ -1686,8 +1698,7 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
@@ -1767,8 +1778,7 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
@@ -1817,8 +1827,7 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
@@ -1847,8 +1856,7 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
@@ -1870,8 +1878,7 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
@@ -1895,8 +1902,7 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.deleteAllDynamicShortcuts();
}
packageShortcutsChanged(packageName, userId);
@@ -1951,8 +1957,7 @@ public class ShortcutService extends IShortcutService.Stub {
final ArrayList<ShortcutInfo> ret = new ArrayList<>();
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.findAll(ret, query, cloneFlags);
return new ParceledListSlice<>(ret);
@@ -1973,8 +1978,7 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
return mMaxUpdatesPerInterval - ps.getApiCallCount();
}
}
@@ -2013,8 +2017,7 @@ public class ShortcutService extends IShortcutService.Stub {
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
if (ps.findShortcutById(shortcutId) == null) {
Log.w(TAG, String.format("reportShortcutUsed: package %s doesn't have shortcut %s",
@@ -3151,9 +3154,19 @@ public class ShortcutService extends IShortcutService.Stub {
return null;
}
- user.forAllPackageItems(spi -> spi.refreshPackageInfoAndSave());
+ // Update the signatures for all packages.
+ user.forAllPackageItems(spi -> spi.refreshPackageSignatureAndSave());
+
+ // Set the version code for the launchers.
+ // We shouldn't do this for publisher packages, because we don't want to update the
+ // version code without rescanning the manifest.
+ user.forAllLaunchers(launcher -> launcher.ensureVersionInfo());
+
+ // Save to the filesystem.
+ scheduleSaveUser(userId);
+ saveDirtyInfo();
- // Then save.
+ // Then create the backup payload.
final ByteArrayOutputStream os = new ByteArrayOutputStream(32 * 1024);
try {
saveUserInternalLocked(userId, os, /* forBackup */ true);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c4834f58c01a..26839482a8d3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5646,7 +5646,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void onServiceDisconnected(ComponentName name) {
- notifyScreenshotError();
+ synchronized (mScreenshotLock) {
+ if (mScreenshotConnection != null) {
+ mContext.unbindService(mScreenshotConnection);
+ mScreenshotConnection = null;
+ mHandler.removeCallbacks(mScreenshotTimeout);
+ notifyScreenshotError();
+ }
+ }
}
};
if (mContext.bindServiceAsUser(serviceIntent, conn,
@@ -7874,7 +7881,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int delta = newRotation - oldRotation;
if (delta < 0) delta += 4;
// Likewise we don't rotate seamlessly for 180 degree rotations
- // in this case the surfaces never resize, and our logic to
+ // in this case the surfaces never resize, and our logic to
// revert the transformations on size change will fail. We could
// fix this in the future with the "tagged" frames idea.
if (delta == Surface.ROTATION_180) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8c034c667947..6156d912597c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -525,6 +525,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
static class ActiveAdmin {
private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
+ private static final String TAG_TEST_ONLY_ADMIN = "test-only-admin";
private static final String TAG_DISABLE_CAMERA = "disable-camera";
private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id";
private static final String TAG_DISABLE_CONTACTS_SEARCH = "disable-contacts-search";
@@ -617,6 +618,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
boolean encryptionRequested = false;
+ boolean testOnlyAdmin = false;
boolean disableCamera = false;
boolean disableCallerId = false;
boolean disableContactsSearch = false;
@@ -786,6 +788,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.attribute(null, ATTR_VALUE, Boolean.toString(encryptionRequested));
out.endTag(null, TAG_ENCRYPTION_REQUESTED);
}
+ if (testOnlyAdmin) {
+ out.startTag(null, TAG_TEST_ONLY_ADMIN);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(testOnlyAdmin));
+ out.endTag(null, TAG_TEST_ONLY_ADMIN);
+ }
if (disableCamera) {
out.startTag(null, TAG_DISABLE_CAMERA);
out.attribute(null, ATTR_VALUE, Boolean.toString(disableCamera));
@@ -981,6 +988,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else if (TAG_ENCRYPTION_REQUESTED.equals(tag)) {
encryptionRequested = Boolean.parseBoolean(
parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_TEST_ONLY_ADMIN.equals(tag)) {
+ testOnlyAdmin = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
} else if (TAG_DISABLE_CAMERA.equals(tag)) {
disableCamera = Boolean.parseBoolean(
parser.getAttributeValue(null, ATTR_VALUE));
@@ -1179,6 +1189,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("uid="); pw.println(getUid());
+ pw.print(prefix); pw.print("testOnlyAdmin=");
+ pw.println(testOnlyAdmin);
pw.print(prefix); pw.println("policies:");
ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
if (pols != null) {
@@ -2829,8 +2841,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
long ident = mInjector.binderClearCallingIdentity();
try {
- if (!refreshing
- && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
+ final ActiveAdmin existingAdmin
+ = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
+ if (!refreshing && existingAdmin != null) {
throw new IllegalArgumentException("Admin is already added");
}
if (policy.mRemovingAdmins.contains(adminReceiver)) {
@@ -2838,6 +2851,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"Trying to set an admin which is being removed");
}
ActiveAdmin newAdmin = new ActiveAdmin(info, /* parent */ false);
+ newAdmin.testOnlyAdmin =
+ (existingAdmin != null) ? existingAdmin.testOnlyAdmin
+ : isPackageTestOnly(adminReceiver.getPackageName(), userHandle);
policy.mAdminMap.put(adminReceiver, newAdmin);
int replaceIndex = -1;
final int N = policy.mAdminList.size();
@@ -2949,12 +2965,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
enforceShell("forceRemoveActiveAdmin");
long ident = mInjector.binderClearCallingIdentity();
try {
- if (!isPackageTestOnly(adminReceiver.getPackageName(), userHandle)) {
- throw new SecurityException("Attempt to remove non-test admin "
- + adminReceiver + " " + userHandle);
- }
- // If admin is a device or profile owner tidy that up first.
synchronized (this) {
+ if (!isAdminTestOnlyLocked(adminReceiver, userHandle)) {
+ throw new SecurityException("Attempt to remove non-test admin "
+ + adminReceiver + " " + userHandle);
+ }
+
+ // If admin is a device or profile owner tidy that up first.
if (isDeviceOwner(adminReceiver, userHandle)) {
clearDeviceOwnerLocked(getDeviceOwnerAdminLocked(), userHandle);
}
@@ -2972,6 +2989,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ /**
+ * Return if a given package has testOnly="true", in which case we'll relax certain rules
+ * for CTS.
+ *
+ * DO NOT use this method except in {@link #setActiveAdmin}. Use {@link #isAdminTestOnlyLocked}
+ * to check wehter an active admin is test-only or not.
+ *
+ * The system allows this flag to be changed when an app is updated, which is not good
+ * for us. So we persist the flag in {@link ActiveAdmin} when an admin is first installed,
+ * and used the persisted version in actual checks. (See b/31382361 and b/28928996)
+ */
private boolean isPackageTestOnly(String packageName, int userHandle) {
final ApplicationInfo ai;
try {
@@ -2988,6 +3016,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return (ai.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0;
}
+ /**
+ * See {@link #isPackageTestOnly}.
+ */
+ private boolean isAdminTestOnlyLocked(ComponentName who, int userHandle) {
+ final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
+ return (admin != null) && admin.testOnlyAdmin;
+ }
+
private void enforceShell(String method) {
final int callingUid = Binder.getCallingUid();
if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID) {
@@ -6227,7 +6263,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* The profile owner can only be set before the user setup phase has completed,
* except for:
* - SYSTEM_UID
- * - adb if there are no accounts. (But see {@link #hasIncompatibleAccounts})
+ * - adb if there are no accounts. (But see {@link #hasIncompatibleAccountsLocked})
*/
private void enforceCanSetProfileOwnerLocked(@Nullable ComponentName owner, int userHandle) {
UserInfo info = getUserInfo(userHandle);
@@ -6250,7 +6286,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int callingUid = mInjector.binderGetCallingUid();
if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
if (hasUserSetupCompleted(userHandle)
- && hasIncompatibleAccounts(userHandle, owner)) {
+ && hasIncompatibleAccountsLocked(userHandle, owner)) {
throw new IllegalStateException("Not allowed to set the profile owner because "
+ "there are already some accounts on the profile");
}
@@ -6274,7 +6310,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
enforceCanManageProfileAndDeviceOwners();
}
- final int code = checkSetDeviceOwnerPreCondition(owner, userId, isAdb);
+ final int code = checkSetDeviceOwnerPreConditionLocked(owner, userId, isAdb);
switch (code) {
case CODE_OK:
return;
@@ -8491,7 +8527,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* The device owner can only be set before the setup phase of the primary user has completed,
* except for adb command if no accounts or additional users are present on the device.
*/
- private synchronized @DeviceOwnerPreConditionCode int checkSetDeviceOwnerPreCondition(
+ private synchronized @DeviceOwnerPreConditionCode int checkSetDeviceOwnerPreConditionLocked(
@Nullable ComponentName owner, int deviceOwnerUserId, boolean isAdb) {
if (mOwners.hasDeviceOwner()) {
return CODE_HAS_DEVICE_OWNER;
@@ -8509,7 +8545,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (mUserManager.getUserCount() > 1) {
return CODE_NONSYSTEM_USER_EXISTS;
}
- if (hasIncompatibleAccounts(UserHandle.USER_SYSTEM, owner)) {
+ if (hasIncompatibleAccountsLocked(UserHandle.USER_SYSTEM, owner)) {
return CODE_ACCOUNTS_NOT_EMPTY;
}
} else {
@@ -8535,8 +8571,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private boolean isDeviceOwnerProvisioningAllowed(int deviceOwnerUserId) {
- return CODE_OK == checkSetDeviceOwnerPreCondition(
- /* owner unknown */ null, deviceOwnerUserId, /* isAdb */ false);
+ synchronized (this) {
+ return CODE_OK == checkSetDeviceOwnerPreConditionLocked(
+ /* owner unknown */ null, deviceOwnerUserId, /* isAdb */ false);
+ }
}
private boolean hasFeatureManagedUsers() {
@@ -9105,7 +9143,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* ..._DISALLOWED, return true.
* - Otherwise return false.
*/
- private boolean hasIncompatibleAccounts(int userId, @Nullable ComponentName owner) {
+ private boolean hasIncompatibleAccountsLocked(int userId, @Nullable ComponentName owner) {
final long token = mInjector.binderClearCallingIdentity();
try {
final AccountManager am = AccountManager.get(mContext);
@@ -9143,7 +9181,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Owner is unknown. Suppose it's not test-only
compatible = false;
log = "Only test-only device/profile owner can be installed with accounts";
- } else if (isPackageTestOnly(owner.getPackageName(), userId)) {
+ } else if (isAdminTestOnlyLocked(owner, userId)) {
if (compatible) {
log = "Installing test-only owner " + owner;
} else {
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 270d818b4ce3..4c7545240c23 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -19,6 +19,7 @@ package android.net.apf;
import static android.system.OsConstants.*;
import android.os.SystemClock;
+import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.net.apf.ApfGenerator;
@@ -44,6 +45,7 @@ import com.android.internal.util.IndentingPrintWriter;
import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.Thread;
+import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
@@ -181,6 +183,7 @@ public class ApfFilter {
private static final int IPV4_PROTOCOL_OFFSET = ETH_HEADER_LEN + 9;
private static final int IPV4_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 16;
private static final int IPV4_ANY_HOST_ADDRESS = 0;
+ private static final int IPV4_BROADCAST_ADDRESS = -1; // 255.255.255.255
private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8;
@@ -229,6 +232,9 @@ public class ApfFilter {
// Our IPv4 address, if we have just one, otherwise null.
@GuardedBy("this")
private byte[] mIPv4Address;
+ // The subnet prefix length of our IPv4 network. Only valid if mIPv4Address is not null.
+ @GuardedBy("this")
+ private int mIPv4PrefixLength;
@VisibleForTesting
ApfFilter(ApfCapabilities apfCapabilities, NetworkInterface networkInterface,
@@ -364,26 +370,6 @@ public class ApfFilter {
// Can't be static because it's in a non-static inner class.
// TODO: Make this static once RA is its own class.
- private int uint8(byte b) {
- return b & 0xff;
- }
-
- private int uint16(short s) {
- return s & 0xffff;
- }
-
- private long uint32(int i) {
- return i & 0xffffffffL;
- }
-
- private long getUint16(ByteBuffer buffer, int position) {
- return uint16(buffer.getShort(position));
- }
-
- private long getUint32(ByteBuffer buffer, int position) {
- return uint32(buffer.getInt(position));
- }
-
private void prefixOptionToString(StringBuffer sb, int offset) {
String prefix = IPv6AddresstoString(offset + 16);
int length = uint8(mPacket.get(offset + 2));
@@ -737,39 +723,57 @@ public class ApfFilter {
// Here's a basic summary of what the IPv4 filter program does:
//
// if filtering multicast (i.e. multicast lock not held):
- // if it's multicast:
- // drop
- // if it's not broadcast:
+ // if it's DHCP destined to our MAC:
// pass
- // if it's not DHCP destined to our MAC:
+ // if it's L2 broadcast:
+ // drop
+ // if it's IPv4 multicast:
+ // drop
+ // if it's IPv4 broadcast:
// drop
// pass
if (mMulticastFilter) {
- // Check for multicast destination address range
- gen.addLoad8(Register.R0, IPV4_DEST_ADDR_OFFSET);
- gen.addAnd(0xf0);
- gen.addJumpIfR0Equals(0xe0, gen.DROP_LABEL);
+ final String skipDhcpv4Filter = "skip_dhcp_v4_filter";
- // Drop all broadcasts besides DHCP addressed to us
- // If not a broadcast packet, pass
- gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
- gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
- // If not UDP, drop
+ // Pass DHCP addressed to us.
+ // Check it's UDP.
gen.addLoad8(Register.R0, IPV4_PROTOCOL_OFFSET);
- gen.addJumpIfR0NotEquals(IPPROTO_UDP, gen.DROP_LABEL);
- // If fragment, drop. This matches the BPF filter installed by the DHCP client.
+ gen.addJumpIfR0NotEquals(IPPROTO_UDP, skipDhcpv4Filter);
+ // Check it's not a fragment. This matches the BPF filter installed by the DHCP client.
gen.addLoad16(Register.R0, IPV4_FRAGMENT_OFFSET_OFFSET);
- gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, gen.DROP_LABEL);
- // If not to DHCP client port, drop
+ gen.addJumpIfR0AnyBitsSet(IPV4_FRAGMENT_OFFSET_MASK, skipDhcpv4Filter);
+ // Check it's addressed to DHCP client port.
gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
gen.addLoad16Indexed(Register.R0, UDP_DESTINATION_PORT_OFFSET);
- gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, gen.DROP_LABEL);
- // If not DHCP to our MAC address, drop
+ gen.addJumpIfR0NotEquals(DHCP_CLIENT_PORT, skipDhcpv4Filter);
+ // Check it's DHCP to our MAC address.
gen.addLoadImmediate(Register.R0, DHCP_CLIENT_MAC_OFFSET);
// NOTE: Relies on R1 containing IPv4 header offset.
gen.addAddR1();
- gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, gen.DROP_LABEL);
+ gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, skipDhcpv4Filter);
+ gen.addJump(gen.PASS_LABEL);
+
+ // Drop all multicasts/broadcasts.
+ gen.defineLabel(skipDhcpv4Filter);
+
+ // If IPv4 destination address is in multicast range, drop.
+ gen.addLoad8(Register.R0, IPV4_DEST_ADDR_OFFSET);
+ gen.addAnd(0xf0);
+ gen.addJumpIfR0Equals(0xe0, gen.DROP_LABEL);
+
+ // If IPv4 broadcast packet, drop regardless of L2 (b/30231088).
+ gen.addLoad32(Register.R0, IPV4_DEST_ADDR_OFFSET);
+ gen.addJumpIfR0Equals(IPV4_BROADCAST_ADDRESS, gen.DROP_LABEL);
+ if (mIPv4Address != null && mIPv4PrefixLength < 31) {
+ int broadcastAddr = ipv4BroadcastAddress(mIPv4Address, mIPv4PrefixLength);
+ gen.addJumpIfR0Equals(broadcastAddr, gen.DROP_LABEL);
+ }
+
+ // If L2 broadcast packet, drop.
+ gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
+ gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
+ gen.addJump(gen.DROP_LABEL);
}
// Otherwise, pass
@@ -1062,26 +1066,32 @@ public class ApfFilter {
}
}
- // Find the single IPv4 address if there is one, otherwise return null.
- private static byte[] findIPv4Address(LinkProperties lp) {
- byte[] ipv4Address = null;
- for (InetAddress inetAddr : lp.getAddresses()) {
- byte[] addr = inetAddr.getAddress();
- if (addr.length != 4) continue;
- // More than one IPv4 address, abort
- if (ipv4Address != null && !Arrays.equals(ipv4Address, addr)) return null;
- ipv4Address = addr;
+ /** Find the single IPv4 LinkAddress if there is one, otherwise return null. */
+ private static LinkAddress findIPv4LinkAddress(LinkProperties lp) {
+ LinkAddress ipv4Address = null;
+ for (LinkAddress address : lp.getLinkAddresses()) {
+ if (!(address.getAddress() instanceof Inet4Address)) {
+ continue;
+ }
+ if (ipv4Address != null && !ipv4Address.isSameAddressAs(address)) {
+ // More than one IPv4 address, abort.
+ return null;
+ }
+ ipv4Address = address;
}
return ipv4Address;
}
public synchronized void setLinkProperties(LinkProperties lp) {
// NOTE: Do not keep a copy of LinkProperties as it would further duplicate state.
- byte[] ipv4Address = findIPv4Address(lp);
- // If ipv4Address is the same as mIPv4Address, then there's no change, just return.
- if (Arrays.equals(ipv4Address, mIPv4Address)) return;
- // Otherwise update mIPv4Address and install new program.
- mIPv4Address = ipv4Address;
+ final LinkAddress ipv4Address = findIPv4LinkAddress(lp);
+ final byte[] addr = (ipv4Address != null) ? ipv4Address.getAddress().getAddress() : null;
+ final int prefix = (ipv4Address != null) ? ipv4Address.getPrefixLength() : 0;
+ if ((prefix == mIPv4PrefixLength) && Arrays.equals(addr, mIPv4Address)) {
+ return;
+ }
+ mIPv4Address = addr;
+ mIPv4PrefixLength = prefix;
installNewProgramLocked();
}
@@ -1127,4 +1137,38 @@ public class ApfFilter {
pw.decreaseIndent();
}
}
+
+ private static int uint8(byte b) {
+ return b & 0xff;
+ }
+
+ private static int uint16(short s) {
+ return s & 0xffff;
+ }
+
+ private static long uint32(int i) {
+ return i & 0xffffffffL;
+ }
+
+ private static long getUint16(ByteBuffer buffer, int position) {
+ return uint16(buffer.getShort(position));
+ }
+
+ private static long getUint32(ByteBuffer buffer, int position) {
+ return uint32(buffer.getInt(position));
+ }
+
+ // TODO: move to android.net.NetworkUtils
+ @VisibleForTesting
+ public static int ipv4BroadcastAddress(byte[] addrBytes, int prefixLength) {
+ return bytesToInt(addrBytes) | (int) (uint32(-1) >>> prefixLength);
+ }
+
+ @VisibleForTesting
+ public static int bytesToInt(byte[] addrBytes) {
+ return (uint8(addrBytes[0]) << 24)
+ + (uint8(addrBytes[1]) << 16)
+ + (uint8(addrBytes[2]) << 8)
+ + (uint8(addrBytes[3]));
+ }
}
diff --git a/services/tests/servicestests/src/android/net/apf/ApfTest.java b/services/tests/servicestests/src/android/net/apf/ApfTest.java
index 26bcf7cf25d0..f7c61d15bb5f 100644
--- a/services/tests/servicestests/src/android/net/apf/ApfTest.java
+++ b/services/tests/servicestests/src/android/net/apf/ApfTest.java
@@ -20,6 +20,9 @@ import static android.system.OsConstants.*;
import com.android.frameworks.servicestests.R;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
import android.net.apf.ApfCapabilities;
import android.net.apf.ApfFilter;
import android.net.apf.ApfGenerator;
@@ -28,8 +31,6 @@ import android.net.apf.ApfGenerator.Register;
import android.net.ip.IpManager;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.RaEvent;
-import android.net.LinkAddress;
-import android.net.LinkProperties;
import android.os.ConditionVariable;
import android.os.Parcelable;
import android.system.ErrnoException;
@@ -604,7 +605,7 @@ public class ApfTest extends AndroidTestCase {
public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
IpConnectivityLog log) throws Exception {
- super(new ApfCapabilities(2, 1536, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
+ super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
ipManagerCallback, multicastFilter, log);
}
@@ -713,7 +714,7 @@ public class ApfTest extends AndroidTestCase {
private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1};
- private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, (byte) 255, (byte) 255};
+ private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2};
private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0};
@@ -721,7 +722,13 @@ public class ApfTest extends AndroidTestCase {
@LargeTest
public void testApfFilterIPv4() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
+ LinkProperties lp = new LinkProperties();
+ lp.addLinkAddress(link);
+
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
+ apfFilter.setLinkProperties(lp);
+
byte[] program = ipManagerCallback.getApfProgram();
// Verify empty packet of 100 zero bytes is passed
@@ -734,11 +741,11 @@ public class ApfTest extends AndroidTestCase {
put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_IPV4_ADDR);
assertPass(program, packet.array());
- // Verify L2 unicast to IPv4 broadcast addresses is passed (b/30231088)
+ // Verify L2 unicast to IPv4 broadcast addresses is dropped (b/30231088)
put(packet, IPV4_DEST_ADDR_OFFSET, IPV4_BROADCAST_ADDRESS);
- assertPass(program, packet.array());
+ assertDrop(program, packet.array());
put(packet, IPV4_DEST_ADDR_OFFSET, MOCK_BROADCAST_IPV4_ADDR);
- assertPass(program, packet.array());
+ assertDrop(program, packet.array());
// Verify multicast/broadcast IPv4, not DHCP to us, is dropped
put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
@@ -795,15 +802,21 @@ public class ApfTest extends AndroidTestCase {
@LargeTest
public void testApfFilterMulticast() throws Exception {
- MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
- ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
- byte[] program = ipManagerCallback.getApfProgram();
-
final byte[] unicastIpv4Addr = {(byte)192,0,2,63};
- final byte[] broadcastIpv4Addr = {(byte)192,0,(byte)255,(byte)255};
+ final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
+ MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
+ LinkProperties lp = new LinkProperties();
+ lp.addLinkAddress(link);
+
+ ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
+ apfFilter.setLinkProperties(lp);
+
+ byte[] program = ipManagerCallback.getApfProgram();
+
// Construct IPv4 and IPv6 multicast packets.
ByteBuffer mcastv4packet = ByteBuffer.wrap(new byte[100]);
mcastv4packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
@@ -846,7 +859,7 @@ public class ApfTest extends AndroidTestCase {
assertDrop(program, mcastv6packet.array());
assertDrop(program, bcastv4packet1.array());
assertDrop(program, bcastv4packet2.array());
- assertPass(program, bcastv4unicastl2packet.array());
+ assertDrop(program, bcastv4unicastl2packet.array());
// Turn off multicast filter and verify it's off
ipManagerCallback.resetApfProgramWait();
@@ -862,11 +875,12 @@ public class ApfTest extends AndroidTestCase {
ipManagerCallback.resetApfProgramWait();
apfFilter.shutdown();
apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
+ apfFilter.setLinkProperties(lp);
program = ipManagerCallback.getApfProgram();
assertDrop(program, mcastv4packet.array());
assertDrop(program, mcastv6packet.array());
assertDrop(program, bcastv4packet1.array());
- assertPass(program, bcastv4unicastl2packet.array());
+ assertDrop(program, bcastv4unicastl2packet.array());
// Verify that ICMPv6 multicast is not dropped.
mcastv6packet.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
@@ -1152,4 +1166,30 @@ public class ApfTest extends AndroidTestCase {
*/
private native static boolean compareBpfApf(String filter, String pcap_filename,
byte[] apf_program);
+
+ public void testBytesToInt() {
+ assertEquals(0x00000000, ApfFilter.bytesToInt(IPV4_ANY_HOST_ADDR));
+ assertEquals(0xffffffff, ApfFilter.bytesToInt(IPV4_BROADCAST_ADDRESS));
+ assertEquals(0x0a000001, ApfFilter.bytesToInt(MOCK_IPV4_ADDR));
+ assertEquals(0x0a000002, ApfFilter.bytesToInt(ANOTHER_IPV4_ADDR));
+ assertEquals(0x0a001fff, ApfFilter.bytesToInt(MOCK_BROADCAST_IPV4_ADDR));
+ assertEquals(0xe0000001, ApfFilter.bytesToInt(MOCK_MULTICAST_IPV4_ADDR));
+ }
+
+ public void testBroadcastAddress() throws Exception {
+ assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0));
+ assertEqualsIp("0.0.0.0", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 32));
+ assertEqualsIp("0.0.3.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 22));
+ assertEqualsIp("0.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 8));
+
+ assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 0));
+ assertEqualsIp("10.0.0.1", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 32));
+ assertEqualsIp("10.0.0.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 24));
+ assertEqualsIp("10.0.255.255", ApfFilter.ipv4BroadcastAddress(MOCK_IPV4_ADDR, 16));
+ }
+
+ public void assertEqualsIp(String expected, int got) throws Exception {
+ int want = ApfFilter.bytesToInt(InetAddress.getByName(expected).getAddress());
+ assertEquals(want, got);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 59ccbd93f3fb..ace6c6e86a66 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -25,6 +25,7 @@ import static android.net.NetworkCapabilities.*;
import static org.mockito.Mockito.mock;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -137,7 +138,8 @@ public class ConnectivityServiceTest extends AndroidTestCase {
@Override
public Object getSystemService(String name) {
- if (name == Context.CONNECTIVITY_SERVICE) return mCm;
+ if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
+ if (Context.NOTIFICATION_SERVICE.equals(name)) return mock(NotificationManager.class);
return super.getSystemService(name);
}
@@ -717,6 +719,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
}
public void tearDown() throws Exception {
+ setMobileDataAlwaysOn(false);
if (mCellNetworkAgent != null) { mCellNetworkAgent.disconnect(); }
if (mWiFiNetworkAgent != null) { mWiFiNetworkAgent.disconnect(); }
mCellNetworkAgent = mWiFiNetworkAgent = null;
@@ -1814,6 +1817,85 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mCm.unregisterNetworkCallback(cellNetworkCallback);
}
+ private void setMobileDataAlwaysOn(boolean enable) {
+ ContentResolver cr = mServiceContext.getContentResolver();
+ Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
+ mService.updateMobileDataAlwaysOn();
+ mService.waitForIdle();
+ }
+
+ private boolean isForegroundNetwork(MockNetworkAgent network) {
+ NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
+ assertNotNull(nc);
+ return nc.hasCapability(NET_CAPABILITY_FOREGROUND);
+ }
+
+ @SmallTest
+ public void testBackgroundNetworks() throws Exception {
+ // Create a background request. We can't do this ourselves because ConnectivityService
+ // doesn't have an API for it. So just turn on mobile data always on.
+ setMobileDataAlwaysOn(true);
+ final NetworkRequest request = new NetworkRequest.Builder().build();
+ final NetworkRequest fgRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_FOREGROUND).build();
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ final TestNetworkCallback fgCallback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(request, callback);
+ mCm.registerNetworkCallback(fgRequest, fgCallback);
+
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ callback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ assertTrue(isForegroundNetwork(mCellNetworkAgent));
+
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
+
+ // When wifi connects, cell lingers.
+ callback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+ fgCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ assertTrue(isForegroundNetwork(mCellNetworkAgent));
+ assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
+
+ // When lingering is complete, cell is still there but is now in the background.
+ fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS);
+ callback.assertNoCallback();
+ assertFalse(isForegroundNetwork(mCellNetworkAgent));
+ assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
+
+ // File a cell request and check that cell comes into the foreground.
+ final NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ final TestNetworkCallback cellCallback = new TestNetworkCallback();
+ mCm.requestNetwork(cellRequest, cellCallback);
+ cellCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ callback.assertNoCallback(); // Because the network is already up.
+ assertTrue(isForegroundNetwork(mCellNetworkAgent));
+ assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
+
+ // Release the request. The network immediately goes into the background, since it was not
+ // lingering.
+ mCm.unregisterNetworkCallback(cellCallback);
+ fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ callback.assertNoCallback();
+ assertFalse(isForegroundNetwork(mCellNetworkAgent));
+ assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
+
+ // Disconnect wifi and check that cell is foreground again.
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ assertTrue(isForegroundNetwork(mCellNetworkAgent));
+
+ mCm.unregisterNetworkCallback(callback);
+ mCm.unregisterNetworkCallback(fgCallback);
+ }
+
@SmallTest
public void testRequestBenchmark() throws Exception {
// Benchmarks connecting and switching performance in the presence of a large number of
@@ -1919,8 +2001,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
// Turn on mobile data always on. The factory starts looking again.
testFactory.expectAddRequests(1);
- Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, 1);
- mService.updateMobileDataAlwaysOn();
+ setMobileDataAlwaysOn(true);
testFactory.waitForNetworkRequests(2);
assertTrue(testFactory.getMyStartRequested());
@@ -1940,8 +2021,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
// Turn off mobile data always on and expect the request to disappear...
testFactory.expectRemoveRequests(1);
- Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, 0);
- mService.updateMobileDataAlwaysOn();
+ setMobileDataAlwaysOn(false);
testFactory.waitForNetworkRequests(1);
// ... and cell data to be torn down.
@@ -1953,6 +2033,79 @@ public class ConnectivityServiceTest extends AndroidTestCase {
handlerThread.quit();
}
+ @SmallTest
+ public void testAvoidBadWifiSetting() throws Exception {
+ ContentResolver cr = mServiceContext.getContentResolver();
+
+ // File a request for cell to ensure it doesn't go down.
+ final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ mCm.requestNetwork(cellRequest, cellNetworkCallback);
+
+ TestNetworkCallback defaultCallback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(defaultCallback);
+
+ NetworkRequest validatedWifiRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .addCapability(NET_CAPABILITY_VALIDATED)
+ .build();
+ TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
+
+ // Takes effect on every rematch.
+ Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
+
+ // Bring up validated cell.
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ Network cellNetwork = mCellNetworkAgent.getNetwork();
+
+ // Bring up validated wifi.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
+ defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+ validatedWifiCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+ Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
+
+ // Fail validation on wifi.
+ mWiFiNetworkAgent.getWrappedNetworkMonitor().gen204ProbeResult = 599;
+ mCm.reportNetworkConnectivity(wifiNetwork, false);
+ validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+ // Because avoid bad wifi is off, we don't switch to cellular.
+ defaultCallback.assertNoCallback();
+ assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
+ NET_CAPABILITY_VALIDATED));
+ assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
+ NET_CAPABILITY_VALIDATED));
+ assertEquals(mCm.getActiveNetwork(), wifiNetwork);
+
+ // Simulate the user selecting "switch" on the dialog.
+ Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
+ mService.updateNetworkAvoidBadWifi();
+
+ // We now switch to cell.
+ defaultCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ assertFalse(mCm.getNetworkCapabilities(wifiNetwork).hasCapability(
+ NET_CAPABILITY_VALIDATED));
+ assertTrue(mCm.getNetworkCapabilities(cellNetwork).hasCapability(
+ NET_CAPABILITY_VALIDATED));
+ assertEquals(mCm.getActiveNetwork(), cellNetwork);
+
+ // If cell goes down, we switch to wifi.
+ mCellNetworkAgent.disconnect();
+ defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ defaultCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+ validatedWifiCallback.assertNoCallback();
+
+ mCm.unregisterNetworkCallback(cellNetworkCallback);
+ mCm.unregisterNetworkCallback(validatedWifiCallback);
+ mCm.unregisterNetworkCallback(defaultCallback);
+ }
+
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 143398f63860..3cfdc329a971 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -3813,9 +3813,9 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "sig1");
addPackage(CALLING_PACKAGE_2, CALLING_UID_1, 10, "sig1", "sig2");
- final ShortcutPackageInfo spi1 = ShortcutPackageInfo.generateForInstalledPackage(
+ final ShortcutPackageInfo spi1 = ShortcutPackageInfo.generateForInstalledPackageForTest(
mService, CALLING_PACKAGE_1, USER_0);
- final ShortcutPackageInfo spi2 = ShortcutPackageInfo.generateForInstalledPackage(
+ final ShortcutPackageInfo spi2 = ShortcutPackageInfo.generateForInstalledPackageForTest(
mService, CALLING_PACKAGE_2, USER_0);
checkCanRestoreTo(true, spi1, 10, "sig1");
@@ -5661,6 +5661,32 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_P0);
});
});
+ // Check the user-IDs.
+ assertEquals(USER_0,
+ mService.getUserShortcutsLocked(USER_0).getPackageShortcuts(CALLING_PACKAGE_1)
+ .getOwnerUserId());
+ assertEquals(USER_0,
+ mService.getUserShortcutsLocked(USER_0).getPackageShortcuts(CALLING_PACKAGE_1)
+ .getPackageUserId());
+ assertEquals(USER_P0,
+ mService.getUserShortcutsLocked(USER_P0).getPackageShortcuts(CALLING_PACKAGE_1)
+ .getOwnerUserId());
+ assertEquals(USER_P0,
+ mService.getUserShortcutsLocked(USER_P0).getPackageShortcuts(CALLING_PACKAGE_1)
+ .getPackageUserId());
+
+ assertEquals(USER_0,
+ mService.getUserShortcutsLocked(USER_0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+ .getOwnerUserId());
+ assertEquals(USER_0,
+ mService.getUserShortcutsLocked(USER_0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+ .getPackageUserId());
+ assertEquals(USER_P0,
+ mService.getUserShortcutsLocked(USER_P0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+ .getOwnerUserId());
+ assertEquals(USER_0,
+ mService.getUserShortcutsLocked(USER_P0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+ .getPackageUserId());
}
public void testOnApplicationActive_permission() {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 828477302245..04104b5c70d7 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -94,7 +94,7 @@ public class UsageStatsService extends SystemService implements
static final String TAG = "UsageStatsService";
- static final boolean DEBUG = false;
+ static final boolean DEBUG = false; // Never submit with true
static final boolean COMPRESS_TIME = false;
private static final long TEN_SECONDS = 10 * 1000;
@@ -139,8 +139,8 @@ public class UsageStatsService extends SystemService implements
long mSystemTimeSnapshot;
boolean mAppIdleEnabled;
- boolean mAppIdleParoled;
- private boolean mScreenOn;
+ boolean mAppIdleTempParoled;
+ boolean mCharging;
private long mLastAppIdleParoledTime;
private volatile boolean mPendingOneTimeCheckIdleStates;
@@ -191,7 +191,7 @@ public class UsageStatsService extends SystemService implements
mAppIdleEnabled = getContext().getResources().getBoolean(
com.android.internal.R.bool.config_enableAutoPowerModes);
if (mAppIdleEnabled) {
- IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING);
+ IntentFilter deviceStates = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
deviceStates.addAction(BatteryManager.ACTION_DISCHARGING);
deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
getContext().registerReceiver(new DeviceStateReceiver(), deviceStates);
@@ -237,7 +237,7 @@ public class UsageStatsService extends SystemService implements
mSystemServicesReady = true;
} else if (phase == PHASE_BOOT_COMPLETED) {
- setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
+ setChargingState(getContext().getSystemService(BatteryManager.class).isCharging());
}
}
@@ -284,9 +284,8 @@ public class UsageStatsService extends SystemService implements
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- if (BatteryManager.ACTION_CHARGING.equals(action)
- || BatteryManager.ACTION_DISCHARGING.equals(action)) {
- setAppIdleParoled(BatteryManager.ACTION_CHARGING.equals(action));
+ if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
+ setChargingState(intent.getIntExtra("plugged", 0) != 0);
} else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
onDeviceIdleModeChanged();
}
@@ -376,12 +375,21 @@ public class UsageStatsService extends SystemService implements
}
}
+ void setChargingState(boolean charging) {
+ synchronized (mLock) {
+ if (mCharging != charging) {
+ mCharging = charging;
+ postParoleStateChanged();
+ }
+ }
+ }
+
/** Paroled here means temporary pardon from being inactive */
void setAppIdleParoled(boolean paroled) {
synchronized (mLock) {
- if (mAppIdleParoled != paroled) {
- mAppIdleParoled = paroled;
- if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleParoled);
+ if (mAppIdleTempParoled != paroled) {
+ mAppIdleTempParoled = paroled;
+ if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleTempParoled);
if (paroled) {
postParoleEndTimeout();
} else {
@@ -393,6 +401,12 @@ public class UsageStatsService extends SystemService implements
}
}
+ boolean isParoledOrCharging() {
+ synchronized (mLock) {
+ return mAppIdleTempParoled || mCharging;
+ }
+ }
+
private void postNextParoleTimeout() {
if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT");
mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT);
@@ -495,7 +509,7 @@ public class UsageStatsService extends SystemService implements
/** Check if it's been a while since last parole and let idle apps do some work */
void checkParoleTimeout() {
synchronized (mLock) {
- if (!mAppIdleParoled) {
+ if (!mAppIdleTempParoled) {
final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
@@ -786,7 +800,7 @@ public class UsageStatsService extends SystemService implements
}
boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime) {
- if (mAppIdleParoled) {
+ if (isParoledOrCharging()) {
return false;
}
return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime);
@@ -989,8 +1003,9 @@ public class UsageStatsService extends SystemService implements
}
void informParoleStateChanged() {
+ final boolean paroled = isParoledOrCharging();
for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
- listener.onParoleStateChanged(mAppIdleParoled);
+ listener.onParoleStateChanged(paroled);
}
}
@@ -1072,9 +1087,9 @@ public class UsageStatsService extends SystemService implements
pw.println();
pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
- pw.print(" mAppIdleParoled="); pw.print(mAppIdleParoled);
- pw.print(" mScreenOn="); pw.println(mScreenOn);
- pw.print("mLastAppIdleParoledTime=");
+ pw.print(" mAppIdleTempParoled="); pw.print(mAppIdleTempParoled);
+ pw.print(" mCharging="); pw.print(mCharging);
+ pw.print(" mLastAppIdleParoledTime=");
TimeUtils.formatDuration(mLastAppIdleParoledTime, pw);
pw.println();
}
@@ -1139,7 +1154,8 @@ public class UsageStatsService extends SystemService implements
break;
case MSG_PAROLE_STATE_CHANGED:
- if (DEBUG) Slog.d(TAG, "Parole state changed: " + mAppIdleParoled);
+ if (DEBUG) Slog.d(TAG, "Parole state: " + mAppIdleTempParoled
+ + ", Charging state:" + mCharging);
informParoleStateChanged();
break;
@@ -1466,7 +1482,7 @@ public class UsageStatsService extends SystemService implements
@Override
public boolean isAppIdleParoleOn() {
- return mAppIdleParoled;
+ return isParoledOrCharging();
}
@Override
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index d6a2ee3c2400..c6cb61d4fd32 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -433,18 +433,11 @@ public class CarrierConfigManager {
"disable_severe_when_extreme_disabled_bool";
/**
- * The data call APN retry configuration for default type APN.
+ * The data call retry configuration for different types of APN.
* @hide
*/
- public static final String KEY_CARRIER_DATA_CALL_RETRY_CONFIG_DEFAULT_STRING =
- "carrier_data_call_retry_config_default_string";
-
- /**
- * The data call APN retry configuration for other type APNs.
- * @hide
- */
- public static final String KEY_CARRIER_DATA_CALL_RETRY_CONFIG_OTHERS_STRING =
- "carrier_data_call_retry_config_others_string";
+ public static final String KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS =
+ "carrier_data_call_retry_config_strings";
/**
* Delay between trying APN from the pool
@@ -668,6 +661,13 @@ public class CarrierConfigManager {
public static final String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
/**
+ * APN types that user is not allowed to modify
+ * @hide
+ */
+ public static final String KEY_READ_ONLY_APN_TYPES_STRING_ARRAY =
+ "read_only_apn_types_string_array";
+
+ /**
* Boolean indicating if intent for emergency call state changes should be broadcast
* @hide
*/
@@ -1019,14 +1019,16 @@ public class CarrierConfigManager {
sDefaults.putString(KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING, "");
sDefaults.putBoolean(KEY_CSP_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_ALLOW_ADDING_APNS_BOOL, true);
+ sDefaults.putStringArray(KEY_READ_ONLY_APN_TYPES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false);
sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
sDefaults.putBoolean(KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL, true);
- sDefaults.putString(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_DEFAULT_STRING,
- "default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,"
- + "320000:5000,640000:5000,1280000:5000,1800000:5000");
- sDefaults.putString(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_OTHERS_STRING,
- "max_retries=3, 5000, 5000, 5000");
+ sDefaults.putStringArray(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS, new String[]{
+ "default:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,"
+ + "320000:5000,640000:5000,1280000:5000,1800000:5000",
+ "mms:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,"
+ + "320000:5000,640000:5000,1280000:5000,1800000:5000",
+ "others:max_retries=3, 5000, 5000, 5000"});
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG, 20000);
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG, 3000);
sDefaults.putString(KEY_CARRIER_ERI_FILE_NAME_STRING, "eri.xml");
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index b417a1c9e206..fdc68b9fb7c6 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -140,6 +140,18 @@ public class PhoneConstants {
/** APN type for Emergency PDN. This is not an IA apn, but is used
* for access to carrier services in an emergency call situation. */
public static final String APN_TYPE_EMERGENCY = "emergency";
+ /** Array of all APN types */
+ public static final String[] APN_TYPES = {APN_TYPE_DEFAULT,
+ APN_TYPE_MMS,
+ APN_TYPE_SUPL,
+ APN_TYPE_DUN,
+ APN_TYPE_HIPRI,
+ APN_TYPE_FOTA,
+ APN_TYPE_IMS,
+ APN_TYPE_CBS,
+ APN_TYPE_IA,
+ APN_TYPE_EMERGENCY
+ };
public static final int RIL_CARD_MAX_APPS = 8;
diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml
index 95bbb2139a95..3d3247cb6b5c 100644
--- a/tests/UiBench/AndroidManifest.xml
+++ b/tests/UiBench/AndroidManifest.xml
@@ -85,13 +85,21 @@
</activity>
<activity
android:name=".TrivialRecyclerViewActivity"
- android:label="General/Trivial Recycler ListView" >
+ android:label="General/Trivial RecyclerView" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="com.android.test.uibench.TEST" />
</intent-filter>
</activity>
<activity
+ android:name=".SlowBindRecyclerViewActivity"
+ android:label="General/Slow Bind RecyclerView" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.uibench.TEST" />
+ </intent-filter>
+ </activity>
+ <activity
android:name=".ActivityTransition"
android:label="Transitions/Activity Transition" >
<intent-filter>
diff --git a/tests/UiBench/src/com/android/test/uibench/SlowBindRecyclerViewActivity.java b/tests/UiBench/src/com/android/test/uibench/SlowBindRecyclerViewActivity.java
new file mode 100644
index 000000000000..e32862f7b7fd
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/SlowBindRecyclerViewActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test.uibench;
+
+import android.content.Context;
+import android.os.Trace;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import com.android.test.uibench.recyclerview.RvBoxAdapter;
+import com.android.test.uibench.recyclerview.RvCompatListActivity;
+
+import java.util.concurrent.TimeUnit;
+
+public class SlowBindRecyclerViewActivity extends RvCompatListActivity {
+ /**
+ * Spin wait. Used instead of sleeping so a core is used up for the duration, and so
+ * traces/sampled profiling show the sections as expensive, and not just a scheduling mistake.
+ */
+ private static void spinWaitMs(long ms) {
+ long start = System.nanoTime();
+ while (System.nanoTime() - start < TimeUnit.MILLISECONDS.toNanos(ms));
+ }
+
+ @Override
+ protected RecyclerView.LayoutManager createLayoutManager(Context context) {
+ return new GridLayoutManager(context, 3);
+ }
+
+ @Override
+ protected RecyclerView.Adapter createAdapter() {
+ return new RvBoxAdapter(this, TextUtils.buildSimpleStringList()) {
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ Trace.beginSection("bind item " + position);
+
+ spinWaitMs(3);
+ super.onBindViewHolder(holder, position);
+ Trace.endSection();
+ }
+ };
+ }
+}
diff --git a/tests/UiBench/src/com/android/test/uibench/recyclerview/RvBoxAdapter.java b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvBoxAdapter.java
new file mode 100644
index 000000000000..3440f192e7c5
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvBoxAdapter.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test.uibench.recyclerview;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.support.v7.widget.RecyclerView;
+import android.util.TypedValue;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class RvBoxAdapter extends RecyclerView.Adapter<RvBoxAdapter.ViewHolder> {
+
+ private int mBackground;
+
+ private List<String> mValues;
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+ public TextView mTextView;
+
+ public ViewHolder(TextView v) {
+ super(v);
+ mTextView = v;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " '" + mTextView.getText();
+ }
+ }
+
+ public RvBoxAdapter(Context context, String[] strings) {
+ TypedValue val = new TypedValue();
+ if (context.getTheme() != null) {
+ context.getTheme().resolveAttribute(
+ android.R.attr.selectableItemBackground, val, true);
+ }
+ mBackground = val.resourceId;
+ mValues = new ArrayList<>();
+ Collections.addAll(mValues, strings);
+ }
+
+ @Override
+ public RvBoxAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ final ViewHolder h = new ViewHolder(new TextView(parent.getContext()));
+ h.mTextView.setMinimumHeight(128);
+ h.mTextView.setPadding(20, 0, 20, 0);
+ h.mTextView.setFocusable(true);
+ h.mTextView.setBackgroundResource(mBackground);
+ RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ lp.leftMargin = 10;
+ lp.rightMargin = 5;
+ lp.topMargin = 20;
+ lp.bottomMargin = 15;
+ h.mTextView.setLayoutParams(lp);
+ return h;
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ holder.mTextView.setText(position + ":" + mValues.get(position));
+ holder.mTextView.setMinHeight((200 + mValues.get(position).length() * 10));
+ holder.mTextView.setBackgroundColor(getBackgroundColor(position));
+ }
+
+ private int getBackgroundColor(int position) {
+ switch (position % 4) {
+ case 0: return Color.LTGRAY;
+ case 1: return Color.RED;
+ case 2: return Color.DKGRAY;
+ case 3: return Color.BLUE;
+ }
+ return Color.TRANSPARENT;
+ }
+
+ @Override
+ public int getItemCount() {
+ return mValues.size();
+ }
+}
diff --git a/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java
index e08dbc66e7f2..939b66198d72 100644
--- a/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/recyclerview/RvCompatListActivity.java
@@ -26,7 +26,6 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import com.android.test.uibench.R;
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 716f1d32ec84..3190ead48da0 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -286,6 +286,12 @@ public class WifiScanner {
* {@hide}
*/
private int mBucketsScanned;
+ /**
+ * Indicates that the scan results received are as a result of a scan of all available
+ * channels. This should only be expected to function for single scans.
+ * {@hide}
+ */
+ private boolean mAllChannelsScanned;
/** all scan results discovered in this scan, sorted by timestamp in ascending order */
private ScanResult mResults[];
@@ -298,10 +304,12 @@ public class WifiScanner {
}
/** {@hide} */
- public ScanData(int id, int flags, int bucketsScanned, ScanResult[] results) {
+ public ScanData(int id, int flags, int bucketsScanned, boolean allChannelsScanned,
+ ScanResult[] results) {
mId = id;
mFlags = flags;
mBucketsScanned = bucketsScanned;
+ mAllChannelsScanned = allChannelsScanned;
mResults = results;
}
@@ -309,6 +317,7 @@ public class WifiScanner {
mId = s.mId;
mFlags = s.mFlags;
mBucketsScanned = s.mBucketsScanned;
+ mAllChannelsScanned = s.mAllChannelsScanned;
mResults = new ScanResult[s.mResults.length];
for (int i = 0; i < s.mResults.length; i++) {
ScanResult result = s.mResults[i];
@@ -330,6 +339,11 @@ public class WifiScanner {
return mBucketsScanned;
}
+ /** {@hide} */
+ public boolean isAllChannelsScanned() {
+ return mAllChannelsScanned;
+ }
+
public ScanResult[] getResults() {
return mResults;
}
@@ -345,6 +359,7 @@ public class WifiScanner {
dest.writeInt(mId);
dest.writeInt(mFlags);
dest.writeInt(mBucketsScanned);
+ dest.writeInt(mAllChannelsScanned ? 1 : 0);
dest.writeInt(mResults.length);
for (int i = 0; i < mResults.length; i++) {
ScanResult result = mResults[i];
@@ -362,12 +377,13 @@ public class WifiScanner {
int id = in.readInt();
int flags = in.readInt();
int bucketsScanned = in.readInt();
+ boolean allChannelsScanned = in.readInt() != 0;
int n = in.readInt();
ScanResult results[] = new ScanResult[n];
for (int i = 0; i < n; i++) {
results[i] = ScanResult.CREATOR.createFromParcel(in);
}
- return new ScanData(id, flags, bucketsScanned, results);
+ return new ScanData(id, flags, bucketsScanned, allChannelsScanned, results);
}
public ScanData[] newArray(int size) {