summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt1
-rw-r--r--cmds/bootanimation/Android.mk7
-rw-r--r--cmds/bootanimation/AudioPlayer.cpp313
-rw-r--r--cmds/bootanimation/AudioPlayer.h48
-rw-r--r--cmds/bootanimation/BootAnimation.cpp90
-rw-r--r--cmds/bootanimation/BootAnimation.h6
-rw-r--r--cmds/bootanimation/FORMAT.md30
-rw-r--r--cmds/bootanimation/audioplay.cpp361
-rw-r--r--cmds/bootanimation/audioplay.h37
-rw-r--r--cmds/bootanimation/bootanim.rc1
-rw-r--r--core/java/android/app/ActivityManager.java8
-rw-r--r--core/java/android/app/ActivityManagerInternal.java9
-rw-r--r--core/java/android/app/ActivityThread.java2
-rw-r--r--core/java/android/app/ApplicationErrorReport.java25
-rw-r--r--core/java/android/app/IWallpaperManager.aidl2
-rw-r--r--core/java/android/app/WallpaperManager.java39
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java80
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl4
-rw-r--r--core/java/android/app/job/JobInfo.java3
-rw-r--r--core/java/android/content/ContentProviderClient.java8
-rw-r--r--core/java/android/content/pm/ILauncherApps.aidl2
-rw-r--r--core/java/android/content/pm/LauncherApps.java80
-rw-r--r--core/java/android/content/pm/PackageManager.java4
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java174
-rw-r--r--core/java/android/content/pm/ShortcutManager.java389
-rw-r--r--core/java/android/content/res/TypedArray.java7
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java33
-rw-r--r--core/java/android/hardware/location/ContextHubService.java80
-rw-r--r--core/java/android/hardware/usb/UsbManager.java2
-rw-r--r--core/java/android/net/ConnectivityManager.java40
-rw-r--r--core/java/android/net/IConnectivityManager.aidl2
-rw-r--r--core/java/android/net/LinkAddress.java2
-rw-r--r--core/java/android/net/NetworkUtils.java9
-rw-r--r--core/java/android/net/network-policy-restrictions.md4
-rw-r--r--core/java/android/os/Environment.java62
-rw-r--r--core/java/android/os/Process.java5
-rw-r--r--core/java/android/os/UserHandle.java6
-rw-r--r--core/java/android/os/UserManager.java11
-rw-r--r--core/java/android/provider/DocumentsContract.java11
-rwxr-xr-xcore/java/android/provider/Settings.java83
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java77
-rw-r--r--core/java/android/text/Emoji.java211
-rw-r--r--core/java/android/text/method/BaseKeyListener.java15
-rw-r--r--core/java/android/view/DragEvent.java8
-rw-r--r--core/java/android/view/IWindowManager.aidl5
-rw-r--r--core/java/android/view/View.java15
-rw-r--r--core/java/android/view/ViewRootImpl.java23
-rw-r--r--core/java/android/widget/AbsListView.java38
-rw-r--r--core/java/android/widget/GridView.java107
-rw-r--r--core/java/android/widget/ListView.java119
-rw-r--r--core/java/com/android/internal/app/NightDisplayController.java421
-rw-r--r--core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl22
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl7
-rw-r--r--core/java/com/android/internal/widget/LockPatternChecker.java11
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java66
-rw-r--r--core/jni/android/graphics/Paint.cpp17
-rw-r--r--core/jni/android_hardware_location_ContextHubService.cpp594
-rw-r--r--core/jni/android_media_AudioFormat.h30
-rw-r--r--core/jni/android_net_NetUtils.cpp94
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/layout-watch/preference_material.xml43
-rw-r--r--core/res/res/values-af/strings.xml2
-rw-r--r--core/res/res/values-am/strings.xml2
-rw-r--r--core/res/res/values-ar/strings.xml2
-rw-r--r--core/res/res/values-az-rAZ/strings.xml2
-rw-r--r--core/res/res/values-bg/strings.xml2
-rw-r--r--core/res/res/values-bn-rBD/strings.xml2
-rw-r--r--core/res/res/values-ca/strings.xml2
-rw-r--r--core/res/res/values-cs/strings.xml2
-rw-r--r--core/res/res/values-da/strings.xml2
-rw-r--r--core/res/res/values-de/strings.xml2
-rw-r--r--core/res/res/values-el/strings.xml2
-rw-r--r--core/res/res/values-en-rAU/strings.xml2
-rw-r--r--core/res/res/values-en-rGB/strings.xml2
-rw-r--r--core/res/res/values-en-rIN/strings.xml2
-rw-r--r--core/res/res/values-es-rUS/strings.xml2
-rw-r--r--core/res/res/values-es/strings.xml2
-rw-r--r--core/res/res/values-et-rEE/strings.xml1
-rw-r--r--core/res/res/values-eu-rES/strings.xml2
-rw-r--r--core/res/res/values-fa/strings.xml4
-rw-r--r--core/res/res/values-fi/strings.xml2
-rw-r--r--core/res/res/values-fr-rCA/strings.xml2
-rw-r--r--core/res/res/values-fr/strings.xml2
-rw-r--r--core/res/res/values-gl-rES/strings.xml2
-rw-r--r--core/res/res/values-gu-rIN/strings.xml2
-rw-r--r--core/res/res/values-hi/strings.xml2
-rw-r--r--core/res/res/values-hr/strings.xml2
-rw-r--r--core/res/res/values-hu/strings.xml1
-rw-r--r--core/res/res/values-hy-rAM/strings.xml2
-rw-r--r--core/res/res/values-in/strings.xml2
-rw-r--r--core/res/res/values-is-rIS/strings.xml2
-rw-r--r--core/res/res/values-it/strings.xml2
-rw-r--r--core/res/res/values-iw/strings.xml2
-rw-r--r--core/res/res/values-ja/strings.xml2
-rw-r--r--core/res/res/values-ka-rGE/strings.xml2
-rw-r--r--core/res/res/values-kk-rKZ/strings.xml4
-rw-r--r--core/res/res/values-km-rKH/strings.xml4
-rw-r--r--core/res/res/values-kn-rIN/strings.xml2
-rw-r--r--core/res/res/values-ko/strings.xml2
-rw-r--r--core/res/res/values-ky-rKG/strings.xml2
-rw-r--r--core/res/res/values-lo-rLA/strings.xml1
-rw-r--r--core/res/res/values-lt/strings.xml2
-rw-r--r--core/res/res/values-lv/strings.xml2
-rw-r--r--core/res/res/values-mcc466-mnc01/config.xml21
-rw-r--r--core/res/res/values-mcc466-mnc02/config.xml21
-rw-r--r--core/res/res/values-mcc466-mnc03/config.xml21
-rw-r--r--core/res/res/values-mcc466-mnc06/config.xml21
-rw-r--r--core/res/res/values-mcc466-mnc07/config.xml21
-rw-r--r--core/res/res/values-mcc466-mnc11/config.xml21
-rw-r--r--core/res/res/values-mcc466-mnc92/config.xml21
-rw-r--r--core/res/res/values-mk-rMK/strings.xml2
-rw-r--r--core/res/res/values-ml-rIN/strings.xml2
-rw-r--r--core/res/res/values-mn-rMN/strings.xml2
-rw-r--r--core/res/res/values-mr-rIN/strings.xml2
-rw-r--r--core/res/res/values-ms-rMY/strings.xml2
-rw-r--r--core/res/res/values-my-rMM/strings.xml94
-rw-r--r--core/res/res/values-nb/strings.xml4
-rw-r--r--core/res/res/values-ne-rNP/strings.xml2
-rw-r--r--core/res/res/values-nl/strings.xml2
-rw-r--r--core/res/res/values-pa-rIN/strings.xml2
-rw-r--r--core/res/res/values-pl/strings.xml2
-rw-r--r--core/res/res/values-pt-rBR/strings.xml2
-rw-r--r--core/res/res/values-pt-rPT/strings.xml2
-rw-r--r--core/res/res/values-pt/strings.xml2
-rw-r--r--core/res/res/values-ro/strings.xml2
-rw-r--r--core/res/res/values-round-watch/dimens_material.xml10
-rw-r--r--core/res/res/values-ru/strings.xml4
-rw-r--r--core/res/res/values-si-rLK/strings.xml2
-rw-r--r--core/res/res/values-sk/strings.xml2
-rw-r--r--core/res/res/values-sl/strings.xml2
-rw-r--r--core/res/res/values-sq-rAL/strings.xml2
-rw-r--r--core/res/res/values-sr/strings.xml2
-rw-r--r--core/res/res/values-sv/strings.xml2
-rw-r--r--core/res/res/values-sw/strings.xml2
-rw-r--r--core/res/res/values-ta-rIN/strings.xml2
-rw-r--r--core/res/res/values-te-rIN/strings.xml2
-rw-r--r--core/res/res/values-th/strings.xml2
-rw-r--r--core/res/res/values-tl/strings.xml2
-rw-r--r--core/res/res/values-tr/strings.xml2
-rw-r--r--core/res/res/values-uk/strings.xml2
-rw-r--r--core/res/res/values-ur-rPK/strings.xml2
-rw-r--r--core/res/res/values-uz-rUZ/strings.xml2
-rw-r--r--core/res/res/values-vi/strings.xml2
-rw-r--r--core/res/res/values-w194dp/dimens_material.xml (renamed from packages/SystemUI/res/layout/night_mode_settings.xml)14
-rw-r--r--core/res/res/values-w205dp/dimens_material.xml (renamed from packages/SystemUI/res/xml/color_and_appearance.xml)20
-rw-r--r--core/res/res/values-w213dp/dimens_material.xml20
-rw-r--r--core/res/res/values-w228dp/dimens_material.xml20
-rw-r--r--core/res/res/values-w240dp/dimens_material.xml20
-rw-r--r--core/res/res/values-watch/colors_material.xml2
-rw-r--r--core/res/res/values-zh-rCN/strings.xml2
-rw-r--r--core/res/res/values-zh-rHK/strings.xml2
-rw-r--r--core/res/res/values-zh-rTW/strings.xml2
-rw-r--r--core/res/res/values-zu/strings.xml2
-rw-r--r--core/res/res/values/config.xml28
-rw-r--r--core/res/res/values/strings.xml3
-rw-r--r--core/res/res/values/symbols.xml10
-rw-r--r--core/tests/coretests/src/android/text/method/BackspaceTest.java24
-rw-r--r--docs/html-intl/intl/ja/training/basics/data-storage/files.jd10
-rw-r--r--docs/html-intl/intl/ko/training/basics/data-storage/files.jd12
-rw-r--r--docs/html-intl/intl/pt-br/training/basics/data-storage/files.jd12
-rw-r--r--docs/html-intl/intl/ru/training/basics/data-storage/files.jd14
-rw-r--r--docs/html-intl/intl/zh-cn/training/basics/data-storage/files.jd14
-rw-r--r--docs/html-intl/intl/zh-tw/training/basics/data-storage/files.jd14
-rw-r--r--docs/html/_redirects.yaml8
-rw-r--r--docs/html/about/dashboards/index.jd54
-rw-r--r--docs/html/auto/images/logos/auto/lincoln.pngbin0 -> 13977 bytes
-rw-r--r--docs/html/auto/images/logos/auto/mbenz.pngbin0 -> 9932 bytes
-rw-r--r--docs/html/auto/images/logos/auto/opel.pngbin60667 -> 23783 bytes
-rw-r--r--docs/html/auto/images/logos/auto/renault.pngbin12177 -> 5578 bytes
-rw-r--r--docs/html/auto/images/logos/auto/rsm.pngbin0 -> 12666 bytes
-rw-r--r--docs/html/auto/images/logos/auto/tata.pngbin0 -> 6377 bytes
-rw-r--r--docs/html/auto/index.jd53
-rw-r--r--docs/html/community/index.html320
-rw-r--r--docs/html/distribute/stories/apps.jd3
-rw-r--r--docs/html/distribute/stories/apps/aftenposten.jd80
-rw-r--r--docs/html/distribute/stories/apps/el-mundo.jd73
-rw-r--r--docs/html/distribute/stories/apps/segundamano.jd63
-rw-r--r--docs/html/distribute/stories/apps/tapps.jd366
-rw-r--r--docs/html/distribute/stories/apps/upbeat-games.jd69
-rw-r--r--docs/html/distribute/stories/games.jd1
-rw-r--r--docs/html/guide/topics/resources/layout-resource.jd50
-rw-r--r--docs/html/guide/topics/security/permissions.jd2
-rw-r--r--docs/html/images/cards/distribute/stories/aftenposten.pngbin0 -> 7948 bytes
-rw-r--r--docs/html/images/cards/distribute/stories/el-mundo.pngbin0 -> 9092 bytes
-rw-r--r--docs/html/images/cards/distribute/stories/segundamano.pngbin0 -> 14540 bytes
-rw-r--r--docs/html/images/cards/distribute/stories/tapps.pngbin0 -> 11603 bytes
-rw-r--r--docs/html/images/cards/distribute/stories/witch-puzzle.pngbin0 -> 31043 bytes
-rw-r--r--docs/html/images/distribute/stories/aftenposten-icon.pngbin0 -> 7948 bytes
-rw-r--r--docs/html/images/distribute/stories/el-mundo-icon.pngbin0 -> 9092 bytes
-rw-r--r--docs/html/images/distribute/stories/japanese-witch-puzzle.pngbin0 -> 94261 bytes
-rw-r--r--docs/html/images/distribute/stories/segundamano-icon.pngbin0 -> 14540 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-candy-hills.pngbin0 -> 357502 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-orig-1.pngbin0 -> 33454 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-orig-2.pngbin0 -> 47461 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-orig-3.pngbin0 -> 24568 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-1-2.pngbin0 -> 27740 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-1.pngbin0 -> 40198 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-2-2.pngbin0 -> 46349 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-2.pngbin0 -> 47518 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-3-2.pngbin0 -> 16998 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-icon-var-3.pngbin0 -> 17868 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-logic-pic.pngbin0 -> 18349 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-logo.pngbin0 -> 11603 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-orig-1.pngbin0 -> 109993 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-orig-2.pngbin0 -> 638813 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-orig-3.pngbin0 -> 279975 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-var-1.pngbin0 -> 861604 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-var-2.pngbin0 -> 522603 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-screen-var-3.pngbin0 -> 358402 bytes
-rw-r--r--docs/html/images/distribute/stories/tapps-villains-corp.pngbin0 -> 43911 bytes
-rw-r--r--docs/html/images/distribute/stories/witch-puzzle-icon.pngbin0 -> 31043 bytes
-rw-r--r--docs/html/images/training/tv/tif/app-link-2x.pngbin0 -> 1359345 bytes
-rw-r--r--docs/html/images/training/tv/tif/app-link-diagram.pngbin0 -> 64710 bytes
-rw-r--r--docs/html/images/training/tv/tif/app-link.pngbin0 -> 340494 bytes
-rw-r--r--docs/html/preview/setup-sdk.jd30
-rwxr-xr-xdocs/html/topic/libraries/support-library/features.jd34
-rw-r--r--docs/html/topic/performance/index.jd2
-rw-r--r--docs/html/topic/performance/launch-time.jd4
-rw-r--r--docs/html/training/articles/perf-tips.jd17
-rw-r--r--docs/html/training/basics/data-storage/files.jd10
-rw-r--r--docs/html/training/basics/firstapp/creating-project.jd22
-rw-r--r--docs/html/training/displaying-bitmaps/load-bitmap.jd4
-rw-r--r--docs/html/training/testing/ui-testing/uiautomator-testing.jd2
-rw-r--r--docs/html/training/tv/tif/channel.jd126
-rw-r--r--docs/html/wear/preview/_book.yaml2
-rw-r--r--docs/html/wear/preview/api-overview.jd22
-rw-r--r--docs/html/wear/preview/downloads.jd25
-rw-r--r--docs/html/wear/preview/features/gestures.jd323
-rw-r--r--docs/html/wear/preview/features/ui-nav-actions.jd94
-rw-r--r--docs/html/wear/preview/program.jd23
-rw-r--r--docs/html/wear/preview/start.jd51
-rw-r--r--docs/html/wear/preview/support.jd284
-rw-r--r--docs/html/work/managed-configurations.jd4
-rw-r--r--docs/image_sources/training/tv/tif/app-link-diagram.graffle.zipbin0 -> 99151 bytes
-rw-r--r--libs/hwui/PropertyValuesAnimatorSet.h4
-rw-r--r--libs/hwui/RenderNode.cpp5
-rw-r--r--libs/hwui/RenderProperties.h4
-rw-r--r--libs/hwui/tests/unit/RenderPropertiesTests.cpp4
-rw-r--r--location/java/android/location/GnssMeasurementsEvent.java8
-rw-r--r--media/java/android/media/AudioFormat.java3
-rw-r--r--media/java/android/media/AudioManager.java2
-rw-r--r--media/java/android/media/AudioRecordingConfiguration.java16
-rw-r--r--media/java/android/media/MediaPlayer.java2
-rw-r--r--media/java/android/media/PlayerBase.java7
-rw-r--r--media/java/android/media/SoundPool.java36
-rw-r--r--media/java/android/media/soundtrigger/SoundTriggerDetector.java11
-rw-r--r--media/jni/android_media_MediaDataSource.cpp5
-rw-r--r--media/jni/android_media_MediaDataSource.h1
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java9
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/Cat.java4
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoLand.java2
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java31
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java13
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java13
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java45
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java31
-rw-r--r--packages/PrintSpooler/res/drawable/print_button.xml2
-rw-r--r--packages/PrintSpooler/res/values/colors.xml2
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java1
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java16
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-my-rMM/strings.xml8
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/SettingsProvider/res/values/defaults.xml3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java1
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java59
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_night_display_off.xml (renamed from packages/SystemUI/res/drawable/ic_night_mode_disabled.xml)15
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_night_display_on.xml (renamed from packages/SystemUI/res/drawable/ic_night_mode.xml)14
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml49
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml33
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml47
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml33
-rw-r--r--packages/SystemUI/res/layout/battery_detail.xml2
-rw-r--r--packages/SystemUI/res/layout/calibrate_sliders.xml97
-rw-r--r--packages/SystemUI/res/layout/qs_detail_header.xml12
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml2
-rw-r--r--packages/SystemUI/res/layout/volume_dialog.xml1
-rw-r--r--packages/SystemUI/res/layout/volume_dialog_row.xml3
-rw-r--r--packages/SystemUI/res/values-af/strings.xml15
-rw-r--r--packages/SystemUI/res/values-am/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml15
-rw-r--r--packages/SystemUI/res/values-az-rAZ/strings.xml15
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml15
-rw-r--r--packages/SystemUI/res/values-bn-rBD/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml15
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml15
-rw-r--r--packages/SystemUI/res/values-da/strings.xml15
-rw-r--r--packages/SystemUI/res/values-de/strings.xml15
-rw-r--r--packages/SystemUI/res/values-el/strings.xml15
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml15
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml15
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml15
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml15
-rw-r--r--packages/SystemUI/res/values-es/strings.xml15
-rw-r--r--packages/SystemUI/res/values-et-rEE/strings.xml15
-rw-r--r--packages/SystemUI/res/values-eu-rES/strings.xml15
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml15
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml15
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml15
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml15
-rw-r--r--packages/SystemUI/res/values-gl-rES/strings.xml15
-rw-r--r--packages/SystemUI/res/values-gu-rIN/strings.xml15
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml15
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml15
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml15
-rw-r--r--packages/SystemUI/res/values-hy-rAM/strings.xml15
-rw-r--r--packages/SystemUI/res/values-in/strings.xml15
-rw-r--r--packages/SystemUI/res/values-is-rIS/strings.xml15
-rw-r--r--packages/SystemUI/res/values-it/strings.xml15
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ka-rGE/strings.xml15
-rw-r--r--packages/SystemUI/res/values-kk-rKZ/strings.xml15
-rw-r--r--packages/SystemUI/res/values-km-rKH/strings.xml15
-rw-r--r--packages/SystemUI/res/values-kn-rIN/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ky-rKG/strings.xml15
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings.xml15
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml15
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml15
-rw-r--r--packages/SystemUI/res/values-mk-rMK/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ml-rIN/strings.xml15
-rw-r--r--packages/SystemUI/res/values-mn-rMN/strings.xml15
-rw-r--r--packages/SystemUI/res/values-mr-rIN/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings.xml15
-rw-r--r--packages/SystemUI/res/values-my-rMM/strings.xml35
-rw-r--r--packages/SystemUI/res/values-my-rMM/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ne-rNP/strings.xml15
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml15
-rw-r--r--packages/SystemUI/res/values-pa-rIN/strings.xml15
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml15
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml15
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml15
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml15
-rw-r--r--packages/SystemUI/res/values-si-rLK/strings.xml15
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml15
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml15
-rw-r--r--packages/SystemUI/res/values-sq-rAL/strings.xml15
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml15
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml15
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml15
-rw-r--r--packages/SystemUI/res/values-ta-rIN/strings.xml15
-rw-r--r--packages/SystemUI/res/values-te-rIN/strings.xml15
-rw-r--r--packages/SystemUI/res/values-th/strings.xml15
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml15
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml15
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml29
-rw-r--r--packages/SystemUI/res/values-ur-rPK/strings.xml15
-rw-r--r--packages/SystemUI/res/values-uz-rUZ/strings.xml15
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml15
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml21
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml15
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml15
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml15
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml62
-rw-r--r--packages/SystemUI/res/xml/night_mode.xml39
-rw-r--r--packages/SystemUI/res/xml/tuner_prefs.xml7
-rw-r--r--packages/SystemUI/src/com/android/systemui/Prefs.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetail.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java99
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java246
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java219
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java188
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java107
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java8
-rw-r--r--packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java103
-rw-r--r--proto/src/metrics_constants.proto429
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java41
-rw-r--r--services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java166
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java2
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java128
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java4
-rw-r--r--services/core/java/com/android/server/AnyMotionDetector.java78
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java268
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java7
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java70
-rw-r--r--services/core/java/com/android/server/PersistentDataBlockService.java19
-rw-r--r--services/core/java/com/android/server/PinnerService.java22
-rw-r--r--services/core/java/com/android/server/UiThread.java5
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java142
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java44
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java8
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java28
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java73
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java243
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java253
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java177
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java23
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java1
-rw-r--r--services/core/java/com/android/server/display/DisplayTransformManager.java175
-rw-r--r--services/core/java/com/android/server/display/NightDisplayService.java367
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java5
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java2
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java145
-rw-r--r--services/core/java/com/android/server/media/MediaSessionStack.java42
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java18
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java4
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java16
-rw-r--r--services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java12
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java48
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptService.java12
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java40
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java54
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java4
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java54
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java17
-rw-r--r--services/core/java/com/android/server/pm/UserRestrictionsUtils.java7
-rw-r--r--services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java8
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java53
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java15
-rw-r--r--services/core/java/com/android/server/twilight/TwilightService.java2
-rw-r--r--services/core/java/com/android/server/vr/EnabledComponentsObserver.java4
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java30
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java5
-rw-r--r--services/core/java/com/android/server/wm/DockedStackDividerController.java48
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java88
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java38
-rw-r--r--services/java/com/android/server/SystemServer.java12
-rw-r--r--services/net/java/android/net/ip/RouterAdvertisementDaemon.java581
-rw-r--r--services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java138
-rw-r--r--services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java68
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java151
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java807
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java30
-rw-r--r--telecomm/java/android/telecom/Connection.java8
-rw-r--r--telecomm/java/android/telecom/ConnectionService.java3
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapter.java15
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapterServant.java9
-rw-r--r--telecomm/java/android/telecom/PhoneAccount.java50
-rw-r--r--telecomm/java/android/telecom/RemoteConnectionService.java6
-rw-r--r--telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl2
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java37
-rw-r--r--telephony/java/android/telephony/DisconnectCause.java12
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java17
-rw-r--r--telephony/java/com/android/ims/ImsExternalCallState.java3
-rw-r--r--telephony/java/com/android/ims/ImsReasonInfo.java14
-rw-r--r--telephony/java/com/android/internal/telephony/DctConstants.java1
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl8
-rw-r--r--tests/AppLaunch/Android.mk4
-rw-r--r--tests/AppLaunch/AndroidManifest.xml10
-rw-r--r--tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java444
-rw-r--r--tests/SoundTriggerTestApp/AndroidManifest.xml19
-rw-r--r--tests/SoundTriggerTestApp/res/layout/main.xml140
-rw-r--r--tests/SoundTriggerTestApp/res/values/strings.xml9
-rw-r--r--tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java329
-rw-r--r--tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java720
-rw-r--r--tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java17
-rw-r--r--tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java400
-rw-r--r--tests/UiBench/src/com/android/test/uibench/MainActivity.java34
-rw-r--r--tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java17
-rw-r--r--tools/aapt/Android.mk2
-rw-r--r--tools/aapt2/util/Util.cpp4
-rwxr-xr-xtools/fonts/fontchain_lint.py40
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java5
-rw-r--r--tools/split-select/Android.mk2
486 files changed, 11520 insertions, 6383 deletions
diff --git a/Android.mk b/Android.mk
index ba4e173ed0c7..8c39d19a322f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -343,6 +343,7 @@ LOCAL_SRC_FILES += \
core/java/com/android/internal/view/IInputMethodManager.aidl \
core/java/com/android/internal/view/IInputMethodSession.aidl \
core/java/com/android/internal/view/IInputSessionCallback.aidl \
+ core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl \
core/java/com/android/internal/widget/ILockSettings.aidl \
core/java/com/android/internal/widget/IRemoteViewsFactory.aidl \
core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl \
diff --git a/api/current.txt b/api/current.txt
index d5f36bdb081f..d3ee682370b9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19652,6 +19652,7 @@ package android.media {
field public static final android.os.Parcelable.Creator<android.media.AudioFormat> CREATOR;
field public static final int ENCODING_AC3 = 5; // 0x5
field public static final int ENCODING_DEFAULT = 1; // 0x1
+ field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe
field public static final int ENCODING_DTS = 7; // 0x7
field public static final int ENCODING_DTS_HD = 8; // 0x8
field public static final int ENCODING_E_AC3 = 6; // 0x6
diff --git a/api/system-current.txt b/api/system-current.txt
index 16c75cc5d747..13ad2d666dcb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21160,6 +21160,7 @@ package android.media {
field public static final android.os.Parcelable.Creator<android.media.AudioFormat> CREATOR;
field public static final int ENCODING_AC3 = 5; // 0x5
field public static final int ENCODING_DEFAULT = 1; // 0x1
+ field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe
field public static final int ENCODING_DTS = 7; // 0x7
field public static final int ENCODING_DTS_HD = 8; // 0x8
field public static final int ENCODING_E_AC3 = 6; // 0x6
diff --git a/api/test-current.txt b/api/test-current.txt
index 7fdbb6411ef4..c6359dd4d1e9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -19722,6 +19722,7 @@ package android.media {
field public static final android.os.Parcelable.Creator<android.media.AudioFormat> CREATOR;
field public static final int ENCODING_AC3 = 5; // 0x5
field public static final int ENCODING_DEFAULT = 1; // 0x1
+ field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe
field public static final int ENCODING_DTS = 7; // 0x7
field public static final int ENCODING_DTS_HD = 8; // 0x8
field public static final int ENCODING_E_AC3 = 6; // 0x6
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 7c8842ca0231..3a92b9e74144 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -3,14 +3,16 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
bootanimation_main.cpp \
- AudioPlayer.cpp \
+ audioplay.cpp \
BootAnimation.cpp
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-LOCAL_C_INCLUDES += external/tinyalsa/include
+LOCAL_C_INCLUDES += \
+ external/tinyalsa/include \
+ frameworks/wilhelm/include
LOCAL_SHARED_LIBRARIES := \
libcutils \
@@ -23,6 +25,7 @@ LOCAL_SHARED_LIBRARIES := \
libEGL \
libGLESv1_CM \
libgui \
+ libOpenSLES \
libtinyalsa
LOCAL_MODULE:= bootanimation
diff --git a/cmds/bootanimation/AudioPlayer.cpp b/cmds/bootanimation/AudioPlayer.cpp
deleted file mode 100644
index 293213008d58..000000000000
--- a/cmds/bootanimation/AudioPlayer.cpp
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_NDEBUG 0
-#define LOG_TAG "BootAnim_AudioPlayer"
-
-#include "AudioPlayer.h"
-
-#include <androidfw/ZipFileRO.h>
-#include <tinyalsa/asoundlib.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#define ID_RIFF 0x46464952
-#define ID_WAVE 0x45564157
-#define ID_FMT 0x20746d66
-#define ID_DATA 0x61746164
-
-// Maximum line length for audio_conf.txt
-// We only accept lines less than this length to avoid overflows using sscanf()
-#define MAX_LINE_LENGTH 1024
-
-struct riff_wave_header {
- uint32_t riff_id;
- uint32_t riff_sz;
- uint32_t wave_id;
-};
-
-struct chunk_header {
- uint32_t id;
- uint32_t sz;
-};
-
-struct chunk_fmt {
- uint16_t audio_format;
- uint16_t num_channels;
- uint32_t sample_rate;
- uint32_t byte_rate;
- uint16_t block_align;
- uint16_t bits_per_sample;
-};
-
-
-namespace android {
-
-AudioPlayer::AudioPlayer()
- : mCard(-1),
- mDevice(-1),
- mPeriodSize(0),
- mPeriodCount(0),
- mCurrentFile(NULL)
-{
-}
-
-AudioPlayer::~AudioPlayer() {
-}
-
-static bool setMixerValue(struct mixer* mixer, const char* name, const char* values)
-{
- if (!mixer) {
- ALOGE("no mixer in setMixerValue");
- return false;
- }
- struct mixer_ctl *ctl = mixer_get_ctl_by_name(mixer, name);
- if (!ctl) {
- ALOGE("mixer_get_ctl_by_name failed for %s", name);
- return false;
- }
-
- enum mixer_ctl_type type = mixer_ctl_get_type(ctl);
- int numValues = mixer_ctl_get_num_values(ctl);
- int intValue;
- char stringValue[MAX_LINE_LENGTH];
-
- for (int i = 0; i < numValues && values; i++) {
- // strip leading space
- while (*values == ' ') values++;
- if (*values == 0) break;
-
- switch (type) {
- case MIXER_CTL_TYPE_BOOL:
- case MIXER_CTL_TYPE_INT:
- if (sscanf(values, "%d", &intValue) == 1) {
- if (mixer_ctl_set_value(ctl, i, intValue) != 0) {
- ALOGE("mixer_ctl_set_value failed for %s %d", name, intValue);
- }
- } else {
- ALOGE("Could not parse %s as int for %s", values, name);
- }
- break;
- case MIXER_CTL_TYPE_ENUM:
- if (sscanf(values, "%s", stringValue) == 1) {
- if (mixer_ctl_set_enum_by_string(ctl, stringValue) != 0) {
- ALOGE("mixer_ctl_set_enum_by_string failed for %s %s", name, stringValue);
- }
- } else {
- ALOGE("Could not parse %s as enum for %s", values, name);
- }
- break;
- default:
- ALOGE("unsupported mixer type %d for %s", type, name);
- break;
- }
-
- values = strchr(values, ' ');
- }
-
- return true;
-}
-
-
-/*
- * Parse the audio configuration file.
- * The file is named audio_conf.txt and must begin with the following header:
- *
- * card=<ALSA card number>
- * device=<ALSA device number>
- * period_size=<period size>
- * period_count=<period count>
- *
- * This header is followed by zero or more mixer settings, each with the format:
- * mixer "<name>" = <value list>
- * Since mixer names can contain spaces, the name must be enclosed in double quotes.
- * The values in the value list can be integers, booleans (represented by 0 or 1)
- * or strings for enum values.
- */
-bool AudioPlayer::init(const char* config)
-{
- int tempInt;
- struct mixer* mixer = NULL;
- char name[MAX_LINE_LENGTH];
-
- for (;;) {
- const char* endl = strstr(config, "\n");
- if (!endl) break;
- String8 line(config, endl - config);
- if (line.length() >= MAX_LINE_LENGTH) {
- ALOGE("Line too long in audio_conf.txt");
- return false;
- }
- const char* l = line.string();
-
- if (sscanf(l, "card=%d", &tempInt) == 1) {
- ALOGD("card=%d", tempInt);
- mCard = tempInt;
-
- mixer = mixer_open(mCard);
- if (!mixer) {
- ALOGE("could not open mixer for card %d", mCard);
- return false;
- }
- } else if (sscanf(l, "device=%d", &tempInt) == 1) {
- ALOGD("device=%d", tempInt);
- mDevice = tempInt;
- } else if (sscanf(l, "period_size=%d", &tempInt) == 1) {
- ALOGD("period_size=%d", tempInt);
- mPeriodSize = tempInt;
- } else if (sscanf(l, "period_count=%d", &tempInt) == 1) {
- ALOGD("period_count=%d", tempInt);
- mPeriodCount = tempInt;
- } else if (sscanf(l, "mixer \"%[0-9a-zA-Z _]s\"", name) == 1) {
- const char* values = strchr(l, '=');
- if (values) {
- values++; // skip '='
- ALOGD("name: \"%s\" = %s", name, values);
- setMixerValue(mixer, name, values);
- } else {
- ALOGE("values missing for name: \"%s\"", name);
- }
- }
- config = ++endl;
- }
-
- mixer_close(mixer);
-
- if (mCard >= 0 && mDevice >= 0) {
- return true;
- }
-
- return false;
-}
-
-void AudioPlayer::playFile(FileMap* fileMap) {
- // stop any currently playing sound
- requestExitAndWait();
-
- mCurrentFile = fileMap;
- run("bootanim audio", PRIORITY_URGENT_AUDIO);
-}
-
-bool AudioPlayer::threadLoop()
-{
- struct pcm_config config;
- struct pcm *pcm = NULL;
- bool moreChunks = true;
- const struct chunk_fmt* chunkFmt = NULL;
- int bufferSize;
- const uint8_t* wavData;
- size_t wavLength;
- const struct riff_wave_header* wavHeader;
-
- if (mCurrentFile == NULL) {
- ALOGE("mCurrentFile is NULL");
- return false;
- }
-
- wavData = (const uint8_t *)mCurrentFile->getDataPtr();
- if (!wavData) {
- ALOGE("Could not access WAV file data");
- goto exit;
- }
- wavLength = mCurrentFile->getDataLength();
-
- wavHeader = (const struct riff_wave_header *)wavData;
- if (wavLength < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) ||
- (wavHeader->wave_id != ID_WAVE)) {
- ALOGE("Error: audio file is not a riff/wave file\n");
- goto exit;
- }
- wavData += sizeof(*wavHeader);
- wavLength -= sizeof(*wavHeader);
-
- do {
- const struct chunk_header* chunkHeader = (const struct chunk_header*)wavData;
- if (wavLength < sizeof(*chunkHeader)) {
- ALOGE("EOF reading chunk headers");
- goto exit;
- }
-
- wavData += sizeof(*chunkHeader);
- wavLength -= sizeof(*chunkHeader);
-
- switch (chunkHeader->id) {
- case ID_FMT:
- chunkFmt = (const struct chunk_fmt *)wavData;
- wavData += chunkHeader->sz;
- wavLength -= chunkHeader->sz;
- break;
- case ID_DATA:
- /* Stop looking for chunks */
- moreChunks = 0;
- break;
- default:
- /* Unknown chunk, skip bytes */
- wavData += chunkHeader->sz;
- wavLength -= chunkHeader->sz;
- }
- } while (moreChunks);
-
- if (!chunkFmt) {
- ALOGE("format not found in WAV file");
- goto exit;
- }
-
-
- memset(&config, 0, sizeof(config));
- config.channels = chunkFmt->num_channels;
- config.rate = chunkFmt->sample_rate;
- config.period_size = mPeriodSize;
- config.period_count = mPeriodCount;
- config.start_threshold = mPeriodSize / 4;
- config.stop_threshold = INT_MAX;
- config.avail_min = config.start_threshold;
- if (chunkFmt->bits_per_sample != 16) {
- ALOGE("only 16 bit WAV files are supported");
- goto exit;
- }
- config.format = PCM_FORMAT_S16_LE;
-
- pcm = pcm_open(mCard, mDevice, PCM_OUT, &config);
- if (!pcm || !pcm_is_ready(pcm)) {
- ALOGE("Unable to open PCM device (%s)\n", pcm_get_error(pcm));
- goto exit;
- }
-
- bufferSize = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
-
- while (wavLength > 0) {
- if (exitPending()) goto exit;
- size_t count = bufferSize;
- if (count > wavLength)
- count = wavLength;
-
- if (pcm_write(pcm, wavData, count)) {
- ALOGE("pcm_write failed (%s)", pcm_get_error(pcm));
- goto exit;
- }
- wavData += count;
- wavLength -= count;
- }
-
-exit:
- if (pcm)
- pcm_close(pcm);
- delete mCurrentFile;
- mCurrentFile = NULL;
- return false;
-}
-
-} // namespace android
diff --git a/cmds/bootanimation/AudioPlayer.h b/cmds/bootanimation/AudioPlayer.h
deleted file mode 100644
index 1def0aeac8d1..000000000000
--- a/cmds/bootanimation/AudioPlayer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _BOOTANIMATION_AUDIOPLAYER_H
-#define _BOOTANIMATION_AUDIOPLAYER_H
-
-#include <utils/Thread.h>
-#include <utils/FileMap.h>
-
-namespace android {
-
-class AudioPlayer : public Thread
-{
-public:
- AudioPlayer();
- virtual ~AudioPlayer();
- bool init(const char* config);
-
- void playFile(FileMap* fileMap);
-
-private:
- virtual bool threadLoop();
-
-private:
- int mCard; // ALSA card to use
- int mDevice; // ALSA device to use
- int mPeriodSize;
- int mPeriodCount;
-
- FileMap* mCurrentFile;
-};
-
-} // namespace android
-
-#endif // _BOOTANIMATION_AUDIOPLAYER_H
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index e849f4b8e9d3..ebcc9ff0451f 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -58,7 +58,7 @@
#include <EGL/eglext.h>
#include "BootAnimation.h"
-#include "AudioPlayer.h"
+#include "audioplay.h"
namespace android {
@@ -72,6 +72,8 @@ static const char LAST_TIME_CHANGED_FILE_NAME[] = "last_time_change";
static const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/system/time/last_time_change";
static const char ACCURATE_TIME_FLAG_FILE_NAME[] = "time_is_accurate";
static const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/system/time/time_is_accurate";
+// Java timestamp format. Don't show the clock if the date is before 2000-01-01 00:00:00.
+static const long long ACCURATE_TIME_EPOCH = 946684800000;
static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
static const int ANIM_ENTRY_NAME_MAX = 256;
@@ -106,9 +108,7 @@ void BootAnimation::binderDied(const wp<IBinder>&)
// might be blocked on a condition variable that will never be updated.
kill( getpid(), SIGKILL );
requestExit();
- if (mAudioPlayer != NULL) {
- mAudioPlayer->requestExit();
- }
+ audioplay::destroy();
}
status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
@@ -202,25 +202,25 @@ status_t BootAnimation::initTexture(const Animation::Frame& frame)
switch (bitmap.colorType()) {
case kN32_SkColorType:
- if (tw != w || th != h) {
+ if (!mUseNpotTextures && (tw != w || th != h)) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,
GL_UNSIGNED_BYTE, 0);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, p);
} else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, GL_RGBA,
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
GL_UNSIGNED_BYTE, p);
}
break;
case kRGB_565_SkColorType:
- if (tw != w || th != h) {
+ if (!mUseNpotTextures && (tw != w || th != h)) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB,
GL_UNSIGNED_SHORT_5_6_5, 0);
glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p);
} else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB,
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
GL_UNSIGNED_SHORT_5_6_5, p);
}
break;
@@ -400,9 +400,6 @@ void BootAnimation::checkExit() {
int exitnow = atoi(value);
if (exitnow) {
requestExit();
- if (mAudioPlayer != NULL) {
- mAudioPlayer->requestExit();
- }
}
}
@@ -524,16 +521,6 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
}
char const* s = desString.string();
- // Create and initialize an AudioPlayer if we have an audio_conf.txt file
- String8 audioConf;
- if (readFile(animation.zip, "audio_conf.txt", audioConf)) {
- mAudioPlayer = new AudioPlayer;
- if (!mAudioPlayer->init(audioConf.string())) {
- ALOGE("mAudioPlayer.init failed");
- mAudioPlayer = NULL;
- }
- }
-
// Parse the description file
for (;;) {
const char* endl = strstr(s, "\n");
@@ -564,7 +551,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
part.pause = pause;
part.path = path;
part.clockPosY = clockPosY;
- part.audioFile = NULL;
+ part.audioData = NULL;
part.animation = NULL;
if (!parseColor(color, part.backgroundColor)) {
ALOGE("> invalid color '#%s'", color);
@@ -580,7 +567,7 @@ bool BootAnimation::parseAnimationDesc(Animation& animation)
part.playUntilComplete = false;
part.count = 1;
part.pause = 0;
- part.audioFile = NULL;
+ part.audioData = NULL;
part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE));
if (part.animation != NULL)
animation.parts.add(part);
@@ -601,6 +588,7 @@ bool BootAnimation::preloadZip(Animation& animation)
return false;
}
+ Animation::Part* partWithAudio = NULL;
ZipEntryRO entry;
char name[ANIM_ENTRY_NAME_MAX];
while ((entry = zip->nextEntry(cookie)) != NULL) {
@@ -625,7 +613,9 @@ bool BootAnimation::preloadZip(Animation& animation)
Animation::Part& part(animation.parts.editItemAt(j));
if (leaf == "audio.wav") {
// a part may have at most one audio file
- part.audioFile = map;
+ part.audioData = (uint8_t *)map->getDataPtr();
+ part.audioLength = map->getDataLength();
+ partWithAudio = &part;
} else if (leaf == "trim.txt") {
part.trimData.setTo((char const*)map->getDataPtr(),
map->getDataLength());
@@ -640,6 +630,8 @@ bool BootAnimation::preloadZip(Animation& animation)
part.frames.add(frame);
}
}
+ } else {
+ ALOGE("bootanimation.zip is compressed; must be only stored");
}
}
}
@@ -673,6 +665,14 @@ bool BootAnimation::preloadZip(Animation& animation)
}
}
+ // Create and initialize audioplay if there is a wav file in any of the animations.
+ if (partWithAudio != NULL) {
+ ALOGD("found audio.wav, creating playback engine");
+ if (!audioplay::create(partWithAudio->audioData, partWithAudio->audioLength)) {
+ return false;
+ }
+ }
+
zip->endIteration(cookie);
return true;
@@ -695,6 +695,20 @@ bool BootAnimation::movie()
mClockEnabled = false;
}
+ // Check if npot textures are supported
+ mUseNpotTextures = false;
+ String8 gl_extensions;
+ const char* exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
+ if (!exts) {
+ glGetError();
+ } else {
+ gl_extensions.setTo(exts);
+ if ((gl_extensions.find("GL_ARB_texture_non_power_of_two") != -1) ||
+ (gl_extensions.find("GL_OES_texture_npot") != -1)) {
+ mUseNpotTextures = true;
+ }
+ }
+
// Blend required to draw time on top of animation frames.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel(GL_FLAT);
@@ -763,8 +777,9 @@ bool BootAnimation::playAnimation(const Animation& animation)
break;
// only play audio file the first time we animate the part
- if (r == 0 && mAudioPlayer != NULL && part.audioFile) {
- mAudioPlayer->playFile(part.audioFile);
+ if (r == 0 && part.audioData) {
+ ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength);
+ audioplay::playClip(part.audioData, part.audioLength);
}
glClearColor(
@@ -839,14 +854,23 @@ bool BootAnimation::playAnimation(const Animation& animation)
break;
}
- // free the textures for this part
+ }
+
+ // Free textures created for looping parts now that the animation is done.
+ for (const Animation::Part& part : animation.parts) {
if (part.count != 1) {
- for (size_t j=0 ; j<fcount ; j++) {
+ const size_t fcount = part.frames.size();
+ for (size_t j = 0; j < fcount; j++) {
const Animation::Frame& frame(part.frames[j]);
glDeleteTextures(1, &frame.tid);
}
}
}
+
+ // we've finally played everything we're going to play
+ audioplay::setPlaying(false);
+ audioplay::destroy();
+
return true;
}
@@ -882,7 +906,10 @@ BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn)
mLoadedFiles.add(animation->fileName);
parseAnimationDesc(*animation);
- preloadZip(*animation);
+ if (!preloadZip(*animation)) {
+ return NULL;
+ }
+
mLoadedFiles.remove(fn);
return animation;
@@ -912,8 +939,9 @@ bool BootAnimation::updateIsTimeAccurate() {
clock_gettime(CLOCK_REALTIME, &now);
// Match the Java timestamp format
long long rtcNow = (now.tv_sec * 1000LL) + (now.tv_nsec / 1000000LL);
- if (lastChangedTime > rtcNow - MAX_TIME_IN_PAST
- && lastChangedTime < rtcNow + MAX_TIME_IN_FUTURE) {
+ if (ACCURATE_TIME_EPOCH < rtcNow
+ && lastChangedTime > (rtcNow - MAX_TIME_IN_PAST)
+ && lastChangedTime < (rtcNow + MAX_TIME_IN_FUTURE)) {
mTimeIsAccurate = true;
}
}
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index a093c9b87e75..a53216eb0310 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -30,7 +30,6 @@ class SkBitmap;
namespace android {
-class AudioPlayer;
class Surface;
class SurfaceComposerClient;
class SurfaceControl;
@@ -98,7 +97,8 @@ private:
SortedVector<Frame> frames;
bool playUntilComplete;
float backgroundColor[3];
- FileMap* audioFile;
+ uint8_t* audioData;
+ int audioLength;
Animation* animation;
};
int fps;
@@ -124,12 +124,12 @@ private:
void checkExit();
sp<SurfaceComposerClient> mSession;
- sp<AudioPlayer> mAudioPlayer;
AssetManager mAssets;
Texture mAndroid[2];
Texture mClock;
int mWidth;
int mHeight;
+ bool mUseNpotTextures = false;
EGLDisplay mDisplay;
EGLDisplay mContext;
EGLDisplay mSurface;
diff --git a/cmds/bootanimation/FORMAT.md b/cmds/bootanimation/FORMAT.md
index e4c52f783fa3..9ea6fea966f2 100644
--- a/cmds/bootanimation/FORMAT.md
+++ b/cmds/bootanimation/FORMAT.md
@@ -67,34 +67,8 @@ If the file is not present, each frame is assumed to be the same size as the ani
## audio.wav
-Each part may optionally play a `wav` sample when it starts. To enable this for an animation,
-you must also include a `audio_conf.txt` file in the ZIP archive. Its format is as follows:
-
- card=<ALSA card number>
- device=<ALSA device number>
- period_size=<period size>
- period_count=<period count>
-
-This header is followed by zero or more mixer settings, each with the format:
-
- mixer "<name>" = <value list>
-
-Here's an example `audio_conf.txt` from Shamu:
-
- card=0
- device=15
- period_size=1024
- period_count=4
-
- mixer "QUAT_MI2S_RX Audio Mixer MultiMedia5" = 1
- mixer "Playback Channel Map" = 0 220 157 195 0 0 0 0
- mixer "QUAT_MI2S_RX Channels" = Two
- mixer "BOOST_STUB Right Mixer right" = 1
- mixer "BOOST_STUB Left Mixer left" = 1
- mixer "Compress Playback 9 Volume" = 80 80
-
-You will probably need to get these mixer names and values out of `audio_platform_info.xml`
-and `mixer_paths.xml` for your device.
+Each part may optionally play a `wav` sample when it starts. To enable this, add a file
+with the name `audio.wav` in the part directory.
## exiting
diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp
new file mode 100644
index 000000000000..8a5c2c6d229c
--- /dev/null
+++ b/cmds/bootanimation/audioplay.cpp
@@ -0,0 +1,361 @@
+/*
+ * 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.
+ *
+ */
+
+// cribbed from samples/native-audio
+
+#include "audioplay.h"
+
+#define CHATTY ALOGD
+
+#include <string.h>
+
+#include <utils/Log.h>
+
+// for native audio
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+
+namespace audioplay {
+namespace {
+
+// engine interfaces
+static SLObjectItf engineObject = NULL;
+static SLEngineItf engineEngine;
+
+// output mix interfaces
+static SLObjectItf outputMixObject = NULL;
+
+// buffer queue player interfaces
+static SLObjectItf bqPlayerObject = NULL;
+static SLPlayItf bqPlayerPlay;
+static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
+static SLMuteSoloItf bqPlayerMuteSolo;
+static SLVolumeItf bqPlayerVolume;
+
+// pointer and size of the next player buffer to enqueue, and number of remaining buffers
+static const uint8_t* nextBuffer;
+static unsigned nextSize;
+
+static const uint32_t ID_RIFF = 0x46464952;
+static const uint32_t ID_WAVE = 0x45564157;
+static const uint32_t ID_FMT = 0x20746d66;
+static const uint32_t ID_DATA = 0x61746164;
+
+struct RiffWaveHeader {
+ uint32_t riff_id;
+ uint32_t riff_sz;
+ uint32_t wave_id;
+};
+
+struct ChunkHeader {
+ uint32_t id;
+ uint32_t sz;
+};
+
+struct ChunkFormat {
+ uint16_t audio_format;
+ uint16_t num_channels;
+ uint32_t sample_rate;
+ uint32_t byte_rate;
+ uint16_t block_align;
+ uint16_t bits_per_sample;
+};
+
+// this callback handler is called every time a buffer finishes playing
+void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
+ (void)bq;
+ (void)context;
+ audioplay::setPlaying(false);
+}
+
+bool hasPlayer() {
+ return (engineObject != NULL && bqPlayerObject != NULL);
+}
+
+// create the engine and output mix objects
+bool createEngine() {
+ SLresult result;
+
+ // create engine
+ result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("slCreateEngine failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ // realize the engine
+ result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl engine Realize failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ // get the engine interface, which is needed in order to create other objects
+ result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl engine GetInterface failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ // create output mix, with environmental reverb specified as a non-required interface
+ const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
+ const SLboolean req[1] = {SL_BOOLEAN_FALSE};
+ result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl engine CreateOutputMix failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ // realize the output mix
+ result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl outputMix Realize failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ return true;
+}
+
+// create buffer queue audio player
+bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) {
+ SLresult result;
+
+ // configure audio source
+ SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1};
+
+ 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,
+ SL_BYTEORDER_LITTLEENDIAN
+ };
+ SLDataSource audioSrc = {&loc_bufq, &format_pcm};
+
+ // configure audio sink
+ SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
+ SLDataSink audioSnk = {&loc_outmix, NULL};
+
+ // create audio player
+ const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
+ const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
+ result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk,
+ 2, ids, req);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl CreateAudioPlayer failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ // realize the player
+ result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl player Realize failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ // get the play interface
+ result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl player GetInterface failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ // get the buffer queue interface
+ result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
+ &bqPlayerBufferQueue);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl playberBufferQueue GetInterface failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ // register callback on the buffer queue
+ result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ // get the volume interface
+ result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
+ if (result != SL_RESULT_SUCCESS) {
+ ALOGE("sl volume GetInterface failed with result %d", result);
+ return false;
+ }
+ (void)result;
+
+ // set the player's state to playing
+ audioplay::setPlaying(true);
+ CHATTY("Created buffer queue player: %p", bqPlayerBufferQueue);
+ return true;
+}
+
+bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** oChunkFormat,
+ const uint8_t** oSoundBuf, unsigned* oSoundBufSize) {
+ *oSoundBuf = clipBuf;
+ *oSoundBufSize = clipBufSize;
+ *oChunkFormat = NULL;
+ const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)*oSoundBuf;
+ if (*oSoundBufSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) ||
+ (wavHeader->wave_id != ID_WAVE)) {
+ ALOGE("Error: audio file is not a riff/wave file\n");
+ return false;
+ }
+ *oSoundBuf += sizeof(*wavHeader);
+ *oSoundBufSize -= sizeof(*wavHeader);
+
+ while (true) {
+ const ChunkHeader* chunkHeader = (const ChunkHeader*)*oSoundBuf;
+ if (*oSoundBufSize < sizeof(*chunkHeader)) {
+ ALOGE("EOF reading chunk headers");
+ return false;
+ }
+
+ *oSoundBuf += sizeof(*chunkHeader);
+ *oSoundBufSize -= sizeof(*chunkHeader);
+
+ bool endLoop = false;
+ switch (chunkHeader->id) {
+ case ID_FMT:
+ *oChunkFormat = (const ChunkFormat*)*oSoundBuf;
+ *oSoundBuf += chunkHeader->sz;
+ *oSoundBufSize -= chunkHeader->sz;
+ break;
+ case ID_DATA:
+ /* Stop looking for chunks */
+ endLoop = true;
+ break;
+ default:
+ /* Unknown chunk, skip bytes */
+ *oSoundBuf += chunkHeader->sz;
+ *oSoundBufSize -= chunkHeader->sz;
+ }
+ if (endLoop) {
+ break;
+ }
+ }
+
+ if (*oChunkFormat == NULL) {
+ ALOGE("format not found in WAV file");
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize) {
+ if (!createEngine()) {
+ return false;
+ }
+
+ // Parse the example clip.
+ const ChunkFormat* chunkFormat;
+ const uint8_t* soundBuf;
+ unsigned soundBufSize;
+ if (!parseClipBuf(exampleClipBuf, exampleClipBufSize, &chunkFormat, &soundBuf, &soundBufSize)) {
+ return false;
+ }
+
+ // Initialize the BufferQueue based on this clip's format.
+ if (!createBufferQueueAudioPlayer(chunkFormat)) {
+ return false;
+ }
+ return true;
+}
+
+bool playClip(const uint8_t* buf, int size) {
+ // Parse the WAV header
+ const ChunkFormat* chunkFormat;
+ if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) {
+ return false;
+ }
+
+ if (!hasPlayer()) {
+ ALOGD("cannot play clip %p without a player", buf);
+ return false;
+ }
+
+ CHATTY("playClip on player %p: buf=%p size=%d", bqPlayerBufferQueue, buf, size);
+
+ if (nextSize > 0) {
+ // here we only enqueue one buffer because it is a long clip,
+ // but for streaming playback we would typically enqueue at least 2 buffers to start
+ SLresult result;
+ result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
+ if (SL_RESULT_SUCCESS != result) {
+ return false;
+ }
+ audioplay::setPlaying(true);
+ }
+
+ return true;
+}
+
+// set the playing state for the buffer queue audio player
+void setPlaying(bool isPlaying) {
+ if (!hasPlayer()) return;
+
+ SLresult result;
+
+ if (NULL != bqPlayerPlay) {
+ // set the player's state
+ result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
+ isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED);
+ }
+
+}
+
+void destroy() {
+ // destroy buffer queue audio player object, and invalidate all associated interfaces
+ if (bqPlayerObject != NULL) {
+ CHATTY("destroying audio player");
+ (*bqPlayerObject)->Destroy(bqPlayerObject);
+ bqPlayerObject = NULL;
+ bqPlayerPlay = NULL;
+ bqPlayerBufferQueue = NULL;
+ bqPlayerMuteSolo = NULL;
+ bqPlayerVolume = NULL;
+ }
+
+ // destroy output mix object, and invalidate all associated interfaces
+ if (outputMixObject != NULL) {
+ (*outputMixObject)->Destroy(outputMixObject);
+ outputMixObject = NULL;
+ }
+
+ // destroy engine object, and invalidate all associated interfaces
+ if (engineObject != NULL) {
+ CHATTY("destroying audio engine");
+ (*engineObject)->Destroy(engineObject);
+ engineObject = NULL;
+ engineEngine = NULL;
+ }
+}
+
+} // namespace audioplay
diff --git a/cmds/bootanimation/audioplay.h b/cmds/bootanimation/audioplay.h
new file mode 100644
index 000000000000..0e5705af0ad0
--- /dev/null
+++ b/cmds/bootanimation/audioplay.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef AUDIOPLAY_H_
+#define AUDIOPLAY_H_
+
+#include <string.h>
+
+namespace audioplay {
+
+// Initializes the engine with an example of the type of WAV clip to play.
+// All buffers passed to playClip are assumed to be in the same format.
+bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize);
+
+// Plays a WAV contained in buf.
+// Should not be called while a clip is still playing.
+bool playClip(const uint8_t* buf, int size);
+void setPlaying(bool isPlaying);
+void destroy();
+
+}
+
+#endif // AUDIOPLAY_H_
diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc
index ee0d0b8c042f..7344ba74f70b 100644
--- a/cmds/bootanimation/bootanim.rc
+++ b/cmds/bootanimation/bootanim.rc
@@ -4,3 +4,4 @@ service bootanim /system/bin/bootanimation
group graphics audio
disabled
oneshot
+ writepid /dev/stune/top-app/tasks \ No newline at end of file
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 23fea7133015..af981f69d3b6 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -93,7 +93,8 @@ public class ActivityManager {
@IntDef({
BUGREPORT_OPTION_FULL,
BUGREPORT_OPTION_INTERACTIVE,
- BUGREPORT_OPTION_REMOTE
+ BUGREPORT_OPTION_REMOTE,
+ BUGREPORT_OPTION_WEAR
})
public @interface BugreportMode {}
/**
@@ -114,6 +115,11 @@ public class ActivityManager {
* @hide
*/
public static final int BUGREPORT_OPTION_REMOTE = 2;
+ /**
+ * Takes a bugreport on a wearable device.
+ * @hide
+ */
+ public static final int BUGREPORT_OPTION_WEAR = 3;
/**
* <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 6dd14fd263e3..fc3596e2b5bb 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -165,9 +165,10 @@ public abstract class ActivityManagerInternal {
int userId);
/**
- * Create an {@link IIntentSender} to start an activity, as if {@code packageName} on
- * user {@code userId} created it.
+ * Start an activity {@code intent} as if {@code packageName} on user {@code userId} did it.
+ *
+ * @return error codes used by {@link IActivityManager#startActivity} and its siblings.
*/
- public abstract IIntentSender getActivityIntentSenderAsPackage(String packageName,
- int userId, int requestCode, Intent intent, int flags, Bundle bOptions);
+ public abstract int startActivityAsPackage(String packageName,
+ int userId, Intent intent, Bundle bOptions);
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index fef1e2c63e46..3f15a755bd79 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -6057,7 +6057,7 @@ public final class ActivityThread {
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
- Environment.init();
+ Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 8692336439f9..9fa8a5d2faee 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -345,7 +345,7 @@ public class ApplicationErrorReport implements Parcelable {
PrintWriter pw = new FastPrintWriter(sw, false, 256);
tr.printStackTrace(pw);
pw.flush();
- stackTrace = sw.toString();
+ stackTrace = sanitizeString(sw.toString());
exceptionMessage = tr.getMessage();
// Populate fields with the "root cause" exception
@@ -374,6 +374,29 @@ public class ApplicationErrorReport implements Parcelable {
throwMethodName = "unknown";
throwLineNumber = 0;
}
+
+ exceptionMessage = sanitizeString(exceptionMessage);
+ }
+
+ /**
+ * Ensure that the string is of reasonable size, truncating from the middle if needed.
+ */
+ private String sanitizeString(String s) {
+ int prefixLength = 10 * 1024;
+ int suffixLength = 10 * 1024;
+ int acceptableLength = prefixLength + suffixLength;
+
+ if (s != null && s.length() > acceptableLength) {
+ String replacement =
+ "\n[TRUNCATED " + (s.length() - acceptableLength) + " CHARS]\n";
+
+ StringBuilder sb = new StringBuilder(acceptableLength + replacement.length());
+ sb.append(s.substring(0, prefixLength));
+ sb.append(replacement);
+ sb.append(s.substring(s.length() - suffixLength));
+ return sb.toString();
+ }
+ return s;
}
/**
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index a0762b94a040..9cd70e6d8366 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -72,7 +72,7 @@ interface IWallpaperManager {
* information about that wallpaper. Otherwise, if it is a static image,
* simply return null.
*/
- WallpaperInfo getWallpaperInfo();
+ WallpaperInfo getWallpaperInfo(int userId);
/**
* Clear the system wallpaper.
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 7f467f0585c8..53da4e32eb8a 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -51,6 +51,7 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.view.WindowManagerGlobal;
@@ -265,7 +266,7 @@ public class WallpaperManager {
}
static class Globals extends IWallpaperManagerCallback.Stub {
- private IWallpaperManager mService;
+ private final IWallpaperManager mService;
private Bitmap mCachedWallpaper;
private int mCachedWallpaperUserId;
private Bitmap mDefaultWallpaper;
@@ -292,16 +293,16 @@ public class WallpaperManager {
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
@SetWallpaperFlags int which, int userId) {
- synchronized (this) {
- if (mService != null) {
- try {
- if (!mService.isWallpaperSupported(context.getOpPackageName())) {
- return null;
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ if (mService != null) {
+ try {
+ if (!mService.isWallpaperSupported(context.getOpPackageName())) {
+ return null;
}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
+ }
+ synchronized (this) {
if (mCachedWallpaper != null && mCachedWallpaperUserId == userId) {
return mCachedWallpaper;
}
@@ -316,17 +317,21 @@ public class WallpaperManager {
if (mCachedWallpaper != null) {
return mCachedWallpaper;
}
- if (returnDefault) {
- if (mDefaultWallpaper == null) {
- mDefaultWallpaper = getDefaultWallpaperLocked(context, which);
+ }
+ if (returnDefault) {
+ Bitmap defaultWallpaper = mDefaultWallpaper;
+ if (defaultWallpaper == null) {
+ defaultWallpaper = getDefaultWallpaper(context, which);
+ synchronized (this) {
+ mDefaultWallpaper = defaultWallpaper;
}
- return mDefaultWallpaper;
}
- return null;
+ return defaultWallpaper;
}
+ return null;
}
- public void forgetLoadedWallpaper() {
+ void forgetLoadedWallpaper() {
synchronized (this) {
mCachedWallpaper = null;
mCachedWallpaperUserId = 0;
@@ -361,7 +366,7 @@ public class WallpaperManager {
return null;
}
- private Bitmap getDefaultWallpaperLocked(Context context, @SetWallpaperFlags int which) {
+ private Bitmap getDefaultWallpaper(Context context, @SetWallpaperFlags int which) {
InputStream is = openDefaultWallpaper(context, which);
if (is != null) {
try {
@@ -783,7 +788,7 @@ public class WallpaperManager {
Log.w(TAG, "WallpaperService not running");
throw new RuntimeException(new DeadSystemException());
} else {
- return sGlobals.mService.getWallpaperInfo();
+ return sGlobals.mService.getWallpaperInfo(UserHandle.myUserId());
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 325a15f1cb30..2a12ac8f0567 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1315,7 +1315,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current minimum password quality for a particular admin or all admins that set
- * retrictions on this user and its participating profiles. Restrictions on profiles that have
+ * restrictions on this user and its participating profiles. Restrictions on profiles that have
* a separate challenge are not taken into account.
*
* <p>This method can be called on the {@link DevicePolicyManager} instance
@@ -1379,7 +1379,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current minimum password length for a particular admin or all admins that set
- * retrictions on this user and its participating profiles. Restrictions on profiles that have
+ * restrictions on this user and its participating profiles. Restrictions on profiles that have
* a separate challenge are not taken into account.
*
* <p>This method can be called on the {@link DevicePolicyManager} instance
@@ -1442,7 +1442,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current number of upper case letters required in the password
- * for a particular admin or all admins that set retrictions on this user and
+ * for a particular admin or all admins that set restrictions on this user and
* its participating profiles. Restrictions on profiles that have a separate challenge
* are not taken into account.
* This is the same value as set by
@@ -1511,7 +1511,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current number of lower case letters required in the password
- * for a particular admin or all admins that set retrictions on this user
+ * for a particular admin or all admins that set restrictions on this user
* and its participating profiles. Restrictions on profiles that have
* a separate challenge are not taken into account.
* This is the same value as set by
@@ -1580,7 +1580,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current number of letters required in the password
- * for a particular admin or all admins that set retrictions on this user
+ * for a particular admin or all admins that set restrictions on this user
* and its participating profiles. Restrictions on profiles that have
* a separate challenge are not taken into account.
* This is the same value as set by
@@ -1648,7 +1648,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current number of numerical digits required in the password
- * for a particular admin or all admins that set retrictions on this user
+ * for a particular admin or all admins that set restrictions on this user
* and its participating profiles. Restrictions on profiles that have
* a separate challenge are not taken into account.
* This is the same value as set by
@@ -1716,7 +1716,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current number of symbols required in the password
- * for a particular admin or all admins that set retrictions on this user
+ * for a particular admin or all admins that set restrictions on this user
* and its participating profiles. Restrictions on profiles that have
* a separate challenge are not taken into account. This is the same value as
* set by {@link #setPasswordMinimumSymbols(ComponentName, int)}
@@ -1783,7 +1783,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current number of non-letter characters required in the password
- * for a particular admin or all admins that set retrictions on this user
+ * for a particular admin or all admins that set restrictions on this user
* and its participating profiles. Restrictions on profiles that have
* a separate challenge are not taken into account.
* This is the same value as set by
@@ -1915,7 +1915,7 @@ public class DevicePolicyManager {
/**
* Get the current password expiration time for a particular admin or all admins that set
- * retrictions on this user and its participating profiles. Restrictions on profiles that have
+ * restrictions on this user and its participating profiles. Restrictions on profiles that have
* a separate challenge are not taken into account. If admin is {@code null}, then a composite
* of all expiration times is returned - which will be the minimum of all of them.
*
@@ -1939,7 +1939,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current password history length for a particular admin or all admins that
- * set retrictions on this user and its participating profiles. Restrictions on profiles that
+ * set restrictions on this user and its participating profiles. Restrictions on profiles that
* have a separate challenge are not taken into account.
*
* <p>This method can be called on the {@link DevicePolicyManager} instance
@@ -2121,7 +2121,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current maximum number of login attempts that are allowed before the device
- * or profile is wiped, for a particular admin or all admins that set retrictions on this user
+ * or profile is wiped, for a particular admin or all admins that set restrictions on this user
* and its participating profiles. Restrictions on profiles that have a separate challenge are
* not taken into account.
*
@@ -2262,7 +2262,7 @@ public class DevicePolicyManager {
/**
* Retrieve the current maximum time to unlock for a particular admin or all admins that set
- * retrictions on this user and its participating profiles. Restrictions on profiles that have
+ * restrictions on this user and its participating profiles. Restrictions on profiles that have
* a separate challenge are not taken into account.
*
* <p>This method can be called on the {@link DevicePolicyManager} instance
@@ -2510,6 +2510,8 @@ public class DevicePolicyManager {
/**
* Result code for {@link #setStorageEncryption} and {@link #getStorageEncryptionStatus}:
* indicating that encryption is active.
+ * <p>
+ * Also see {@link #ENCRYPTION_STATUS_ACTIVE_PER_USER}.
*/
public static final int ENCRYPTION_STATUS_ACTIVE = 3;
@@ -2522,7 +2524,11 @@ public class DevicePolicyManager {
/**
* Result code for {@link #getStorageEncryptionStatus}:
- * indicating that encryption is active and the encryption key is tied to the user.
+ * indicating that encryption is active and the encryption key is tied to the user or profile.
+ * <p>
+ * This value is only returned to apps targeting API level 24 and above. For apps targeting
+ * earlier API levels, {@link #ENCRYPTION_STATUS_ACTIVE} is returned, even if the
+ * encryption key is specific to the user or profile.
*/
public static final int ENCRYPTION_STATUS_ACTIVE_PER_USER = 5;
@@ -2649,7 +2655,7 @@ public class DevicePolicyManager {
/**
* Called by an application that is administering the device to
* determine the current encryption status of the device.
- *
+ * <p>
* Depending on the returned status code, the caller may proceed in different
* ways. If the result is {@link #ENCRYPTION_STATUS_UNSUPPORTED}, the
* storage system does not support encryption. If the
@@ -2657,13 +2663,14 @@ public class DevicePolicyManager {
* #ACTION_START_ENCRYPTION} to begin the process of encrypting or decrypting the
* storage. If the result is {@link #ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY}, the
* storage system has enabled encryption but no password is set so further action
- * may be required. If the result is {@link #ENCRYPTION_STATUS_ACTIVATING} or
- * {@link #ENCRYPTION_STATUS_ACTIVE}, no further action is required.
+ * may be required. If the result is {@link #ENCRYPTION_STATUS_ACTIVATING},
+ * {@link #ENCRYPTION_STATUS_ACTIVE} or {@link #ENCRYPTION_STATUS_ACTIVE_PER_USER},
+ * no further action is required.
*
* @return current status of encryption. The value will be one of
* {@link #ENCRYPTION_STATUS_UNSUPPORTED}, {@link #ENCRYPTION_STATUS_INACTIVE},
* {@link #ENCRYPTION_STATUS_ACTIVATING}, {@link #ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY},
- * or {@link #ENCRYPTION_STATUS_ACTIVE}.
+ * {@link #ENCRYPTION_STATUS_ACTIVE}, or {@link #ENCRYPTION_STATUS_ACTIVE_PER_USER}.
*/
public int getStorageEncryptionStatus() {
throwIfParentInstance("getStorageEncryptionStatus");
@@ -3341,7 +3348,7 @@ public class DevicePolicyManager {
/**
* Determine whether or not features have been disabled in keyguard either by the calling
- * admin, if specified, or all admins that set retrictions on this user and its participating
+ * admin, if specified, or all admins that set restrictions on this user and its participating
* profiles. Restrictions on profiles that have a separate challenge are not taken into account.
*
* <p>This method can be called on the {@link DevicePolicyManager} instance
@@ -6416,6 +6423,43 @@ public class DevicePolicyManager {
}
}
+ /**
+ * @hide
+ * @return whether {@link android.provider.Settings.Global#DEVICE_PROVISIONED} has ever been set
+ * to 1.
+ */
+ public boolean isDeviceProvisioned() {
+ try {
+ return mService.isDeviceProvisioned();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * Writes that the provisioning configuration has been applied.
+ */
+ public void setDeviceProvisioningConfigApplied() {
+ try {
+ mService.setDeviceProvisioningConfigApplied();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * @return whether the provisioning configuration has been applied.
+ */
+ public boolean isDeviceProvisioningConfigApplied() {
+ try {
+ return mService.isDeviceProvisioningConfigApplied();
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
private void throwIfParentInstance(String functionName) {
if (mParentInstance) {
throw new SecurityException(functionName + " cannot be called on the parent instance");
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index ddec412e53c1..1036f0499a54 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -301,4 +301,8 @@ interface IDevicePolicyManager {
boolean isUninstallInQueue(String packageName);
void uninstallPackageWithActiveAdmins(String packageName);
+
+ boolean isDeviceProvisioned();
+ boolean isDeviceProvisioningConfigApplied();
+ void setDeviceProvisioningConfigApplied();
}
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 5823abf9d78f..734bf6917eca 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -165,6 +165,9 @@ public class JobInfo implements Parcelable {
* network restrictions for the requesting app. Note that this flag alone
* doesn't actually place your {@link JobService} in the foreground; you
* still need to post the notification yourself.
+ * <p>
+ * To use this flag, the caller must hold the
+ * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL} permission.
*
* @hide
*/
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index e49eb34aeea8..9221fbb50c96 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -147,7 +147,13 @@ public class ContentProviderClient implements AutoCloseable {
if (cursor == null) {
return null;
}
- return new CursorWrapperInner(cursor);
+
+ if ("com.google.android.gms".equals(mPackageName)) {
+ // They're casting to a concrete subclass, sigh
+ return cursor;
+ } else {
+ return new CursorWrapperInner(cursor);
+ }
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index c19e6382775a..430c7e706b64 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -51,7 +51,7 @@ interface ILauncherApps {
in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
in UserHandle user);
- void startShortcut(String callingPackage, String packageName, String id,
+ boolean startShortcut(String callingPackage, String packageName, String id,
in Rect sourceBounds, in Bundle startActivityOptions, int userId);
int getShortcutIconResId(String callingPackage, String packageName, String id,
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 528fe2002391..29b2230b4140 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -164,17 +165,19 @@ public class LauncherApps {
}
/**
- * Indicates that one or more shortcuts (which may be dynamic and/or pinned)
+ * Indicates that one or more shortcuts of any kinds (dynamic, pinned, or manifest)
* have been added, updated or removed.
*
* <p>Only the applications that are allowed to access the shortcut information,
* as defined in {@link #hasShortcutHostPermission()}, will receive it.
*
* @param packageName The name of the package that has the shortcuts.
- * @param shortcuts all shortcuts from the package (dynamic, manifest and/or pinned).
- * Only "key" information will be provided, as defined in
+ * @param shortcuts all shortcuts from the package (dynamic, manifest and/or pinned) will
+ * be passed. Only "key" information will be provided, as defined in
* {@link ShortcutInfo#hasKeyFieldsOnly()}.
* @param user The UserHandle of the profile that generated the change.
+ *
+ * @see ShortcutManager
*/
public void onShortcutsChanged(@NonNull String packageName,
@NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
@@ -222,7 +225,17 @@ public class LauncherApps {
/**
* Requests "key" fields only. See {@link ShortcutInfo#hasKeyFieldsOnly()} for which
- * fields are available.
+ * fields are available. This allows quicker access to shortcut information in order to
+ * determine in-memory cache in the caller needs to be updated.
+ *
+ * <p>Typically, launcher applications cache all or most shortcuts' information
+ * in memory in order to show shortcuts without a delay. When they want to update their
+ * cache (e.g. when their process restart), they can fetch all shortcuts' information with
+ * with this flag, then check {@link ShortcutInfo#getLastChangedTimestamp()} for each
+ * shortcut and issue a second call to fetch the non-key information of only updated
+ * shortcuts.
+ *
+ * @see ShortcutManager
*/
public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2;
@@ -255,8 +268,8 @@ public class LauncherApps {
}
/**
- * If non-zero, returns only shortcuts that have been added or updated since the timestamp,
- * which is a milliseconds since the Epoch.
+ * If non-zero, returns only shortcuts that have been added or updated since the timestamp.
+ * Units are as per {@link System#currentTimeMillis()}.
*/
public ShortcutQuery setChangedSince(long changedSince) {
mChangedSince = changedSince;
@@ -273,7 +286,7 @@ public class LauncherApps {
/**
* If non-null, return only the specified shortcuts by ID. When setting this field,
- * a packange name must also be set with {@link #setPackage}.
+ * a package name must also be set with {@link #setPackage}.
*/
public ShortcutQuery setShortcutIds(@Nullable List<String> shortcutIds) {
mShortcutIds = shortcutIds;
@@ -291,7 +304,13 @@ public class LauncherApps {
}
/**
- * Set query options.
+ * Set query options. At least one of the {@code MATCH} flags should be set. (Otherwise
+ * no shortcuts will be returned.)
+ *
+ * @see {@link #FLAG_MATCH_DYNAMIC}
+ * @see {@link #FLAG_MATCH_PINNED}
+ * @see {@link #FLAG_MATCH_MANIFEST}
+ * @see {@link #FLAG_GET_KEY_FIELDS_ONLY}
*/
public ShortcutQuery setQueryFlags(@QueryFlags int queryFlags) {
mQueryFlags = queryFlags;
@@ -460,10 +479,14 @@ public class LauncherApps {
*
* <p>Only the default launcher can access the shortcut information.
*
- * <p>Note when this method returns {@code false}, that may be a temporary situation because
+ * <p>Note when this method returns {@code false}, it may be a temporary situation because
* the user is trying a new launcher application. The user may decide to change the default
- * launcher to the calling application again, so even if a launcher application loses
+ * launcher back to the calling application again, so even if a launcher application loses
* this permission, it does <b>not</b> have to purge pinned shortcut information.
+ * Also in this situation, pinned shortcuts can still be started, even though the caller
+ * no longer has the shortcut host permission.
+ *
+ * @see ShortcutManager
*/
public boolean hasShortcutHostPermission() {
try {
@@ -474,7 +497,7 @@ public class LauncherApps {
}
/**
- * Returns the IDs of {@link ShortcutInfo}s that match {@code query}.
+ * Returns {@link ShortcutInfo}s that match {@code query}.
*
* <p>Callers must be allowed to access the shortcut information, as defined in {@link
* #hasShortcutHostPermission()}.
@@ -483,6 +506,8 @@ public class LauncherApps {
* @param user The UserHandle of the profile.
*
* @return the IDs of {@link ShortcutInfo}s that match the query.
+ *
+ * @see ShortcutManager
*/
@Nullable
public List<ShortcutInfo> getShortcuts(@NonNull ShortcutQuery query,
@@ -523,6 +548,8 @@ public class LauncherApps {
* @param packageName The target package name.
* @param shortcutIds The IDs of the shortcut to be pinned.
* @param user The UserHandle of the profile.
+ *
+ * @see ShortcutManager
*/
public void pinShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
@NonNull UserHandle user) {
@@ -586,11 +613,17 @@ public class LauncherApps {
/**
* Returns the icon for this shortcut, without any badging for the profile.
*
+ * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+ * #hasShortcutHostPermission()}.
+ *
* @param density The preferred density of the icon, zero for default density. Use
* density DPI values from {@link DisplayMetrics}.
+ *
+ * @return The drawable associated with the shortcut.
+ *
+ * @see ShortcutManager
* @see #getShortcutBadgedIconDrawable(ShortcutInfo, int)
* @see DisplayMetrics
- * @return The drawable associated with the shortcut.
*/
public Drawable getShortcutIconDrawable(@NonNull ShortcutInfo shortcut, int density) {
if (shortcut.hasIconFile()) {
@@ -628,10 +661,15 @@ public class LauncherApps {
/**
* Returns the shortcut icon with badging appropriate for the profile.
*
+ * <p>Callers must be allowed to access the shortcut information, as defined in {@link
+ * #hasShortcutHostPermission()}.
+ *
* @param density Optional density for the icon, or 0 to use the default density. Use
- * {@link DisplayMetrics} for DPI values.
- * @see DisplayMetrics
* @return A badged icon for the shortcut.
+ *
+ * @see ShortcutManager
+ * @see #getShortcutBadgedIconDrawable(ShortcutInfo, int)
+ * @see DisplayMetrics
*/
public Drawable getShortcutBadgedIconDrawable(ShortcutInfo shortcut, int density) {
final Drawable originalIcon = getShortcutIconDrawable(shortcut, density);
@@ -641,7 +679,7 @@ public class LauncherApps {
}
/**
- * Launches a shortcut.
+ * Starts a shortcut.
*
* <p>Callers must be allowed to access the shortcut information, as defined in {@link
* #hasShortcutHostPermission()}.
@@ -651,6 +689,9 @@ public class LauncherApps {
* @param sourceBounds The Rect containing the source bounds of the clicked icon.
* @param startActivityOptions Options to pass to startActivity.
* @param user The UserHandle of the profile.
+ *
+ * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g.
+ * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc)
*/
public void startShortcut(@NonNull String packageName, @NonNull String shortcutId,
@Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
@@ -668,6 +709,9 @@ public class LauncherApps {
* @param shortcut The target shortcut.
* @param sourceBounds The Rect containing the source bounds of the clicked icon.
* @param startActivityOptions Options to pass to startActivity.
+ *
+ * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g.
+ * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc)
*/
public void startShortcut(@NonNull ShortcutInfo shortcut,
@Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions) {
@@ -680,8 +724,12 @@ public class LauncherApps {
@Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
int userId) {
try {
- mService.startShortcut(mContext.getPackageName(), packageName, shortcutId,
+ final boolean success =
+ mService.startShortcut(mContext.getPackageName(), packageName, shortcutId,
sourceBounds, startActivityOptions, userId);
+ if (!success) {
+ throw new ActivityNotFoundException("Shortcut could not be started");
+ }
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index fbe16c5db717..281d6f691bc2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -146,6 +146,8 @@ public abstract class PackageManager {
MATCH_UNINSTALLED_PACKAGES,
MATCH_SYSTEM_ONLY,
MATCH_DEBUG_TRIAGED_MISSING,
+ MATCH_DISABLED_UNTIL_USED_COMPONENTS,
+ GET_DISABLED_UNTIL_USED_COMPONENTS,
GET_UNINSTALLED_PACKAGES,
})
@Retention(RetentionPolicy.SOURCE)
@@ -2879,6 +2881,7 @@ public abstract class PackageManager {
*
* @see #GET_META_DATA
* @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
* @see #MATCH_SYSTEM_ONLY
* @see #MATCH_UNINSTALLED_PACKAGES
*/
@@ -3507,6 +3510,7 @@ public abstract class PackageManager {
*
* @see #GET_META_DATA
* @see #GET_SHARED_LIBRARY_FILES
+ * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS
* @see #MATCH_SYSTEM_ONLY
* @see #MATCH_UNINSTALLED_PACKAGES
*/
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 39e15e01bab4..8ea77d6428a8 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -22,8 +22,10 @@ import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
+import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Parcel;
@@ -42,20 +44,10 @@ import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Set;
-// TODO Enhance javadoc
/**
+ * Represents a "launcher shortcut" that can be published via {@link ShortcutManager}.
*
- * Represents a shortcut from an application.
- *
- * <p>Notes about icons:
- * <ul>
- * <li>If an {@link Icon} is a resource, the system keeps the package name and the resource ID.
- * Otherwise, the bitmap is fetched when it's registered to ShortcutManager,
- * then shrunk if necessary, and persisted.
- * <li>The system disallows byte[] icons, because they can easily go over the binder size limit.
- * </ul>
- *
- * @see {@link ShortcutManager}.
+ * @see ShortcutManager
*/
public final class ShortcutInfo implements Parcelable {
static final String TAG = "Shortcut";
@@ -149,7 +141,7 @@ public final class ShortcutInfo implements Parcelable {
public @interface CloneFlags {}
/**
- * Shortcut category for
+ * Shortcut category for messaging related actions, such as chat.
*/
public static final String SHORTCUT_CATEGORY_CONVERSATION = "android.shortcut.conversation";
@@ -665,6 +657,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* Builder class for {@link ShortcutInfo} objects.
+ *
+ * @see ShortcutManager
*/
public static class Builder {
private final Context mContext;
@@ -727,19 +721,25 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Sets the target activity. A shortcut will be shown with this activity on the launcher.
+ * Sets the target activity. A shortcut will be shown along with this activity's icon
+ * on the launcher.
*
- * <p>Only "main" activities -- i.e. ones with an intent filter for
- * {@link Intent#ACTION_MAIN} and {@link Intent#CATEGORY_LAUNCHER} can be target activities.
+ * <p>This is a mandatory field when publishing a new shortcut with
+ * {@link ShortcutManager#addDynamicShortcuts(List)} or
+ * {@link ShortcutManager#setDynamicShortcuts(List)}.
+ *
+ * <ul>
+ * <li>Only "main" activities (ones with an intent filter for
+ * {@link Intent#ACTION_MAIN} and {@link Intent#CATEGORY_LAUNCHER}) can be target
+ * activities.
*
- * <p>By default, the first main activity defined in the application manifest will be
+ * <li>By default, the first main activity defined in the application manifest will be
* the target.
*
- * <p>The package name of the target activity must match the package name of the shortcut
- * publisher.
+ * <li>A target activity must belong to the publisher application.
+ * </ul>
*
- * <p>This has nothing to do with the activity that this shortcut will launch. This is
- * a hint to the launcher app about which launcher icon to associate this shortcut with.
+ * @see ShortcutInfo#getActivity()
*/
@NonNull
public Builder setActivity(@NonNull ComponentName activity) {
@@ -748,18 +748,23 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Sets an icon.
- *
- * <ul>
- * <li>Tints set by {@link Icon#setTint} or {@link Icon#setTintList} are not supported.
- * <li>Bitmaps and resources are supported, but "content:" URIs are not supported.
- * </ul>
+ * Sets an icon of a shortcut.
*
- * <p>For performance and security reasons, icons will <b>NOT</b> be available on instances
- * returned by {@link ShortcutManager} or {@link LauncherApps}. Default launcher application
- * can use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}
+ * <p>Icons are not available on {@link ShortcutInfo} instances
+ * returned by {@link ShortcutManager} or {@link LauncherApps}. The default launcher
+ * application can use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}
* or {@link LauncherApps#getShortcutBadgedIconDrawable(ShortcutInfo, int)} to fetch
* shortcut icons.
+ *
+ * <p>Tints set with {@link Icon#setTint} or {@link Icon#setTintList} are not supported
+ * and will be ignored.
+ *
+ * <p>Only icons created with {@link Icon#createWithBitmap(Bitmap)} and
+ * {@link Icon#createWithResource} are supported. Other types such as URI based icons
+ * are not supported.
+ *
+ * @see LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)
+ * @see LauncherApps#getShortcutBadgedIconDrawable(ShortcutInfo, int)
*/
@NonNull
public Builder setIcon(Icon icon) {
@@ -781,11 +786,15 @@ public final class ShortcutInfo implements Parcelable {
/**
* Sets the short title of a shortcut.
*
- * <p>This is a mandatory field, unless it's passed to
- * {@link ShortcutManager#updateShortcuts(List)}.
+ * <p>This is a mandatory field when publishing a new shortcut with
+ * {@link ShortcutManager#addDynamicShortcuts(List)} or
+ * {@link ShortcutManager#setDynamicShortcuts(List)}.
+ *
+ * <p>This field is intended for a concise description of a shortcut.
+ *
+ * <p>The recommended max length is 10 characters.
*
- * <p>This field is intended for a concise description of a shortcut displayed under
- * an icon. The recommend max length is 10 characters.
+ * @see ShortcutInfo#getShortLabel()
*/
@NonNull
public Builder setShortLabel(@NonNull CharSequence shortLabel) {
@@ -809,8 +818,11 @@ public final class ShortcutInfo implements Parcelable {
* Sets the text of a shortcut.
*
* <p>This field is intended to be more descriptive than the shortcut title. The launcher
- * shows this instead of the short title, when it has enough space.
- * The recommend max length is 25 characters.
+ * shows this instead of the short title when it has enough space.
+ *
+ * <p>The recommend max length is 25 characters.
+ *
+ * @see ShortcutInfo#getLongLabel()
*/
@NonNull
public Builder setLongLabel(@NonNull CharSequence longLabel) {
@@ -854,6 +866,11 @@ public final class ShortcutInfo implements Parcelable {
return this;
}
+ /**
+ * Sets the message that should be shown when a shortcut is launched when disabled.
+ *
+ * @see ShortcutInfo#getDisabledMessage()
+ */
@NonNull
public Builder setDisabledMessage(@NonNull CharSequence disabledMessage) {
Preconditions.checkState(
@@ -869,6 +886,7 @@ public final class ShortcutInfo implements Parcelable {
* categorise shortcuts.
*
* @see #SHORTCUT_CATEGORY_CONVERSATION
+ * @see ShortcutInfo#getCategories()
*/
@NonNull
public Builder setCategories(Set<String> categories) {
@@ -877,8 +895,22 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Sets the intent of a shortcut. This is a mandatory field. The extras must only contain
- * persistable information. (See {@link PersistableBundle}).
+ * Sets the intent of a shortcut.
+ *
+ * <p>This is a mandatory field when publishing a new shortcut with
+ * {@link ShortcutManager#addDynamicShortcuts(List)} or
+ * {@link ShortcutManager#setDynamicShortcuts(List)}.
+ *
+ * <p>A shortcut can launch any intent that the publisher application has a permission to
+ * launch -- for example, a shortcut can launch an unexported activity within the publisher
+ * application.
+ *
+ * <p>A shortcut intent doesn't have to point at the target activity.
+ *
+ * <p>{@code intent} can contain extras, but only values of the primitive types are
+ * supported so the system can persist them.
+ *
+ * @see ShortcutInfo#getIntent()
*/
@NonNull
public Builder setIntent(@NonNull Intent intent) {
@@ -890,6 +922,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* "Rank" of a shortcut, which is a non-negative value that's used by the launcher app
* to sort shortcuts.
+ *
+ * See {@link ShortcutInfo#getRank()} for details.
*/
@NonNull
public Builder setRank(int rank) {
@@ -903,7 +937,7 @@ public final class ShortcutInfo implements Parcelable {
* Extras that application can set to any purposes.
*
* <p>Applications can store any meta-data of
- * shortcuts in this, and retrieve later from {@link ShortcutInfo#getExtras()}.
+ * shortcuts in extras, and retrieve later from {@link ShortcutInfo#getExtras()}.
*/
@NonNull
public Builder setExtras(@NonNull PersistableBundle extras) {
@@ -921,7 +955,11 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return the ID of the shortcut.
+ * Returns the ID of a shortcut.
+ *
+ * <p>Shortcut IDs are unique within each publisher application, and must be stable across
+ * devices to that shortcuts will still be valid when restored. See {@link ShortcutManager}
+ * for details.
*/
@NonNull
public String getId() {
@@ -929,7 +967,7 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return the package name of the creator application.
+ * Return the package name of the publisher application.
*/
@NonNull
public String getPackage() {
@@ -937,11 +975,10 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return the target activity, which may be null, in which case the shortcut is not associated
- * with a specific activity.
+ * Return the target activity.
*
- * <p>This has nothing to do with the activity that this shortcut will launch. This is
- * a hint to the launcher app that on which launcher icon this shortcut should be shown.
+ * <p>This has nothing to do with the activity that this shortcut will launch. Launcher
+ * applications should show a shortcut along with the launcher icon for this activity.
*
* @see Builder#setActivity
*/
@@ -956,11 +993,7 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Icon.
- *
- * For performance reasons, this will <b>NOT</b> be available when an instance is returned
- * by {@link ShortcutManager} or {@link LauncherApps}. A launcher application needs to use
- * other APIs in LauncherApps to fetch the bitmap.
+ * Returns the shortcut icon.
*
* @hide
*/
@@ -996,10 +1029,9 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return the shorter version of the shortcut title.
+ * Return the shorter description of a shortcut.
*
- * <p>All shortcuts must have a non-empty title, but this method will return null when
- * {@link #hasKeyFieldsOnly()} is true.
+ * @see Builder#setShortLabel(CharSequence)
*/
@Nullable
public CharSequence getShortLabel() {
@@ -1012,7 +1044,9 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return the shortcut text.
+ * Return the longer description of a shortcut.
+ *
+ * @see Builder#setLongLabel(CharSequence)
*/
@Nullable
public CharSequence getLongLabel() {
@@ -1026,6 +1060,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* Return the message that should be shown when a shortcut in disabled state is launched.
+ *
+ * @see Builder#setDisabledMessage(CharSequence)
*/
@Nullable
public CharSequence getDisabledMessage() {
@@ -1039,6 +1075,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* Return the categories.
+ *
+ * @see Builder#setCategories(Set)
*/
@Nullable
public Set<String> getCategories() {
@@ -1048,12 +1086,11 @@ public final class ShortcutInfo implements Parcelable {
/**
* Return the intent.
*
- * <p>All shortcuts must have an intent, but this method will return null when
- * {@link #hasKeyFieldsOnly()} is true.
+ * <p>Launcher applications <b>cannot</b> see the intent. If a {@link ShortcutInfo} is
+ * obtained via {@link LauncherApps}, then this method will always return null.
+ * Launchers can only start a shortcut intent with {@link LauncherApps#startShortcut}.
*
- * <p>Launcher apps <b>cannot</b> see the intent. If a {@link ShortcutInfo} is obtained via
- * {@link LauncherApps}, then this method will always return null. Launcher apps can only
- * start a shortcut intent with {@link LauncherApps#startShortcut}.
+ * @see Builder#setIntent(Intent)
*/
@Nullable
public Intent getIntent() {
@@ -1096,6 +1133,10 @@ public final class ShortcutInfo implements Parcelable {
*
* <p>"Floating" shortcuts (i.e. shortcuts that are neither dynamic nor manifest) will all
* have rank 0, because there's no sorting for them.
+ *
+ * See the {@link ShortcutManager}'s class javadoc for details.
+ *
+ * @see Builder#setRank(int)
*/
public int getRank() {
return mRank;
@@ -1139,6 +1180,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* Extras that application can set to any purposes.
+ *
+ * @see Builder#setExtras(PersistableBundle)
*/
@Nullable
public PersistableBundle getExtras() {
@@ -1151,7 +1194,7 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * {@link UserHandle} on which the publisher created shortcuts.
+ * {@link UserHandle} on which the publisher created a shortcut.
*/
public UserHandle getUserHandle() {
return UserHandle.of(mUserId);
@@ -1201,16 +1244,13 @@ public final class ShortcutInfo implements Parcelable {
}
/**
- * Return whether a shortcut is published via AndroidManifest.xml or not. If {@code true},
+ * Return whether a shortcut is published AndroidManifest.xml or not. If {@code true},
* it's also {@link #isImmutable()}.
*
* <p>When an app is upgraded and a shortcut is no longer published from AndroidManifest.xml,
* this will be set to {@code false}. If the shortcut is not pinned, then it'll just disappear.
* However, if it's pinned, it will still be alive, and {@link #isEnabled()} will be
* {@code false} and {@link #isImmutable()} will be {@code true}.
- *
- * <p>NOTE this is whether a shortcut is published from the <b>current version's</b>
- * AndroidManifest.xml.
*/
public boolean isDeclaredInManifest() {
return hasFlags(FLAG_MANIFEST);
@@ -1311,6 +1351,12 @@ public final class ShortcutInfo implements Parcelable {
* <li>{@link #isEnabled()}
* <li>{@link #getUserHandle()}
* </ul>
+ *
+ * <p>{@link ShortcutInfo}s passed to
+ * {@link LauncherApps.Callback#onShortcutsChanged(String, List, UserHandle)}
+ * as well as returned by {@link LauncherApps#getShortcuts(ShortcutQuery, UserHandle)} with
+ * the {@link ShortcutQuery#FLAG_GET_KEY_FIELDS_ONLY} option will only have key information
+ * for performance reasons.
*/
public boolean hasKeyFieldsOnly() {
return hasFlags(FLAG_KEY_FIELDS_ONLY);
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 1af63a01ce2b..f6c0be07db84 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -20,6 +20,7 @@ import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.app.usage.UsageStatsManager;
import android.content.Context;
+import android.content.Intent;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -28,62 +29,333 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.List;
-// TODO Enhance javadoc
/**
- * <b>TODO: Update to reflect DR changes, such as manifest shortcuts.</b><br>
+ * ShortcutManager manages "launcher shortcuts" (or simply "shortcuts"). Shortcuts provide user
+ * with quick
+ * ways to access activities other than the main activity from the launcher to users. For example,
+ * an email application may publish the "compose new email" action which will directly open the
+ * compose activity. The {@link ShortcutInfo} class represents shortcuts.
*
- * {@link ShortcutManager} manages shortcuts created by applications.
+ * <h3>Dynamic Shortcuts and Manifest Shortcuts</h3>
*
- * <h3>Dynamic shortcuts and pinned shortcuts</h3>
+ * There are two ways to publish shortcuts: manifest shortcuts and dynamic shortcuts.
*
- * An application can publish shortcuts with {@link #setDynamicShortcuts(List)} and
- * {@link #addDynamicShortcuts(List)}. There can be at most
- * {@link #getMaxShortcutCountPerActivity()} number of dynamic shortcuts at a time from the
- * same application.
- * A dynamic shortcut can be deleted with {@link #removeDynamicShortcuts(List)}, and apps
- * can also use {@link #removeAllDynamicShortcuts()} to delete all dynamic shortcuts.
+ * <ul>
+ * <li>Manifest shortcuts are declared in a resource XML which is referred to from
+ * AndroidManifest.xml. Manifest shortcuts are published when an application is installed,
+ * and are updated when an application is upgraded with an updated XML file.
+ * Manifest shortcuts are immutable and their
+ * definitions (e.g. icons and labels) can not be changed dynamically (without upgrading the
+ * publisher application).
+ *
+ * <li>Dynamic shortcuts are published at runtime with {@link ShortcutManager} APIs.
+ * Applications can publish, update and remove dynamic shortcuts at runtime with certain limitations
+ * described below.
+ * </ul>
+ *
+ * <p>Only "main" activities (i.e. activities that handle the {@code MAIN} action and the
+ * {@code LAUNCHER} category) can have shortcuts. If an application has multiple main activities,
+ * they will have different set of shortcuts.
+ *
+ * <p>Dynamic shortcuts and manifest shortcuts are shown by launcher applications when the user
+ * takes a certain action (e.g. long-press) on an application launcher icon.
+ *
+ * <p>Each launcher icon can have at most {@link #getMaxShortcutCountPerActivity()} number of
+ * dynamic and manifest shortcuts combined.
+ *
+ *
+ * <h3>Pinning Shortcuts</h3>
+ *
+ * Launcher applications allow users to "pin" shortcuts so they're easier to access. Both manifest
+ * and dynamic shortcuts can be pinned, to avoid user's confusion.
+ * Pinned shortcuts <b>cannot</b> be removed by publisher
+ * applications -- they are only removed when the publisher is uninstalled. (Or the user performs
+ * "clear data" on the publisher application on the Settings application.)
+ *
+ * <p>Publisher can however "disable" pinned shortcuts so they cannot be launched. See below
+ * for details.
+ *
+ *
+ * <h3>Updating and Disabling Shortcuts</h3>
+ *
+ * <p>When a dynamic shortcut is pinned, even when the publisher removes it as a dynamic shortcut,
+ * the pinned shortcut will still be available and launchable. This allows an application to have
+ * more than {@link #getMaxShortcutCountPerActivity()} number of shortcuts -- for example, suppose
+ * {@link #getMaxShortcutCountPerActivity()} is 5:
+ * <ul>
+ * <li>A chat application publishes 5 dynamic shortcuts for the 5 most recent
+ * conversations, "c1" - "c5".
+ *
+ * <li>The user pins all of the 5 shortcuts.
+ *
+ * <li>Later, the user has 3 newer conversations ("c6", "c7" and "c8"), so the application
+ * re-publishes dynamic shortcuts and now it has the dynamic shortcuts "c4", "c5", "c6", "c7"
+ * and "c8". The publisher has to remove "c1", "c2" and "c3" because it can't have more than
+ * 5 dynamic shortcuts.
+ *
+ * <li>However, even though "c1", "c2" and "c3" are no longer dynamic shortcuts, the pinned
+ * shortcuts for those conversations are still available and launchable.
+ *
+ * <li>At this point, the application has 8 shortcuts in total, including the 3 pinned
+ * shortcuts, even though it's allowed to have at most 5 dynamic shortcuts.
+ *
+ * <li>The application can use {@link #updateShortcuts(List)} to update any of the existing
+ * 8 shortcuts, when, for example, the chat peers' icons have changed.
+ * </ul>
+ * {@link #addDynamicShortcuts(List)} and {@link #setDynamicShortcuts(List)} can also be used
+ * to update existing shortcuts with the same IDs, but they <b>cannot</b> be used for
+ * non-dynamic pinned shortcuts because these two APIs will always try to make the passed
+ * shortcuts dynamic.
+ *
+ *
+ * <h4>Disabling Manifest Shortcuts</h4>
+ * Sometimes pinned shortcuts become obsolete and may not be usable. For example, a pinned shortcut
+ * to a group chat will be unusable when the group chat room is deleted. In cases like this,
+ * applications should use {@link #disableShortcuts(List)}, which will remove the specified dynamic
+ * shortcuts and also make the pinned shortcuts un-launchable, if any.
+ * {@link #disableShortcuts(List, CharSequence)} can also be used to disable shortcuts with
+ * a custom error message that will be shown when the user starts the shortcut.
+ *
+ * <h4>Disabling Manifest Shortcuts</h4>
+ * When an application is upgraded and the new version no longer has a manifest shortcut that
+ * the previous version had, this shortcut will no longer be published as a manifest shortcut.
+ *
+ * <p>If the shortcut is pinned, then the pinned shortcut will remain on the launcher, but will be
+ * disabled. Note in this case, the pinned shortcut is no longer a manifest shortcut, but is
+ * still <b>immutable</b> and cannot be updated with the {@link ShortcutManager} APIs.
+ *
+ *
+ * <h3>Publishing Dynamic Shortcuts</h3>
+ *
+ * Applications can publish dynamic shortcuts with {@link #setDynamicShortcuts(List)}
+ * or {@link #addDynamicShortcuts(List)}. {@link #updateShortcuts(List)} can also be used to
+ * update existing (mutable) shortcuts.
+ * Use {@link #removeDynamicShortcuts(List)} or {@link #removeAllDynamicShortcuts()} to remove
+ * dynamic shortcuts.
+ *
+ * <p>Example:
+ * <pre>
+ * ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
+ *
+ * ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "id1")
+ * .setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.mysite.com/")))
+ * .setShortLabel("Web site")
+ * .setLongLabel("Open the web site")
+ * .setIcon(Icon.createWithResource(context, R.drawable.icon_website))
+ * .build();
*
- * <p>The shortcuts that are currently published by the above APIs are called "dynamic", because
- * they can be removed by the creator application at any time. The user may "pin" dynamic shortcuts
- * on Launcher to make "pinned" shortcuts. Pinned shortcuts <b>cannot</b> be removed by the creator
- * app. An application can obtain all pinned shortcuts from itself with
- * {@link #getPinnedShortcuts()}. Applications should keep the pinned shortcut information
- * up-to-date using {@link #updateShortcuts(List)}.
+ * shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut));
+ * </pre>
*
- * <p>The number of pinned shortcuts does not affect the number of dynamic shortcuts that can be
- * published by an application at a time.
- * No matter how many pinned shortcuts that Launcher has for an application, the
- * application can still always publish {@link #getMaxShortcutCountPerActivity()} number of
- * dynamic
- * shortcuts.
*
- * <h3>Shortcut IDs</h3>
+ * <h3>Publishing Manifest Shortcuts</h3>
*
- * Each shortcut must have an ID, which must be unique within each application. When a shortcut is
- * published, existing shortcuts with the same ID will be updated. Note this may include a
- * pinned shortcut.
+ * In order to add manifest shortcuts to your application, first add
+ * {@code <meta-data android:name="android.app.shortcuts" />} to your main activity in
+ * AndroidManifest.xml.
+ * <pre>
+ * &lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+ * package=&quot;com.example.myapplication&quot;&gt;
+ * &lt;application . . .&gt;
+ * &lt;activity android:name=&quot;Main&quot;&gt;
+ * &lt;intent-filter&gt;
+ * &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
+ * &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
+ * &lt;/intent-filter&gt;
+ * <b>&lt;meta-data android:name=&quot;android.app.shortcuts&quot; android:resource=&quot;@xml/shortcuts&quot;/&gt;</b>
+ * &lt;/activity&gt;
+ * &lt;/application&gt;
+ * &lt;/manifest&gt;
+ * </pre>
+ *
+ * Then define shortcuts in res/xml/shortcuts.xml.
+ * <pre>
+ * &lt;shortcuts xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; &gt;
+ * &lt;shortcut
+ * android:shortcutId=&quot;compose&quot;
+ * android:enabled=&quot;true&quot;
+ * android:icon=&quot;@drawable/compose_icon&quot;
+ * android:shortcutShortLabel=&quot;@string/compose_shortcut_short_label1&quot;
+ * android:shortcutLongLabel=&quot;@string/compose_shortcut_short_label1&quot;
+ * android:shortcutDisabledMessage=&quot;@string/compose_disabled_message1&quot;
+ * &gt;
+ * &lt;intent
+ * android:action=&quot;android.intent.action.VIEW&quot;
+ * android:targetPackage=&quot;com.example.myapplication&quot;
+ * android:targetClass=&quot;com.example.myapplication.ComposeActivity&quot; /&gt;
+ * &lt;categories android:name=&quot;android.shortcut.conversation&quot; /&gt;
+ * &lt;/shortcut&gt;
+ * &lt;!-- more shortcut can go here --&gt;
+ * &lt;/shortcuts&gt;
+ * </pre>
+ * <ul>
+ * <li>{@code android:shortcutId} Mandatory shortcut ID
+ *
+ * <li>{@code android:enabled} Default is {@code true}. Can be set to {@code false} in order
+ * to disable a manifest shortcut that was published on a previous version with a custom
+ * disabled message. If a custom disabled message is not needed, then a manifest shortcut can
+ * be simply removed from the xml file rather than keeping it with {@code enabled="false"}.
+ *
+ * <li>{@code android:icon} Shortcut icon.
+ *
+ * <li>{@code android:shortcutShortLabel} Mandatory shortcut short label.
+ * See {@link ShortcutInfo.Builder#setShortLabel(CharSequence)}
+ *
+ * <li>{@code android:shortcutLongLabel} Shortcut long label.
+ * See {@link ShortcutInfo.Builder#setLongLabel(CharSequence)}
+ *
+ * <li>{@code android:shortcutDisabledMessage} When {@code android:enabled} is set to
+ * {@code false}, this can be used to set a custom disabled message.
+ *
+ * <li>{@code intent} Intent to launch. {@code android:action} is mandatory.
+ * See <a href="{@docRoot}guide/topics/ui/settings.html#Intents">Using intents</a> for the
+ * other supported tags.
+ * </ul>
+ *
+ * <h3>Updating Shortcuts v.s. Re-publishing New One with Different ID</h3>
+ * In order to avoid users' confusion, {@link #updateShortcuts(List)} should not be used to update
+ * a shortcut to something that is conceptually different.
+ *
+ * <p>For example, a phone application may publish the most frequently called contact as a dynamic
+ * shortcut. Over the time, this contact may change, but when it changes the application should
+ * publish a new contact with a different ID with either
+ * {@link #setDynamicShortcuts(List)} or {@link #addDynamicShortcuts(List)}, rather than updating
+ * the existing shortcut with {@link #updateShortcuts(List)}.
+ *
+ * This is because when the shortcut is pinned, changing it to a different contact
+ * will likely confuse the user.
+ *
+ * <p>On the other hand, when the contact's information (e.g. the name or picture) has changed,
+ * then the application should use {@link #updateShortcuts(List)} so that the pinned shortcut
+ * will be updated too.
+ *
+ *
+ * <h3>Shortcut Display Order</h3>
+ * When the launcher show the shortcuts for a launcher icon, the showing order should be the
+ * following:
+ * <ul>
+ * <li>First show manifest shortcuts
+ * ({@link ShortcutInfo#isDeclaredInManifest()} is {@code true}),
+ * and then dynamic shortcuts ({@link ShortcutInfo#isDynamic()} is {@code true}).
+ * <li>Within each category, sort by {@link ShortcutInfo#getRank()}.
+ * </ul>
+ * <p>Shortcut ranks are non-negative sequential integers for each target activity. Ranks of
+ * existing shortcuts can be updated with
+ * {@link #updateShortcuts(List)} ({@link #addDynamicShortcuts(List)} and
+ * {@link #setDynamicShortcuts(List)} may be used too).
+ *
+ * <p>Ranks will be auto-adjusted so that they're unique for each target activity for each category
+ * (dynamic or manifest). For example, if there are 3 dynamic shortcuts with ranks 0, 1 and 2,
+ * adding another dynamic shortcut with rank = 1 means to place this shortcut at the second
+ * position. The third and forth shortcuts (that were originally second and third) will be adjusted
+ * to 2 and 3 respectively.
+ *
+ * <h3>Rate Limiting</h3>
+ *
+ * Calls to {@link #setDynamicShortcuts(List)}, {@link #addDynamicShortcuts(List)} and
+ * {@link #updateShortcuts(List)} may be rate-limited when called by background applications (i.e.
+ * applications with no foreground activity or service). When rate-limited, these APIs will return
+ * {@code false}.
+ *
+ * <p>Applications with a foreground activity or service will not be rate-limited.
+ *
+ * <p>Rate-limiting will be reset upon certain events, so that even background applications
+ * will be able to call these APIs again (until they are rate-limited again).
+ * <ul>
+ * <li>When an application comes to foreground.
+ * <li>When the system locale changes.
+ * <li>When the user performs "inline reply" on a notification.
+ * </ul>
+ *
+ * <h4>Resetting rate-limiting for testing</h4>
+ *
+ * If your application is rate-limited during development or testing, you can use the
+ * "Reset ShortcutManager rate-limiting" development option, or the following adb command to reset
+ * it.
+ * <pre>
+ * adb shell cmd shortcut reset-throttling [ --user USER-ID ]
+ * </pre>
+ *
+ * <h3>Handling System Locale Change</h3>
+ *
+ * Applications should update dynamic and pinned shortcuts when the system locale changes
+ * using the {@link Intent#ACTION_LOCALE_CHANGED} broadcast.
+ *
+ * <p>When the system locale changes, rate-limiting will be reset, so even background applications
+ * what were previously rate-limited will be able to call {@link #updateShortcuts(List)}.
*
*
* <h3>Backup and Restore</h3>
*
- * Pinned shortcuts will be backed up and restored across devices. This means all information
- * within shortcuts, including IDs, must be meaningful on different devices.
+ * When an application has {@code android:allowBackup="true"} in its AndroidManifest.xml, pinned
+ * shortcuts will be backed up automatically and restored when the user sets up a new device.
+ *
+ * <h4>What will be backed up and what will not be backed up</h4>
*
- * <p>Note that:
* <ul>
- * <li>Dynamic shortcuts will not be backed up or restored.
- * <li>Icons of pinned shortcuts will <b>not</b> be backed up for performance reasons, unless
- * they refer to resources. Instead, launcher applications are supposed to back up and restore
- * icons of pinned shortcuts by themselves, and thus from the user's point of view, pinned
- * shortcuts will look to have icons restored.
+ * <li>Pinned shortcuts will be backed up. Bitmap icons will not be backed up by the system,
+ * but launcher applications should back them up and restore them, so the user will still get
+ * icons for pinned shortcuts on the launcher. Applications can always use
+ * {@link #updateShortcuts(List)} to re-publish icons.
+ *
+ * <li>Manifest shortcuts will not be backed up, but when an application is re-installed on a new
+ * device, they will be re-published from AndroidManifest.xml anyway.
+ *
+ * <li>Dynamic shortcuts will <b>not</b> be backed up.
* </ul>
*
+ * <p>Because dynamic shortcuts will not restored, it is recommended that applications check
+ * currently published dynamic shortcuts with {@link #getDynamicShortcuts()} when they start,
+ * and re-publish dynamic shortcuts when necessary.
+ *
+ * <pre>
+ * public class MainActivity extends Activity {
+ * public void onCreate(Bundle savedInstanceState) {
+ * super.onCreate(savedInstanceState);
+ *
+ * ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
+ *
+ * if (shortcutManager.getDynamicShortcuts().size() == 0) {
+ * // Application restored; re-publish dynamic shortcuts.
+ *
+ * if (shortcutManager.getPinnedShortcuts().size() > 0) {
+ * // Pinned shortcuts have been restored. use updateShortcuts() to make sure
+ * // they have up-to-date information.
+ * }
+ * }
+ * }
+ * :
+ *
+ * }
+ * </pre>
*
- * <h3>APIs for launcher</h3>
*
- * Launcher applications should use {@link LauncherApps} to get shortcuts that are published from
- * applications. Launcher applications can also pin shortcuts with
- * {@link LauncherApps#pinShortcuts(String, List, UserHandle)}.
+ * <h4>Backup/restore and shortcut IDs</h4>
+ *
+ * Because pinned shortcuts will be backed up and restored on new devices, shortcut IDs should be
+ * meaningful across devices; that is, IDs should be either stable constant strings, or server-side
+ * identifiers, rather than identifiers generated locally that may not make sense on other devices.
+ *
+ *
+ * <h3>Report Shortcut Usage and Prediction</h3>
+ *
+ * Launcher applications may be capable of predicting which shortcuts will most likely be used at
+ * the moment with the shortcut usage history data.
+ *
+ * <p>In order to provide launchers with such data, publisher applications should report which
+ * shortcut is used with {@link #reportShortcutUsed(String)} when a shortcut is started,
+ * <b>or when an action equivalent to a shortcut is taken by the user even if it wasn't started
+ * with the shortcut</b>.
+ *
+ * <p>For example, suppose a GPS navigation application exposes "navigate to work" as a shortcut.
+ * Then it should report it when the user starts this shortcut, and also when the user navigates
+ * to work within the application without using the shortcut. This helps the launcher application
+ * learn that the user wants to navigate to work at a certain time every weekday, so that the
+ * launcher can show this shortcut in a suggestion list.
+ *
+ * <h3>Launcher API</h3>
+ *
+ * {@link LauncherApps} provides APIs for launcher applications to access shortcuts.
*/
public class ShortcutManager {
private static final String TAG = "ShortcutManager";
@@ -110,14 +382,15 @@ public class ShortcutManager {
/**
* Publish a list of shortcuts. All existing dynamic shortcuts from the caller application
- * will be replaced.
+ * will be replaced. If there's already pinned shortcuts with the same IDs, they will all be
+ * updated, unless they're immutable.
*
* <p>This API will be rate-limited.
*
* @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
*
- * @throws IllegalArgumentException if {@code shortcutInfoList} contains more than
- * {@link #getMaxShortcutCountPerActivity()} shortcuts.
+ * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
+ * or trying to update immutable shortcuts.
*/
public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
try {
@@ -129,8 +402,7 @@ public class ShortcutManager {
}
/**
- * Return all dynamic shortcuts from the caller application. The number of result items
- * will not exceed the value returned by {@link #getMaxShortcutCountPerActivity()}.
+ * Return all dynamic shortcuts from the caller application.
*/
@NonNull
public List<ShortcutInfo> getDynamicShortcuts() {
@@ -143,7 +415,7 @@ public class ShortcutManager {
}
/**
- * TODO Javadoc
+ * Return all manifest shortcuts from the caller application.
*/
@NonNull
public List<ShortcutInfo> getManifestShortcuts() {
@@ -157,14 +429,14 @@ public class ShortcutManager {
/**
* Publish list of dynamic shortcuts. If there's already dynamic or pinned shortcuts with
- * the same IDs, they will all be updated.
+ * the same IDs, they will all be updated, unless they're immutable.
*
* <p>This API will be rate-limited.
*
* @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
*
- * @throws IllegalArgumentException if the caller application has already published the
- * max number of dynamic shortcuts.
+ * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
+ * or trying to update immutable shortcuts.
*/
public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
try {
@@ -212,11 +484,14 @@ public class ShortcutManager {
}
/**
- * Update all existing shortcuts with the same IDs. Shortcuts may be pinned and/or dynamic.
+ * Update all existing shortcuts with the same IDs. Target shortcuts may be pinned and/or
+ * dynamic, but may not be immutable.
*
* <p>This API will be rate-limited.
*
* @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
+ *
+ * @throws IllegalArgumentException if trying to update immutable shortcuts.
*/
public boolean updateShortcuts(List<ShortcutInfo> shortcutInfoList) {
try {
@@ -228,7 +503,7 @@ public class ShortcutManager {
}
/**
- * TODO Javadoc
+ * Disable pinned shortcuts. See {@link ShortcutManager}'s class javadoc for details.
*/
public void disableShortcuts(@NonNull List<String> shortcutIds) {
try {
@@ -261,7 +536,8 @@ public class ShortcutManager {
}
/**
- * TODO Javadoc
+ * Disable pinned shortcuts with a custom error message.
+ * See {@link ShortcutManager}'s class javadoc for details.
*/
public void disableShortcuts(@NonNull List<String> shortcutIds, CharSequence disabledMessage) {
try {
@@ -274,7 +550,7 @@ public class ShortcutManager {
}
/**
- * TODO Javadoc
+ * Re-enable disabled pinned shortcuts.
*/
public void enableShortcuts(@NonNull List<String> shortcutIds) {
try {
@@ -293,7 +569,7 @@ public class ShortcutManager {
}
/**
- * Return the max number of dynamic shortcuts + manifest shortcuts that each launcher icon
+ * Return the max number of dynamic and manifest shortcuts that each launcher icon
* can have at a time.
*/
public int getMaxShortcutCountPerActivity() {
@@ -362,12 +638,9 @@ public class ShortcutManager {
}
/**
- * Applications that publish shortcuts should call this method whenever an action that's
- * equivalent to an existing shortcut has been taken by the user. This includes not only when
- * the user manually taps a shortcut, but when the user takes an equivalent action within the
- * application -- for example, when a music player application has a shortcut to playlist X,
- * then the application should not only report it when the playlist is opened from the
- * shortcut, but also when the user plays the playlist within the application.
+ * Applications that publish shortcuts should call this method whenever a shortcut is started
+ * or an action equivalent to a shortcut is taken. See the {@link ShortcutManager} class
+ * javadoc for details.
*
* <p>The information is accessible via {@link UsageStatsManager#queryEvents}
* Typically, launcher applications use this information to build a prediction model
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 92134ee01de8..1e44a5ccafc9 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -49,6 +49,10 @@ public class TypedArray {
attrs.mLength = len;
attrs.mRecycled = false;
+ // Reset the assets, which may have changed due to configuration changes
+ // or further resource loading.
+ attrs.mAssets = res.getAssets();
+
final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
if (attrs.mData.length >= fullLen) {
return attrs;
@@ -66,7 +70,7 @@ public class TypedArray {
private final Resources mResources;
private final DisplayMetrics mMetrics;
- private final AssetManager mAssets;
+ private AssetManager mAssets;
private boolean mRecycled;
@@ -1086,6 +1090,7 @@ public class TypedArray {
// These may have been set by the client.
mXml = null;
mTheme = null;
+ mAssets = null;
mResources.mTypedArrayPool.release(this);
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 3917bfa6beea..145b1d076e80 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -267,6 +267,10 @@ public final class CameraManager {
* @param cameraId The unique identifier of the camera device to open
* @param callback The callback for the camera. Must not be null.
* @param handler The handler to invoke the callback on. Must not be null.
+ * @param uid The UID of the application actually opening the camera.
+ * Must be USE_CALLING_UID unless the caller is a service
+ * that is trusted to open the device on behalf of an
+ * application and to forward the real UID.
*
* @throws CameraAccessException if the camera is disabled by device policy,
* too many camera devices are already open, or the cameraId does not match
@@ -281,7 +285,7 @@ public final class CameraManager {
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
*/
private CameraDevice openCameraDeviceUserAsync(String cameraId,
- CameraDevice.StateCallback callback, Handler handler)
+ CameraDevice.StateCallback callback, Handler handler, final int uid)
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
@@ -317,7 +321,7 @@ public final class CameraManager {
"Camera service is currently unavailable");
}
cameraUser = cameraService.connectDevice(callbacks, id,
- mContext.getOpPackageName(), USE_CALLING_UID);
+ mContext.getOpPackageName(), uid);
} else {
// Use legacy camera implementation for HAL1 devices
Log.i(TAG, "Using legacy camera HAL.");
@@ -434,6 +438,29 @@ public final class CameraManager {
@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)
throws CameraAccessException {
+ openCameraForUid(cameraId, callback, handler, USE_CALLING_UID);
+ }
+
+ /**
+ * Open a connection to a camera with the given ID, on behalf of another application
+ * specified by clientUid.
+ *
+ * <p>The behavior of this method matches that of {@link #openCamera}, except that it allows
+ * the caller to specify the UID to use for permission/etc verification. This can only be
+ * done by services trusted by the camera subsystem to act on behalf of applications and
+ * to forward the real UID.</p>
+ *
+ * @param clientUid
+ * The UID of the application on whose behalf the camera is being opened.
+ * Must be USE_CALLING_UID unless the caller is a trusted service.
+ *
+ * @hide
+ */
+ public void openCameraForUid(@NonNull String cameraId,
+ @NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler,
+ int clientUid)
+ throws CameraAccessException {
+
if (cameraId == null) {
throw new IllegalArgumentException("cameraId was null");
} else if (callback == null) {
@@ -447,7 +474,7 @@ public final class CameraManager {
}
}
- openCameraDeviceUserAsync(cameraId, callback, handler);
+ openCameraDeviceUserAsync(cameraId, callback, handler, clientUid);
}
/**
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
index 43e596fe5566..fcbc962f0743 100644
--- a/core/java/android/hardware/location/ContextHubService.java
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -16,6 +16,11 @@
package android.hardware.location;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -53,10 +58,14 @@ public class ContextHubService extends IContextHubService.Stub {
private static final int PRE_LOADED_APP_MEM_REQ = 0;
private static final int MSG_HEADER_SIZE = 4;
- private static final int MSG_FIELD_TYPE = 0;
- private static final int MSG_FIELD_VERSION = 1;
- private static final int MSG_FIELD_HUB_HANDLE = 2;
- private static final int MSG_FIELD_APP_INSTANCE = 3;
+ private static final int HEADER_FIELD_MSG_TYPE = 0;
+ private static final int HEADER_FIELD_MSG_VERSION = 1;
+ private static final int HEADER_FIELD_HUB_HANDLE = 2;
+ private static final int HEADER_FIELD_APP_INSTANCE = 3;
+
+ private static final int HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
+ private static final int HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
+ private static final int MSG_LOAD_APP_HEADER_SIZE = MSG_HEADER_SIZE + 2;
private static final int OS_APP_INSTANCE = -1;
@@ -146,11 +155,16 @@ public class ContextHubService extends IContextHubService.Stub {
return -1;
}
- int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[MSG_FIELD_HUB_HANDLE] = contextHubHandle;
- msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
- msgHeader[MSG_FIELD_VERSION] = 0;
- msgHeader[MSG_FIELD_TYPE] = MSG_LOAD_NANO_APP;
+ int[] msgHeader = new int[MSG_LOAD_APP_HEADER_SIZE];
+ msgHeader[HEADER_FIELD_HUB_HANDLE] = contextHubHandle;
+ msgHeader[HEADER_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
+ msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
+ msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_LOAD_NANO_APP;
+
+ long appId = app.getAppId();
+
+ msgHeader[HEADER_FIELD_LOAD_APP_ID_LO] = (int)(appId & 0xFFFFFFFF);
+ msgHeader[HEADER_FIELD_LOAD_APP_ID_HI] = (int)((appId >> 32) & 0xFFFFFFFF);
if (nativeSendMessage(msgHeader, app.getAppBinary()) != 0) {
return -1;
@@ -169,12 +183,14 @@ public class ContextHubService extends IContextHubService.Stub {
// Call Native interface here
int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[MSG_FIELD_HUB_HANDLE] = ANY_HUB;
- msgHeader[MSG_FIELD_APP_INSTANCE] = OS_APP_INSTANCE;
- msgHeader[MSG_FIELD_VERSION] = 0;
- msgHeader[MSG_FIELD_TYPE] = MSG_UNLOAD_NANO_APP;
+ msgHeader[HEADER_FIELD_HUB_HANDLE] = ANY_HUB;
+ msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppInstanceHandle;
+ msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
+ msgHeader[HEADER_FIELD_MSG_TYPE] = MSG_UNLOAD_NANO_APP;
- if (nativeSendMessage(msgHeader, null) != 0) {
+ byte msg[] = new byte[0];
+
+ if (nativeSendMessage(msgHeader, msg) != 0) {
return -1;
}
@@ -222,10 +238,10 @@ public class ContextHubService extends IContextHubService.Stub {
checkPermissions();
int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[MSG_FIELD_HUB_HANDLE] = hubHandle;
- msgHeader[MSG_FIELD_APP_INSTANCE] = nanoAppHandle;
- msgHeader[MSG_FIELD_VERSION] = msg.getVersion();
- msgHeader[MSG_FIELD_TYPE] = msg.getMsgType();
+ msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle;
+ msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppHandle;
+ msgHeader[HEADER_FIELD_MSG_VERSION] = msg.getVersion();
+ msgHeader[HEADER_FIELD_MSG_TYPE] = msg.getMsgType();
return nativeSendMessage(msgHeader, msg.getData());
}
@@ -269,15 +285,17 @@ public class ContextHubService extends IContextHubService.Stub {
Log.v(TAG, "No message callbacks registered.");
return 0;
}
- ContextHubMessage message =
- new ContextHubMessage(header[MSG_FIELD_TYPE], header[MSG_FIELD_VERSION], data);
+
+ ContextHubMessage msg = new ContextHubMessage(header[HEADER_FIELD_MSG_TYPE],
+ header[HEADER_FIELD_MSG_VERSION],
+ data);
for (int i = 0; i < callbacksCount; ++i) {
IContextHubCallback callback = mCallbacksList.getBroadcastItem(i);
try {
callback.onMessageReceipt(
- header[MSG_FIELD_HUB_HANDLE],
- header[MSG_FIELD_APP_INSTANCE],
- message);
+ header[HEADER_FIELD_HUB_HANDLE],
+ header[HEADER_FIELD_APP_INSTANCE],
+ msg);
} catch (RemoteException e) {
Log.i(TAG, "Exception (" + e + ") calling remote callback (" + callback + ").");
continue;
@@ -308,12 +326,20 @@ public class ContextHubService extends IContextHubService.Stub {
return 0;
}
+ private int deleteAppInstance(int appInstanceHandle) {
+ if (mNanoAppHash.remove(appInstanceHandle) == null) {
+ return -1;
+ }
+
+ return 0;
+ }
+
private void sendVrStateChangeMessageToApp(NanoAppInstanceInfo app, boolean vrModeEnabled) {
int[] msgHeader = new int[MSG_HEADER_SIZE];
- msgHeader[MSG_FIELD_TYPE] = 0;
- msgHeader[MSG_FIELD_VERSION] = 0;
- msgHeader[MSG_FIELD_HUB_HANDLE] = ANY_HUB;
- msgHeader[MSG_FIELD_APP_INSTANCE] = app.getHandle();
+ msgHeader[HEADER_FIELD_MSG_TYPE] = 0;
+ msgHeader[HEADER_FIELD_MSG_VERSION] = 0;
+ msgHeader[HEADER_FIELD_HUB_HANDLE] = ANY_HUB;
+ msgHeader[HEADER_FIELD_APP_INSTANCE] = app.getHandle();
byte[] data = new byte[1];
data[0] = (byte) ((vrModeEnabled) ? 1 : 0);
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 8f21b38ec25f..629db06a30e3 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -43,7 +43,7 @@ import java.util.HashMap;
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>For more information about communicating with USB hardware, read the
- * <a href="{@docRoot}guide/topics/usb/index.html">USB</a> developer guide.</p>
+ * <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB developer guide</a>.</p>
* </div>
*/
public class UsbManager {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 8d4137957b3f..3c2ac6733c52 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1035,6 +1035,26 @@ public class ConnectivityManager {
}
/**
+ * Request that this callback be invoked at ConnectivityService's earliest
+ * convenience with the current satisfying network's LinkProperties.
+ * If no such network exists no callback invocation is performed.
+ *
+ * The callback must have been registered with #requestNetwork() or
+ * #registerDefaultNetworkCallback(); callbacks registered with
+ * registerNetworkCallback() are not specific to any particular Network so
+ * do not cause any updates.
+ *
+ * @hide
+ */
+ public void requestLinkProperties(NetworkCallback networkCallback) {
+ try {
+ mService.requestLinkProperties(networkCallback.networkRequest);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This
* will return {@code null} if the network is unknown.
* <p>This method requires the caller to hold the permission
@@ -1052,6 +1072,26 @@ public class ConnectivityManager {
}
/**
+ * Request that this callback be invoked at ConnectivityService's earliest
+ * convenience with the current satisfying network's NetworkCapabilities.
+ * If no such network exists no callback invocation is performed.
+ *
+ * The callback must have been registered with #requestNetwork() or
+ * #registerDefaultNetworkCallback(); callbacks registered with
+ * registerNetworkCallback() are not specific to any particular Network so
+ * do not cause any updates.
+ *
+ * @hide
+ */
+ public void requestNetworkCapabilities(NetworkCallback networkCallback) {
+ try {
+ mService.requestNetworkCapabilities(networkCallback.networkRequest);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Gets the URL that should be used for resolving whether a captive portal is present.
* 1. This URL should respond with a 204 response to a GET request to indicate no captive
* portal is present.
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 0d518cc14049..d48c155986f3 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -156,6 +156,8 @@ interface IConnectivityManager
void pendingListenForNetwork(in NetworkCapabilities networkCapabilities,
in PendingIntent operation);
+ void requestLinkProperties(in NetworkRequest networkRequest);
+ void requestNetworkCapabilities(in NetworkRequest networkRequest);
void releaseNetworkRequest(in NetworkRequest networkRequest);
void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 384ab1c8f50c..6e74f14bd138 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -103,7 +103,7 @@ public class LinkAddress implements Parcelable {
private boolean isIPv6ULA() {
if (address != null && address instanceof Inet6Address) {
byte[] bytes = address.getAddress();
- return ((bytes[0] & (byte)0xfc) == (byte)0xfc);
+ return ((bytes[0] & (byte)0xfe) == (byte)0xfc);
}
return false;
}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 141af3d49563..35e3065b078f 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -45,13 +45,20 @@ public class NetworkUtils {
public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException;
/**
- * Attaches a socket filter that accepts ICMP6 router advertisement packets to the given socket.
+ * Attaches a socket filter that accepts ICMPv6 router advertisements to the given socket.
* @param fd the socket's {@link FileDescriptor}.
* @param packetType the hardware address type, one of ARPHRD_*.
*/
public native static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException;
/**
+ * Configures a socket for receiving ICMPv6 router solicitations and sending advertisements.
+ * @param fd the socket's {@link FileDescriptor}.
+ * @param ifIndex the interface index.
+ */
+ public native static void setupRaSocket(FileDescriptor fd, int ifIndex) throws SocketException;
+
+ /**
* Binds the current process to the network designated by {@code netId}. All sockets created
* in the future (and not explicitly bound via a bound {@link SocketFactory} (see
* {@link Network#getSocketFactory}) will be bound to this network. Note that if this
diff --git a/core/java/android/net/network-policy-restrictions.md b/core/java/android/net/network-policy-restrictions.md
index fe13f7a5aab9..63ce1a244643 100644
--- a/core/java/android/net/network-policy-restrictions.md
+++ b/core/java/android/net/network-policy-restrictions.md
@@ -29,8 +29,8 @@ More specifically:
| **DS** | *WL* | ok | blk | ok | ok |
| **ON** | *!WL* | blk | blk | blk | blk |
| | *BL* | blk | blk | blk | blk |
-| **DS** | *WL* | blk | ok | ok | ok |
-| **OFF** | *!WL* | blk | ok | ok | ok |
+| **DS** | *WL* | blk | blk | ok | ok |
+| **OFF** | *!WL* | blk | blk | ok | ok |
| | *BL* | blk | blk | blk | blk |
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index fa328090e90a..8d6d9ed567b6 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -62,34 +62,17 @@ public class Environment {
private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm");
private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
- // NoPreloadHolder to separate shared data from user-specific data, and to be able to initialize
- // Environment without side effect (allowing a lazy init of the data where possible).
- private static class NoPreloadHolder {
- public final static UserEnvironment sCurrentUser;
- public static boolean sUserRequired;
-
- static {
- sCurrentUser = new UserEnvironment(UserHandle.myUserId());
- }
-
- // Empty function to be able to trigger static initialization.
- public static void init() {
- }
+ private static UserEnvironment sCurrentUser;
+ private static boolean sUserRequired;
- // Disallow allocation.
- private NoPreloadHolder() {
- }
+ static {
+ initForCurrentUser();
}
/** {@hide} */
- public static void init() {
- NoPreloadHolder.init();
-
- // Check for expected outcome. We only allow one initialization, this will trigger if
- // somebody tried to re-initialize.
- if (NoPreloadHolder.sCurrentUser.mUserId != UserHandle.myUserId()) {
- throw new IllegalStateException();
- }
+ public static void initForCurrentUser() {
+ final int userId = UserHandle.myUserId();
+ sCurrentUser = new UserEnvironment(userId);
}
/** {@hide} */
@@ -303,6 +286,11 @@ public class Environment {
}
/** {@hide} */
+ public static File getReferenceProfile(String packageName) {
+ return buildPath(getDataDirectory(), "misc", "profiles", "ref", packageName);
+ }
+
+ /** {@hide} */
public static File getDataProfilesDePackageDirectory(int userId, String packageName) {
return buildPath(getDataProfilesDeDirectory(userId), packageName);
}
@@ -445,7 +433,7 @@ public class Environment {
*/
public static File getExternalStorageDirectory() {
throwIfUserRequired();
- return NoPreloadHolder.sCurrentUser.getExternalDirs()[0];
+ return sCurrentUser.getExternalDirs()[0];
}
/** {@hide} */
@@ -629,7 +617,7 @@ public class Environment {
*/
public static File getExternalStoragePublicDirectory(String type) {
throwIfUserRequired();
- return NoPreloadHolder.sCurrentUser.buildExternalStoragePublicDirs(type)[0];
+ return sCurrentUser.buildExternalStoragePublicDirs(type)[0];
}
/**
@@ -638,7 +626,7 @@ public class Environment {
*/
public static File[] buildExternalStorageAndroidDataDirs() {
throwIfUserRequired();
- return NoPreloadHolder.sCurrentUser.buildExternalStorageAndroidDataDirs();
+ return sCurrentUser.buildExternalStorageAndroidDataDirs();
}
/**
@@ -647,7 +635,7 @@ public class Environment {
*/
public static File[] buildExternalStorageAppDataDirs(String packageName) {
throwIfUserRequired();
- return NoPreloadHolder.sCurrentUser.buildExternalStorageAppDataDirs(packageName);
+ return sCurrentUser.buildExternalStorageAppDataDirs(packageName);
}
/**
@@ -656,7 +644,7 @@ public class Environment {
*/
public static File[] buildExternalStorageAppMediaDirs(String packageName) {
throwIfUserRequired();
- return NoPreloadHolder.sCurrentUser.buildExternalStorageAppMediaDirs(packageName);
+ return sCurrentUser.buildExternalStorageAppMediaDirs(packageName);
}
/**
@@ -665,7 +653,7 @@ public class Environment {
*/
public static File[] buildExternalStorageAppObbDirs(String packageName) {
throwIfUserRequired();
- return NoPreloadHolder.sCurrentUser.buildExternalStorageAppObbDirs(packageName);
+ return sCurrentUser.buildExternalStorageAppObbDirs(packageName);
}
/**
@@ -674,7 +662,7 @@ public class Environment {
*/
public static File[] buildExternalStorageAppFilesDirs(String packageName) {
throwIfUserRequired();
- return NoPreloadHolder.sCurrentUser.buildExternalStorageAppFilesDirs(packageName);
+ return sCurrentUser.buildExternalStorageAppFilesDirs(packageName);
}
/**
@@ -683,7 +671,7 @@ public class Environment {
*/
public static File[] buildExternalStorageAppCacheDirs(String packageName) {
throwIfUserRequired();
- return NoPreloadHolder.sCurrentUser.buildExternalStorageAppCacheDirs(packageName);
+ return sCurrentUser.buildExternalStorageAppCacheDirs(packageName);
}
/**
@@ -787,7 +775,7 @@ public class Environment {
* {@link #MEDIA_BAD_REMOVAL}, or {@link #MEDIA_UNMOUNTABLE}.
*/
public static String getExternalStorageState() {
- final File externalDir = NoPreloadHolder.sCurrentUser.getExternalDirs()[0];
+ final File externalDir = sCurrentUser.getExternalDirs()[0];
return getExternalStorageState(externalDir);
}
@@ -828,7 +816,7 @@ public class Environment {
*/
public static boolean isExternalStorageRemovable() {
if (isStorageDisabled()) return false;
- final File externalDir = NoPreloadHolder.sCurrentUser.getExternalDirs()[0];
+ final File externalDir = sCurrentUser.getExternalDirs()[0];
return isExternalStorageRemovable(externalDir);
}
@@ -867,7 +855,7 @@ public class Environment {
*/
public static boolean isExternalStorageEmulated() {
if (isStorageDisabled()) return false;
- final File externalDir = NoPreloadHolder.sCurrentUser.getExternalDirs()[0];
+ final File externalDir = sCurrentUser.getExternalDirs()[0];
return isExternalStorageEmulated(externalDir);
}
@@ -902,11 +890,11 @@ public class Environment {
/** {@hide} */
public static void setUserRequired(boolean userRequired) {
- NoPreloadHolder.sUserRequired = userRequired;
+ sUserRequired = userRequired;
}
private static void throwIfUserRequired() {
- if (NoPreloadHolder.sUserRequired) {
+ if (sUserRequired) {
Log.wtf(TAG, "Path requests must specify a user by using UserEnvironment",
new Throwable());
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index c26d974b2cba..84d2c98ba93d 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -971,6 +971,9 @@ public class Process {
* priority.
* If the thread is a thread group leader, that is it's gettid() == getpid(),
* then the other threads in the same thread group are _not_ affected.
+ *
+ * Does not set cpuset for some historical reason, just calls
+ * libcutils::set_sched_policy().
*/
public static final native void setThreadGroup(int tid, int group)
throws IllegalArgumentException, SecurityException;
@@ -992,6 +995,8 @@ public class Process {
* priority threads alone. group == THREAD_GROUP_BG_NONINTERACTIVE moves all
* threads, regardless of priority, to the background scheduling group.
* group == THREAD_GROUP_FOREGROUND is not allowed.
+ *
+ * Always sets cpusets.
*/
public static final native void setProcessGroup(int pid, int group)
throws IllegalArgumentException, SecurityException;
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 10e3718601ea..b3f44536214b 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -297,11 +297,7 @@ public final class UserHandle implements Parcelable {
*/
@SystemApi
public static @UserIdInt int myUserId() {
- int myUid = Process.myUid();
- if (myUid == 0) {
- throw new IllegalStateException("myUserId unsupported in zygote.");
- }
- return getUserId(myUid);
+ return getUserId(Process.myUid());
}
/**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index a44a9eed701b..feb8b2be3c58 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -603,6 +603,17 @@ public class UserManager {
public static final String DISALLOW_SET_USER_ICON = "no_set_user_icon";
/**
+ * Specifies if a user is not allowed to enable the oem unlock setting. The default value is
+ * <code>false</code>.
+ *
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ * @hide
+ */
+ public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
+
+ /**
* Allows apps in the parent profile to handle web links from the managed profile.
*
* This user restriction has an effect only in a managed profile.
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 1158776f5fd1..d587ba80a18c 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -235,7 +235,6 @@ public final class DocumentsContract {
* @see #FLAG_DIR_PREFERS_GRID
* @see #FLAG_DIR_PREFERS_LAST_MODIFIED
* @see #FLAG_VIRTUAL_DOCUMENT
- * @see #FLAG_ARCHIVE
* @see #FLAG_SUPPORTS_COPY
* @see #FLAG_SUPPORTS_MOVE
* @see #FLAG_SUPPORTS_REMOVE
@@ -326,7 +325,7 @@ public final class DocumentsContract {
* Flag indicating that a document can be renamed.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#renameDocument(ContentProviderClient, Uri,
+ * @see DocumentsContract#renameDocument(ContentResolver, Uri,
* String)
* @see DocumentsProvider#renameDocument(String, String)
*/
@@ -337,7 +336,7 @@ public final class DocumentsContract {
* within the same document provider.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#copyDocument(ContentProviderClient, Uri, Uri)
+ * @see DocumentsContract#copyDocument(ContentResolver, Uri, Uri)
* @see DocumentsProvider#copyDocument(String, String)
*/
public static final int FLAG_SUPPORTS_COPY = 1 << 7;
@@ -347,7 +346,7 @@ public final class DocumentsContract {
* within the same document provider.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#moveDocument(ContentProviderClient, Uri, Uri, Uri)
+ * @see DocumentsContract#moveDocument(ContentResolver, Uri, Uri, Uri)
* @see DocumentsProvider#moveDocument(String, String, String)
*/
public static final int FLAG_SUPPORTS_MOVE = 1 << 8;
@@ -368,7 +367,7 @@ public final class DocumentsContract {
* Flag indicating that a document can be removed from a parent.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#removeDocument(ContentProviderClient, Uri, Uri)
+ * @see DocumentsContract#removeDocument(ContentResolver, Uri, Uri)
* @see DocumentsProvider#removeDocument(String, String)
*/
public static final int FLAG_SUPPORTS_REMOVE = 1 << 10;
@@ -870,7 +869,7 @@ public final class DocumentsContract {
* Test if the given URI represents a {@link Document} tree.
*
* @see #buildTreeDocumentUri(String, String)
- * @see #getTreeDocumentId(Uri, String)
+ * @see #getTreeDocumentId(Uri)
*/
public static boolean isTreeUri(Uri uri) {
final List<String> paths = uri.getPathSegments();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bb8011080b44..765a3a8cd9d4 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5295,15 +5295,6 @@ public final class Settings {
"accessibility_display_daltonizer";
/**
- * Float list that specifies the color matrix to apply to
- * the display. Valid values are defined in AccessibilityManager.
- *
- * @hide
- */
- public static final String ACCESSIBILITY_DISPLAY_COLOR_MATRIX =
- "accessibility_display_color_matrix";
-
- /**
* Setting that specifies whether automatic click when the mouse pointer stops moving is
* enabled.
*
@@ -6147,6 +6138,39 @@ public final class Settings {
"camera_double_tap_power_gesture_disabled";
/**
+ * Whether the camera double twist gesture to flip between front and back mode should be
+ * enabled.
+ *
+ * @hide
+ */
+ public static final String CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED =
+ "camera_double_twist_to_flip_enabled";
+
+ /**
+ * Control whether Night display is currently activated.
+ * @hide
+ */
+ public static final String NIGHT_DISPLAY_ACTIVATED = "night_display_activated";
+
+ /**
+ * Control whether Night display will automatically activate/deactivate.
+ * @hide
+ */
+ public static final String NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode";
+
+ /**
+ * Custom time when Night display is scheduled to activate.
+ * Represented as milliseconds from midnight (e.g. 79200000 == 10pm).
+ * @hide
+ */
+ public static final String NIGHT_DISPLAY_CUSTOM_START_TIME = "night_display_custom_start_time";
+
+ /**
+ * Custom time when Night display is scheduled to deactivate.
+ * Represented as milliseconds from midnight (e.g. 21600000 == 6am).
+ * @hide
+ */
+ public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
/**
* Behavior of twilight on the device.
@@ -6277,6 +6301,14 @@ public final class Settings {
/**
+ * Whether SystemUI navigation keys is enabled.
+ * @hide
+ */
+ public static final String SYSTEM_NAVIGATION_KEYS_ENABLED =
+ "system_navigation_keys_enabled";
+
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
@@ -6293,7 +6325,6 @@ public final class Settings {
USB_MASS_STORAGE_ENABLED, // moved to global
ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
ACCESSIBILITY_DISPLAY_DALTONIZER,
- ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
@@ -8659,6 +8690,22 @@ public final class Settings {
public static final String DEVICE_DEMO_MODE = "device_demo_mode";
/**
+ * Retail mode specific settings. This is encoded as a key=value list, separated by commas.
+ * Ex: "user_inactivity_timeout_ms=30000,warning_dialog_timeout_ms=10000". The following
+ * keys are supported:
+ *
+ * <pre>
+ * user_inactivity_timeout_ms (long)
+ * warning_dialog_timeout_ms (long)
+ * </pre>
+ * <p>
+ * Type: string
+ *
+ * @hide
+ */
+ public static final String RETAIL_DEMO_MODE_CONSTANTS = "retail_demo_mode_constants";
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
*
@@ -9057,15 +9104,6 @@ public final class Settings {
public static final String ENABLE_CELLULAR_ON_BOOT = "enable_cellular_on_boot";
/**
- * Whether toggling OEM unlock is disallowed. If disallowed, it is not possible to enable or
- * disable OEM unlock.
- * <p>
- * Type: int (0: allow OEM unlock setting. 1: disallow OEM unlock)
- * @hide
- */
- public static final String OEM_UNLOCK_DISALLOWED = "oem_unlock_disallowed";
-
- /**
* The maximum allowed notification enqueue rate in Hertz.
*
* Should be a float, and includes both posts and updates.
@@ -9074,13 +9112,6 @@ public final class Settings {
public static final String MAX_NOTIFICATION_ENQUEUE_RATE = "max_notification_enqueue_rate";
/**
- * Whether SystemUI navigation keys is enabled.
- * @hide
- */
- public static final String SYSTEM_NAVIGATION_KEYS_ENABLED =
- "system_navigation_keys_enabled";
-
- /**
* Whether cell is enabled/disabled
* @hide
*/
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 6911b0161704..69960b04518a 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -20,6 +20,8 @@ import android.app.ActivityManager;
import android.app.NotificationManager.Policy;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Parcel;
@@ -118,6 +120,7 @@ public class ZenModeConfig implements Parcelable {
private static final String RULE_ATT_ZEN = "zen";
private static final String RULE_ATT_CONDITION_ID = "conditionId";
private static final String RULE_ATT_CREATION_TIME = "creationTime";
+ private static final String RULE_ATT_ENABLER = "enabler";
public boolean allowCalls = DEFAULT_ALLOW_CALLS;
public boolean allowRepeatCallers = DEFAULT_ALLOW_REPEAT_CALLERS;
@@ -502,6 +505,7 @@ public class ZenModeConfig implements Parcelable {
rt.conditionId = safeUri(parser, RULE_ATT_CONDITION_ID);
rt.component = safeComponentName(parser, RULE_ATT_COMPONENT);
rt.creationTime = safeLong(parser, RULE_ATT_CREATION_TIME, 0);
+ rt.enabler = parser.getAttributeValue(null, RULE_ATT_ENABLER);
rt.condition = readConditionXml(parser);
return rt;
}
@@ -520,6 +524,9 @@ public class ZenModeConfig implements Parcelable {
out.attribute(null, RULE_ATT_CONDITION_ID, rule.conditionId.toString());
}
out.attribute(null, RULE_ATT_CREATION_TIME, Long.toString(rule.creationTime));
+ if (rule.enabler != null) {
+ out.attribute(null, RULE_ATT_ENABLER, rule.enabler);
+ }
if (rule.condition != null) {
writeConditionXml(rule.condition, out);
}
@@ -989,6 +996,25 @@ public class ZenModeConfig implements Parcelable {
return UUID.randomUUID().toString().replace("-", "");
}
+ private static String getOwnerCaption(Context context, String owner) {
+ final PackageManager pm = context.getPackageManager();
+ try {
+ final ApplicationInfo info = pm.getApplicationInfo(owner, 0);
+ if (info != null) {
+ final CharSequence seq = info.loadLabel(pm);
+ if (seq != null) {
+ final String str = seq.toString().trim();
+ if (str.length() > 0) {
+ return str;
+ }
+ }
+ }
+ } catch (Throwable e) {
+ Slog.w(TAG, "Error loading owner caption", e);
+ }
+ return "";
+ }
+
public static String getConditionSummary(Context context, ZenModeConfig config,
int userHandle, boolean shortVersion) {
return getConditionLine(context, config, userHandle, false /*useLine1*/, shortVersion);
@@ -997,23 +1023,28 @@ public class ZenModeConfig implements Parcelable {
private static String getConditionLine(Context context, ZenModeConfig config,
int userHandle, boolean useLine1, boolean shortVersion) {
if (config == null) return "";
+ String summary = "";
if (config.manualRule != null) {
final Uri id = config.manualRule.conditionId;
- if (id == null) {
- return context.getString(com.android.internal.R.string.zen_mode_forever);
- }
- final long time = tryParseCountdownConditionId(id);
- Condition c = config.manualRule.condition;
- if (time > 0) {
- final long now = System.currentTimeMillis();
- final long span = time - now;
- c = toTimeCondition(context, time, Math.round(span / (float) MINUTES_MS),
- userHandle, shortVersion);
+ if (config.manualRule.enabler != null) {
+ summary = getOwnerCaption(context, config.manualRule.enabler);
+ } else {
+ if (id == null) {
+ summary = context.getString(com.android.internal.R.string.zen_mode_forever);
+ } else {
+ final long time = tryParseCountdownConditionId(id);
+ Condition c = config.manualRule.condition;
+ if (time > 0) {
+ final long now = System.currentTimeMillis();
+ final long span = time - now;
+ c = toTimeCondition(context, time, Math.round(span / (float) MINUTES_MS),
+ userHandle, shortVersion);
+ }
+ final String rt = c == null ? "" : useLine1 ? c.line1 : c.summary;
+ summary = TextUtils.isEmpty(rt) ? "" : rt;
+ }
}
- final String rt = c == null ? "" : useLine1 ? c.line1 : c.summary;
- return TextUtils.isEmpty(rt) ? "" : rt;
}
- String summary = "";
for (ZenRule automaticRule : config.automaticRules.values()) {
if (automaticRule.isAutomaticActive()) {
if (summary.isEmpty()) {
@@ -1023,6 +1054,7 @@ public class ZenModeConfig implements Parcelable {
.getString(R.string.zen_mode_rule_name_combination, summary,
automaticRule.name);
}
+
}
}
return summary;
@@ -1038,6 +1070,7 @@ public class ZenModeConfig implements Parcelable {
public ComponentName component; // optional
public String id; // required for automatic (unique)
public long creationTime; // required for automatic
+ public String enabler; // package name, only used for manual rules.
public ZenRule() { }
@@ -1055,6 +1088,9 @@ public class ZenModeConfig implements Parcelable {
id = source.readString();
}
creationTime = source.readLong();
+ if (source.readInt() == 1) {
+ enabler = source.readString();
+ }
}
@Override
@@ -1083,6 +1119,12 @@ public class ZenModeConfig implements Parcelable {
dest.writeInt(0);
}
dest.writeLong(creationTime);
+ if (enabler != null) {
+ dest.writeInt(1);
+ dest.writeString(enabler);
+ } else {
+ dest.writeInt(0);
+ }
}
@Override
@@ -1097,6 +1139,7 @@ public class ZenModeConfig implements Parcelable {
.append(",component=").append(component)
.append(",id=").append(id)
.append(",creationTime=").append(creationTime)
+ .append(",enabler=").append(enabler)
.append(']').toString();
}
@@ -1143,6 +1186,9 @@ public class ZenModeConfig implements Parcelable {
if (creationTime != to.creationTime) {
d.addLine(item, "creationTime", creationTime, to.creationTime);
}
+ if (enabler != to.enabler) {
+ d.addLine(item, "enabler", enabler, to.enabler);
+ }
}
@Override
@@ -1158,13 +1204,14 @@ public class ZenModeConfig implements Parcelable {
&& Objects.equals(other.condition, condition)
&& Objects.equals(other.component, component)
&& Objects.equals(other.id, id)
- && other.creationTime == creationTime;
+ && other.creationTime == creationTime
+ && Objects.equals(other.enabler, enabler);
}
@Override
public int hashCode() {
return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
- component, id, creationTime);
+ component, id, creationTime, enabler);
}
public boolean isAutomaticActive() {
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index b62cc66b5269..b6d720d453e9 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -32,111 +32,112 @@ public class Emoji {
0x23EC, 0x23ED, 0x23EE, 0x23EF, 0x23F0, 0x23F1, 0x23F2, 0x23F3, 0x23F8, 0x23F9, 0x23FA,
0x24C2, 0x25AA, 0x25AB, 0x25B6, 0x25C0, 0x25FB, 0x25FC, 0x25FD, 0x25FE, 0x2600, 0x2601,
0x2602, 0x2603, 0x2604, 0x260E, 0x2611, 0x2614, 0x2615, 0x2618, 0x261D, 0x2620, 0x2622,
- 0x2623, 0x2626, 0x262A, 0x262E, 0x262F, 0x2638, 0x2639, 0x263A, 0x2648, 0x2649, 0x264A,
- 0x264B, 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653, 0x2660, 0x2663,
- 0x2665, 0x2666, 0x2668, 0x267B, 0x267F, 0x2692, 0x2693, 0x2694, 0x2696, 0x2697, 0x2699,
- 0x269B, 0x269C, 0x26A0, 0x26A1, 0x26AA, 0x26AB, 0x26B0, 0x26B1, 0x26BD, 0x26BE, 0x26C4,
- 0x26C5, 0x26C8, 0x26CE, 0x26CF, 0x26D1, 0x26D3, 0x26D4, 0x26E9, 0x26EA, 0x26F0, 0x26F1,
- 0x26F2, 0x26F3, 0x26F4, 0x26F5, 0x26F7, 0x26F8, 0x26F9, 0x26FA, 0x26FD, 0x2702, 0x2705,
- 0x2708, 0x2709, 0x270A, 0x270B, 0x270C, 0x270D, 0x270F, 0x2712, 0x2714, 0x2716, 0x271D,
- 0x2721, 0x2728, 0x2733, 0x2734, 0x2744, 0x2747, 0x274C, 0x274E, 0x2753, 0x2754, 0x2755,
- 0x2757, 0x2763, 0x2764, 0x2795, 0x2796, 0x2797, 0x27A1, 0x27B0, 0x27BF, 0x2934, 0x2935,
- 0x2B05, 0x2B06, 0x2B07, 0x2B1B, 0x2B1C, 0x2B50, 0x2B55, 0x3030, 0x303D, 0x3297, 0x3299,
- 0x1F004, 0x1F0CF, 0x1F170, 0x1F171, 0x1F17E, 0x1F17F, 0x1F18E, 0x1F191, 0x1F192, 0x1F193,
- 0x1F194, 0x1F195, 0x1F196, 0x1F197, 0x1F198, 0x1F199, 0x1F19A, 0x1F1E6, 0x1F1E7, 0x1F1E8,
- 0x1F1E9, 0x1F1EA, 0x1F1EB, 0x1F1EC, 0x1F1ED, 0x1F1EE, 0x1F1EF, 0x1F1F0, 0x1F1F1, 0x1F1F2,
- 0x1F1F3, 0x1F1F4, 0x1F1F5, 0x1F1F6, 0x1F1F7, 0x1F1F8, 0x1F1F9, 0x1F1FA, 0x1F1FB, 0x1F1FC,
- 0x1F1FD, 0x1F1FE, 0x1F1FF, 0x1F201, 0x1F202, 0x1F21A, 0x1F22F, 0x1F232, 0x1F233, 0x1F234,
- 0x1F235, 0x1F236, 0x1F237, 0x1F238, 0x1F239, 0x1F23A, 0x1F250, 0x1F251, 0x1F300, 0x1F301,
- 0x1F302, 0x1F303, 0x1F304, 0x1F305, 0x1F306, 0x1F307, 0x1F308, 0x1F309, 0x1F30A, 0x1F30B,
- 0x1F30C, 0x1F30D, 0x1F30E, 0x1F30F, 0x1F310, 0x1F311, 0x1F312, 0x1F313, 0x1F314, 0x1F315,
- 0x1F316, 0x1F317, 0x1F318, 0x1F319, 0x1F31A, 0x1F31B, 0x1F31C, 0x1F31D, 0x1F31E, 0x1F31F,
- 0x1F320, 0x1F321, 0x1F324, 0x1F325, 0x1F326, 0x1F327, 0x1F328, 0x1F329, 0x1F32A, 0x1F32B,
- 0x1F32C, 0x1F32D, 0x1F32E, 0x1F32F, 0x1F330, 0x1F331, 0x1F332, 0x1F333, 0x1F334, 0x1F335,
- 0x1F336, 0x1F337, 0x1F338, 0x1F339, 0x1F33A, 0x1F33B, 0x1F33C, 0x1F33D, 0x1F33E, 0x1F33F,
- 0x1F340, 0x1F341, 0x1F342, 0x1F343, 0x1F344, 0x1F345, 0x1F346, 0x1F347, 0x1F348, 0x1F349,
- 0x1F34A, 0x1F34B, 0x1F34C, 0x1F34D, 0x1F34E, 0x1F34F, 0x1F350, 0x1F351, 0x1F352, 0x1F353,
- 0x1F354, 0x1F355, 0x1F356, 0x1F357, 0x1F358, 0x1F359, 0x1F35A, 0x1F35B, 0x1F35C, 0x1F35D,
- 0x1F35E, 0x1F35F, 0x1F360, 0x1F361, 0x1F362, 0x1F363, 0x1F364, 0x1F365, 0x1F366, 0x1F367,
- 0x1F368, 0x1F369, 0x1F36A, 0x1F36B, 0x1F36C, 0x1F36D, 0x1F36E, 0x1F36F, 0x1F370, 0x1F371,
- 0x1F372, 0x1F373, 0x1F374, 0x1F375, 0x1F376, 0x1F377, 0x1F378, 0x1F379, 0x1F37A, 0x1F37B,
- 0x1F37C, 0x1F37D, 0x1F37E, 0x1F37F, 0x1F380, 0x1F381, 0x1F382, 0x1F383, 0x1F384, 0x1F385,
- 0x1F386, 0x1F387, 0x1F388, 0x1F389, 0x1F38A, 0x1F38B, 0x1F38C, 0x1F38D, 0x1F38E, 0x1F38F,
- 0x1F390, 0x1F391, 0x1F392, 0x1F393, 0x1F396, 0x1F397, 0x1F399, 0x1F39A, 0x1F39B, 0x1F39E,
- 0x1F39F, 0x1F3A0, 0x1F3A1, 0x1F3A2, 0x1F3A3, 0x1F3A4, 0x1F3A5, 0x1F3A6, 0x1F3A7, 0x1F3A8,
- 0x1F3A9, 0x1F3AA, 0x1F3AB, 0x1F3AC, 0x1F3AD, 0x1F3AE, 0x1F3AF, 0x1F3B0, 0x1F3B1, 0x1F3B2,
- 0x1F3B3, 0x1F3B4, 0x1F3B5, 0x1F3B6, 0x1F3B7, 0x1F3B8, 0x1F3B9, 0x1F3BA, 0x1F3BB, 0x1F3BC,
- 0x1F3BD, 0x1F3BE, 0x1F3BF, 0x1F3C0, 0x1F3C1, 0x1F3C2, 0x1F3C3, 0x1F3C4, 0x1F3C5, 0x1F3C6,
- 0x1F3C7, 0x1F3C8, 0x1F3C9, 0x1F3CA, 0x1F3CB, 0x1F3CC, 0x1F3CD, 0x1F3CE, 0x1F3CF, 0x1F3D0,
- 0x1F3D1, 0x1F3D2, 0x1F3D3, 0x1F3D4, 0x1F3D5, 0x1F3D6, 0x1F3D7, 0x1F3D8, 0x1F3D9, 0x1F3DA,
- 0x1F3DB, 0x1F3DC, 0x1F3DD, 0x1F3DE, 0x1F3DF, 0x1F3E0, 0x1F3E1, 0x1F3E2, 0x1F3E3, 0x1F3E4,
- 0x1F3E5, 0x1F3E6, 0x1F3E7, 0x1F3E8, 0x1F3E9, 0x1F3EA, 0x1F3EB, 0x1F3EC, 0x1F3ED, 0x1F3EE,
- 0x1F3EF, 0x1F3F0, 0x1F3F3, 0x1F3F4, 0x1F3F5, 0x1F3F7, 0x1F3F8, 0x1F3F9, 0x1F3FA, 0x1F3FB,
- 0x1F3FC, 0x1F3FD, 0x1F3FE, 0x1F3FF, 0x1F400, 0x1F401, 0x1F402, 0x1F403, 0x1F404, 0x1F405,
- 0x1F406, 0x1F407, 0x1F408, 0x1F409, 0x1F40A, 0x1F40B, 0x1F40C, 0x1F40D, 0x1F40E, 0x1F40F,
- 0x1F410, 0x1F411, 0x1F412, 0x1F413, 0x1F414, 0x1F415, 0x1F416, 0x1F417, 0x1F418, 0x1F419,
- 0x1F41A, 0x1F41B, 0x1F41C, 0x1F41D, 0x1F41E, 0x1F41F, 0x1F420, 0x1F421, 0x1F422, 0x1F423,
- 0x1F424, 0x1F425, 0x1F426, 0x1F427, 0x1F428, 0x1F429, 0x1F42A, 0x1F42B, 0x1F42C, 0x1F42D,
- 0x1F42E, 0x1F42F, 0x1F430, 0x1F431, 0x1F432, 0x1F433, 0x1F434, 0x1F435, 0x1F436, 0x1F437,
- 0x1F438, 0x1F439, 0x1F43A, 0x1F43B, 0x1F43C, 0x1F43D, 0x1F43E, 0x1F43F, 0x1F440, 0x1F441,
- 0x1F442, 0x1F443, 0x1F444, 0x1F445, 0x1F446, 0x1F447, 0x1F448, 0x1F449, 0x1F44A, 0x1F44B,
- 0x1F44C, 0x1F44D, 0x1F44E, 0x1F44F, 0x1F450, 0x1F451, 0x1F452, 0x1F453, 0x1F454, 0x1F455,
- 0x1F456, 0x1F457, 0x1F458, 0x1F459, 0x1F45A, 0x1F45B, 0x1F45C, 0x1F45D, 0x1F45E, 0x1F45F,
- 0x1F460, 0x1F461, 0x1F462, 0x1F463, 0x1F464, 0x1F465, 0x1F466, 0x1F467, 0x1F468, 0x1F469,
- 0x1F46A, 0x1F46B, 0x1F46C, 0x1F46D, 0x1F46E, 0x1F46F, 0x1F470, 0x1F471, 0x1F472, 0x1F473,
- 0x1F474, 0x1F475, 0x1F476, 0x1F477, 0x1F478, 0x1F479, 0x1F47A, 0x1F47B, 0x1F47C, 0x1F47D,
- 0x1F47E, 0x1F47F, 0x1F480, 0x1F481, 0x1F482, 0x1F483, 0x1F484, 0x1F485, 0x1F486, 0x1F487,
- 0x1F488, 0x1F489, 0x1F48A, 0x1F48B, 0x1F48C, 0x1F48D, 0x1F48E, 0x1F48F, 0x1F490, 0x1F491,
- 0x1F492, 0x1F493, 0x1F494, 0x1F495, 0x1F496, 0x1F497, 0x1F498, 0x1F499, 0x1F49A, 0x1F49B,
- 0x1F49C, 0x1F49D, 0x1F49E, 0x1F49F, 0x1F4A0, 0x1F4A1, 0x1F4A2, 0x1F4A3, 0x1F4A4, 0x1F4A5,
- 0x1F4A6, 0x1F4A7, 0x1F4A8, 0x1F4A9, 0x1F4AA, 0x1F4AB, 0x1F4AC, 0x1F4AD, 0x1F4AE, 0x1F4AF,
- 0x1F4B0, 0x1F4B1, 0x1F4B2, 0x1F4B3, 0x1F4B4, 0x1F4B5, 0x1F4B6, 0x1F4B7, 0x1F4B8, 0x1F4B9,
- 0x1F4BA, 0x1F4BB, 0x1F4BC, 0x1F4BD, 0x1F4BE, 0x1F4BF, 0x1F4C0, 0x1F4C1, 0x1F4C2, 0x1F4C3,
- 0x1F4C4, 0x1F4C5, 0x1F4C6, 0x1F4C7, 0x1F4C8, 0x1F4C9, 0x1F4CA, 0x1F4CB, 0x1F4CC, 0x1F4CD,
- 0x1F4CE, 0x1F4CF, 0x1F4D0, 0x1F4D1, 0x1F4D2, 0x1F4D3, 0x1F4D4, 0x1F4D5, 0x1F4D6, 0x1F4D7,
- 0x1F4D8, 0x1F4D9, 0x1F4DA, 0x1F4DB, 0x1F4DC, 0x1F4DD, 0x1F4DE, 0x1F4DF, 0x1F4E0, 0x1F4E1,
- 0x1F4E2, 0x1F4E3, 0x1F4E4, 0x1F4E5, 0x1F4E6, 0x1F4E7, 0x1F4E8, 0x1F4E9, 0x1F4EA, 0x1F4EB,
- 0x1F4EC, 0x1F4ED, 0x1F4EE, 0x1F4EF, 0x1F4F0, 0x1F4F1, 0x1F4F2, 0x1F4F3, 0x1F4F4, 0x1F4F5,
- 0x1F4F6, 0x1F4F7, 0x1F4F8, 0x1F4F9, 0x1F4FA, 0x1F4FB, 0x1F4FC, 0x1F4FD, 0x1F4FF, 0x1F500,
- 0x1F501, 0x1F502, 0x1F503, 0x1F504, 0x1F505, 0x1F506, 0x1F507, 0x1F508, 0x1F509, 0x1F50A,
- 0x1F50B, 0x1F50C, 0x1F50D, 0x1F50E, 0x1F50F, 0x1F510, 0x1F511, 0x1F512, 0x1F513, 0x1F514,
- 0x1F515, 0x1F516, 0x1F517, 0x1F518, 0x1F519, 0x1F51A, 0x1F51B, 0x1F51C, 0x1F51D, 0x1F51E,
- 0x1F51F, 0x1F520, 0x1F521, 0x1F522, 0x1F523, 0x1F524, 0x1F525, 0x1F526, 0x1F527, 0x1F528,
- 0x1F529, 0x1F52A, 0x1F52B, 0x1F52C, 0x1F52D, 0x1F52E, 0x1F52F, 0x1F530, 0x1F531, 0x1F532,
- 0x1F533, 0x1F534, 0x1F535, 0x1F536, 0x1F537, 0x1F538, 0x1F539, 0x1F53A, 0x1F53B, 0x1F53C,
- 0x1F53D, 0x1F549, 0x1F54A, 0x1F54B, 0x1F54C, 0x1F54D, 0x1F54E, 0x1F550, 0x1F551, 0x1F552,
- 0x1F553, 0x1F554, 0x1F555, 0x1F556, 0x1F557, 0x1F558, 0x1F559, 0x1F55A, 0x1F55B, 0x1F55C,
- 0x1F55D, 0x1F55E, 0x1F55F, 0x1F560, 0x1F561, 0x1F562, 0x1F563, 0x1F564, 0x1F565, 0x1F566,
- 0x1F567, 0x1F56F, 0x1F570, 0x1F573, 0x1F574, 0x1F575, 0x1F576, 0x1F577, 0x1F578, 0x1F579,
- 0x1F57A, 0x1F587, 0x1F58A, 0x1F58B, 0x1F58C, 0x1F58D, 0x1F590, 0x1F595, 0x1F596, 0x1F5A4,
- 0x1F5A5, 0x1F5A8, 0x1F5B1, 0x1F5B2, 0x1F5BC, 0x1F5C2, 0x1F5C3, 0x1F5C4, 0x1F5D1, 0x1F5D2,
- 0x1F5D3, 0x1F5DC, 0x1F5DD, 0x1F5DE, 0x1F5E1, 0x1F5E3, 0x1F5E8, 0x1F5EF, 0x1F5F3, 0x1F5FA,
- 0x1F5FB, 0x1F5FC, 0x1F5FD, 0x1F5FE, 0x1F5FF, 0x1F600, 0x1F601, 0x1F602, 0x1F603, 0x1F604,
- 0x1F605, 0x1F606, 0x1F607, 0x1F608, 0x1F609, 0x1F60A, 0x1F60B, 0x1F60C, 0x1F60D, 0x1F60E,
- 0x1F60F, 0x1F610, 0x1F611, 0x1F612, 0x1F613, 0x1F614, 0x1F615, 0x1F616, 0x1F617, 0x1F618,
- 0x1F619, 0x1F61A, 0x1F61B, 0x1F61C, 0x1F61D, 0x1F61E, 0x1F61F, 0x1F620, 0x1F621, 0x1F622,
- 0x1F623, 0x1F624, 0x1F625, 0x1F626, 0x1F627, 0x1F628, 0x1F629, 0x1F62A, 0x1F62B, 0x1F62C,
- 0x1F62D, 0x1F62E, 0x1F62F, 0x1F630, 0x1F631, 0x1F632, 0x1F633, 0x1F634, 0x1F635, 0x1F636,
- 0x1F637, 0x1F638, 0x1F639, 0x1F63A, 0x1F63B, 0x1F63C, 0x1F63D, 0x1F63E, 0x1F63F, 0x1F640,
- 0x1F641, 0x1F642, 0x1F643, 0x1F644, 0x1F645, 0x1F646, 0x1F647, 0x1F648, 0x1F649, 0x1F64A,
- 0x1F64B, 0x1F64C, 0x1F64D, 0x1F64E, 0x1F64F, 0x1F680, 0x1F681, 0x1F682, 0x1F683, 0x1F684,
- 0x1F685, 0x1F686, 0x1F687, 0x1F688, 0x1F689, 0x1F68A, 0x1F68B, 0x1F68C, 0x1F68D, 0x1F68E,
- 0x1F68F, 0x1F690, 0x1F691, 0x1F692, 0x1F693, 0x1F694, 0x1F695, 0x1F696, 0x1F697, 0x1F698,
- 0x1F699, 0x1F69A, 0x1F69B, 0x1F69C, 0x1F69D, 0x1F69E, 0x1F69F, 0x1F6A0, 0x1F6A1, 0x1F6A2,
- 0x1F6A3, 0x1F6A4, 0x1F6A5, 0x1F6A6, 0x1F6A7, 0x1F6A8, 0x1F6A9, 0x1F6AA, 0x1F6AB, 0x1F6AC,
- 0x1F6AD, 0x1F6AE, 0x1F6AF, 0x1F6B0, 0x1F6B1, 0x1F6B2, 0x1F6B3, 0x1F6B4, 0x1F6B5, 0x1F6B6,
- 0x1F6B7, 0x1F6B8, 0x1F6B9, 0x1F6BA, 0x1F6BB, 0x1F6BC, 0x1F6BD, 0x1F6BE, 0x1F6BF, 0x1F6C0,
- 0x1F6C1, 0x1F6C2, 0x1F6C3, 0x1F6C4, 0x1F6C5, 0x1F6CB, 0x1F6CC, 0x1F6CD, 0x1F6CE, 0x1F6CF,
- 0x1F6D0, 0x1F6D1, 0x1F6D2, 0x1F6E0, 0x1F6E1, 0x1F6E2, 0x1F6E3, 0x1F6E4, 0x1F6E5, 0x1F6E9,
- 0x1F6EB, 0x1F6EC, 0x1F6F0, 0x1F6F3, 0x1F6F4, 0x1F6F5, 0x1F6F6, 0x1F910, 0x1F911, 0x1F912,
- 0x1F913, 0x1F914, 0x1F915, 0x1F916, 0x1F917, 0x1F918, 0x1F919, 0x1F91A, 0x1F91B, 0x1F91C,
- 0x1F91D, 0x1F91E, 0x1F920, 0x1F921, 0x1F922, 0x1F923, 0x1F924, 0x1F925, 0x1F926, 0x1F927,
- 0x1F930, 0x1F933, 0x1F934, 0x1F935, 0x1F936, 0x1F937, 0x1F938, 0x1F939, 0x1F93A, 0x1F93B,
- 0x1F93C, 0x1F93D, 0x1F93E, 0x1F940, 0x1F941, 0x1F942, 0x1F943, 0x1F944, 0x1F945, 0x1F946,
- 0x1F947, 0x1F948, 0x1F949, 0x1F94A, 0x1F94B, 0x1F950, 0x1F951, 0x1F952, 0x1F953, 0x1F954,
- 0x1F955, 0x1F956, 0x1F957, 0x1F958, 0x1F959, 0x1F95A, 0x1F95B, 0x1F95C, 0x1F95D, 0x1F95E,
- 0x1F980, 0x1F981, 0x1F982, 0x1F983, 0x1F984, 0x1F985, 0x1F986, 0x1F987, 0x1F988, 0x1F989,
- 0x1F98A, 0x1F98B, 0x1F98C, 0x1F98D, 0x1F98E, 0x1F98F, 0x1F990, 0x1F991, 0x1F9C0
+ 0x2623, 0x2626, 0x262A, 0x262E, 0x262F, 0x2638, 0x2639, 0x263A, 0x2640, 0x2642, 0x2648,
+ 0x2649, 0x264A, 0x264B, 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653,
+ 0x2660, 0x2663, 0x2665, 0x2666, 0x2668, 0x267B, 0x267F, 0x2692, 0x2693, 0x2694, 0x2695,
+ 0x2696, 0x2697, 0x2699, 0x269B, 0x269C, 0x26A0, 0x26A1, 0x26AA, 0x26AB, 0x26B0, 0x26B1,
+ 0x26BD, 0x26BE, 0x26C4, 0x26C5, 0x26C8, 0x26CE, 0x26CF, 0x26D1, 0x26D3, 0x26D4, 0x26E9,
+ 0x26EA, 0x26F0, 0x26F1, 0x26F2, 0x26F3, 0x26F4, 0x26F5, 0x26F7, 0x26F8, 0x26F9, 0x26FA,
+ 0x26FD, 0x2702, 0x2705, 0x2708, 0x2709, 0x270A, 0x270B, 0x270C, 0x270D, 0x270F, 0x2712,
+ 0x2714, 0x2716, 0x271D, 0x2721, 0x2728, 0x2733, 0x2734, 0x2744, 0x2747, 0x274C, 0x274E,
+ 0x2753, 0x2754, 0x2755, 0x2757, 0x2763, 0x2764, 0x2795, 0x2796, 0x2797, 0x27A1, 0x27B0,
+ 0x27BF, 0x2934, 0x2935, 0x2B05, 0x2B06, 0x2B07, 0x2B1B, 0x2B1C, 0x2B50, 0x2B55, 0x3030,
+ 0x303D, 0x3297, 0x3299, 0x1F004, 0x1F0CF, 0x1F170, 0x1F171, 0x1F17E, 0x1F17F, 0x1F18E,
+ 0x1F191, 0x1F192, 0x1F193, 0x1F194, 0x1F195, 0x1F196, 0x1F197, 0x1F198, 0x1F199, 0x1F19A,
+ 0x1F1E6, 0x1F1E7, 0x1F1E8, 0x1F1E9, 0x1F1EA, 0x1F1EB, 0x1F1EC, 0x1F1ED, 0x1F1EE, 0x1F1EF,
+ 0x1F1F0, 0x1F1F1, 0x1F1F2, 0x1F1F3, 0x1F1F4, 0x1F1F5, 0x1F1F6, 0x1F1F7, 0x1F1F8, 0x1F1F9,
+ 0x1F1FA, 0x1F1FB, 0x1F1FC, 0x1F1FD, 0x1F1FE, 0x1F1FF, 0x1F201, 0x1F202, 0x1F21A, 0x1F22F,
+ 0x1F232, 0x1F233, 0x1F234, 0x1F235, 0x1F236, 0x1F237, 0x1F238, 0x1F239, 0x1F23A, 0x1F250,
+ 0x1F251, 0x1F300, 0x1F301, 0x1F302, 0x1F303, 0x1F304, 0x1F305, 0x1F306, 0x1F307, 0x1F308,
+ 0x1F309, 0x1F30A, 0x1F30B, 0x1F30C, 0x1F30D, 0x1F30E, 0x1F30F, 0x1F310, 0x1F311, 0x1F312,
+ 0x1F313, 0x1F314, 0x1F315, 0x1F316, 0x1F317, 0x1F318, 0x1F319, 0x1F31A, 0x1F31B, 0x1F31C,
+ 0x1F31D, 0x1F31E, 0x1F31F, 0x1F320, 0x1F321, 0x1F324, 0x1F325, 0x1F326, 0x1F327, 0x1F328,
+ 0x1F329, 0x1F32A, 0x1F32B, 0x1F32C, 0x1F32D, 0x1F32E, 0x1F32F, 0x1F330, 0x1F331, 0x1F332,
+ 0x1F333, 0x1F334, 0x1F335, 0x1F336, 0x1F337, 0x1F338, 0x1F339, 0x1F33A, 0x1F33B, 0x1F33C,
+ 0x1F33D, 0x1F33E, 0x1F33F, 0x1F340, 0x1F341, 0x1F342, 0x1F343, 0x1F344, 0x1F345, 0x1F346,
+ 0x1F347, 0x1F348, 0x1F349, 0x1F34A, 0x1F34B, 0x1F34C, 0x1F34D, 0x1F34E, 0x1F34F, 0x1F350,
+ 0x1F351, 0x1F352, 0x1F353, 0x1F354, 0x1F355, 0x1F356, 0x1F357, 0x1F358, 0x1F359, 0x1F35A,
+ 0x1F35B, 0x1F35C, 0x1F35D, 0x1F35E, 0x1F35F, 0x1F360, 0x1F361, 0x1F362, 0x1F363, 0x1F364,
+ 0x1F365, 0x1F366, 0x1F367, 0x1F368, 0x1F369, 0x1F36A, 0x1F36B, 0x1F36C, 0x1F36D, 0x1F36E,
+ 0x1F36F, 0x1F370, 0x1F371, 0x1F372, 0x1F373, 0x1F374, 0x1F375, 0x1F376, 0x1F377, 0x1F378,
+ 0x1F379, 0x1F37A, 0x1F37B, 0x1F37C, 0x1F37D, 0x1F37E, 0x1F37F, 0x1F380, 0x1F381, 0x1F382,
+ 0x1F383, 0x1F384, 0x1F385, 0x1F386, 0x1F387, 0x1F388, 0x1F389, 0x1F38A, 0x1F38B, 0x1F38C,
+ 0x1F38D, 0x1F38E, 0x1F38F, 0x1F390, 0x1F391, 0x1F392, 0x1F393, 0x1F396, 0x1F397, 0x1F399,
+ 0x1F39A, 0x1F39B, 0x1F39E, 0x1F39F, 0x1F3A0, 0x1F3A1, 0x1F3A2, 0x1F3A3, 0x1F3A4, 0x1F3A5,
+ 0x1F3A6, 0x1F3A7, 0x1F3A8, 0x1F3A9, 0x1F3AA, 0x1F3AB, 0x1F3AC, 0x1F3AD, 0x1F3AE, 0x1F3AF,
+ 0x1F3B0, 0x1F3B1, 0x1F3B2, 0x1F3B3, 0x1F3B4, 0x1F3B5, 0x1F3B6, 0x1F3B7, 0x1F3B8, 0x1F3B9,
+ 0x1F3BA, 0x1F3BB, 0x1F3BC, 0x1F3BD, 0x1F3BE, 0x1F3BF, 0x1F3C0, 0x1F3C1, 0x1F3C2, 0x1F3C3,
+ 0x1F3C4, 0x1F3C5, 0x1F3C6, 0x1F3C7, 0x1F3C8, 0x1F3C9, 0x1F3CA, 0x1F3CB, 0x1F3CC, 0x1F3CD,
+ 0x1F3CE, 0x1F3CF, 0x1F3D0, 0x1F3D1, 0x1F3D2, 0x1F3D3, 0x1F3D4, 0x1F3D5, 0x1F3D6, 0x1F3D7,
+ 0x1F3D8, 0x1F3D9, 0x1F3DA, 0x1F3DB, 0x1F3DC, 0x1F3DD, 0x1F3DE, 0x1F3DF, 0x1F3E0, 0x1F3E1,
+ 0x1F3E2, 0x1F3E3, 0x1F3E4, 0x1F3E5, 0x1F3E6, 0x1F3E7, 0x1F3E8, 0x1F3E9, 0x1F3EA, 0x1F3EB,
+ 0x1F3EC, 0x1F3ED, 0x1F3EE, 0x1F3EF, 0x1F3F0, 0x1F3F3, 0x1F3F4, 0x1F3F5, 0x1F3F7, 0x1F3F8,
+ 0x1F3F9, 0x1F3FA, 0x1F3FB, 0x1F3FC, 0x1F3FD, 0x1F3FE, 0x1F3FF, 0x1F400, 0x1F401, 0x1F402,
+ 0x1F403, 0x1F404, 0x1F405, 0x1F406, 0x1F407, 0x1F408, 0x1F409, 0x1F40A, 0x1F40B, 0x1F40C,
+ 0x1F40D, 0x1F40E, 0x1F40F, 0x1F410, 0x1F411, 0x1F412, 0x1F413, 0x1F414, 0x1F415, 0x1F416,
+ 0x1F417, 0x1F418, 0x1F419, 0x1F41A, 0x1F41B, 0x1F41C, 0x1F41D, 0x1F41E, 0x1F41F, 0x1F420,
+ 0x1F421, 0x1F422, 0x1F423, 0x1F424, 0x1F425, 0x1F426, 0x1F427, 0x1F428, 0x1F429, 0x1F42A,
+ 0x1F42B, 0x1F42C, 0x1F42D, 0x1F42E, 0x1F42F, 0x1F430, 0x1F431, 0x1F432, 0x1F433, 0x1F434,
+ 0x1F435, 0x1F436, 0x1F437, 0x1F438, 0x1F439, 0x1F43A, 0x1F43B, 0x1F43C, 0x1F43D, 0x1F43E,
+ 0x1F43F, 0x1F440, 0x1F441, 0x1F442, 0x1F443, 0x1F444, 0x1F445, 0x1F446, 0x1F447, 0x1F448,
+ 0x1F449, 0x1F44A, 0x1F44B, 0x1F44C, 0x1F44D, 0x1F44E, 0x1F44F, 0x1F450, 0x1F451, 0x1F452,
+ 0x1F453, 0x1F454, 0x1F455, 0x1F456, 0x1F457, 0x1F458, 0x1F459, 0x1F45A, 0x1F45B, 0x1F45C,
+ 0x1F45D, 0x1F45E, 0x1F45F, 0x1F460, 0x1F461, 0x1F462, 0x1F463, 0x1F464, 0x1F465, 0x1F466,
+ 0x1F467, 0x1F468, 0x1F469, 0x1F46A, 0x1F46B, 0x1F46C, 0x1F46D, 0x1F46E, 0x1F46F, 0x1F470,
+ 0x1F471, 0x1F472, 0x1F473, 0x1F474, 0x1F475, 0x1F476, 0x1F477, 0x1F478, 0x1F479, 0x1F47A,
+ 0x1F47B, 0x1F47C, 0x1F47D, 0x1F47E, 0x1F47F, 0x1F480, 0x1F481, 0x1F482, 0x1F483, 0x1F484,
+ 0x1F485, 0x1F486, 0x1F487, 0x1F488, 0x1F489, 0x1F48A, 0x1F48B, 0x1F48C, 0x1F48D, 0x1F48E,
+ 0x1F48F, 0x1F490, 0x1F491, 0x1F492, 0x1F493, 0x1F494, 0x1F495, 0x1F496, 0x1F497, 0x1F498,
+ 0x1F499, 0x1F49A, 0x1F49B, 0x1F49C, 0x1F49D, 0x1F49E, 0x1F49F, 0x1F4A0, 0x1F4A1, 0x1F4A2,
+ 0x1F4A3, 0x1F4A4, 0x1F4A5, 0x1F4A6, 0x1F4A7, 0x1F4A8, 0x1F4A9, 0x1F4AA, 0x1F4AB, 0x1F4AC,
+ 0x1F4AD, 0x1F4AE, 0x1F4AF, 0x1F4B0, 0x1F4B1, 0x1F4B2, 0x1F4B3, 0x1F4B4, 0x1F4B5, 0x1F4B6,
+ 0x1F4B7, 0x1F4B8, 0x1F4B9, 0x1F4BA, 0x1F4BB, 0x1F4BC, 0x1F4BD, 0x1F4BE, 0x1F4BF, 0x1F4C0,
+ 0x1F4C1, 0x1F4C2, 0x1F4C3, 0x1F4C4, 0x1F4C5, 0x1F4C6, 0x1F4C7, 0x1F4C8, 0x1F4C9, 0x1F4CA,
+ 0x1F4CB, 0x1F4CC, 0x1F4CD, 0x1F4CE, 0x1F4CF, 0x1F4D0, 0x1F4D1, 0x1F4D2, 0x1F4D3, 0x1F4D4,
+ 0x1F4D5, 0x1F4D6, 0x1F4D7, 0x1F4D8, 0x1F4D9, 0x1F4DA, 0x1F4DB, 0x1F4DC, 0x1F4DD, 0x1F4DE,
+ 0x1F4DF, 0x1F4E0, 0x1F4E1, 0x1F4E2, 0x1F4E3, 0x1F4E4, 0x1F4E5, 0x1F4E6, 0x1F4E7, 0x1F4E8,
+ 0x1F4E9, 0x1F4EA, 0x1F4EB, 0x1F4EC, 0x1F4ED, 0x1F4EE, 0x1F4EF, 0x1F4F0, 0x1F4F1, 0x1F4F2,
+ 0x1F4F3, 0x1F4F4, 0x1F4F5, 0x1F4F6, 0x1F4F7, 0x1F4F8, 0x1F4F9, 0x1F4FA, 0x1F4FB, 0x1F4FC,
+ 0x1F4FD, 0x1F4FF, 0x1F500, 0x1F501, 0x1F502, 0x1F503, 0x1F504, 0x1F505, 0x1F506, 0x1F507,
+ 0x1F508, 0x1F509, 0x1F50A, 0x1F50B, 0x1F50C, 0x1F50D, 0x1F50E, 0x1F50F, 0x1F510, 0x1F511,
+ 0x1F512, 0x1F513, 0x1F514, 0x1F515, 0x1F516, 0x1F517, 0x1F518, 0x1F519, 0x1F51A, 0x1F51B,
+ 0x1F51C, 0x1F51D, 0x1F51E, 0x1F51F, 0x1F520, 0x1F521, 0x1F522, 0x1F523, 0x1F524, 0x1F525,
+ 0x1F526, 0x1F527, 0x1F528, 0x1F529, 0x1F52A, 0x1F52B, 0x1F52C, 0x1F52D, 0x1F52E, 0x1F52F,
+ 0x1F530, 0x1F531, 0x1F532, 0x1F533, 0x1F534, 0x1F535, 0x1F536, 0x1F537, 0x1F538, 0x1F539,
+ 0x1F53A, 0x1F53B, 0x1F53C, 0x1F53D, 0x1F549, 0x1F54A, 0x1F54B, 0x1F54C, 0x1F54D, 0x1F54E,
+ 0x1F550, 0x1F551, 0x1F552, 0x1F553, 0x1F554, 0x1F555, 0x1F556, 0x1F557, 0x1F558, 0x1F559,
+ 0x1F55A, 0x1F55B, 0x1F55C, 0x1F55D, 0x1F55E, 0x1F55F, 0x1F560, 0x1F561, 0x1F562, 0x1F563,
+ 0x1F564, 0x1F565, 0x1F566, 0x1F567, 0x1F56F, 0x1F570, 0x1F573, 0x1F574, 0x1F575, 0x1F576,
+ 0x1F577, 0x1F578, 0x1F579, 0x1F57A, 0x1F587, 0x1F58A, 0x1F58B, 0x1F58C, 0x1F58D, 0x1F590,
+ 0x1F595, 0x1F596, 0x1F5A4, 0x1F5A5, 0x1F5A8, 0x1F5B1, 0x1F5B2, 0x1F5BC, 0x1F5C2, 0x1F5C3,
+ 0x1F5C4, 0x1F5D1, 0x1F5D2, 0x1F5D3, 0x1F5DC, 0x1F5DD, 0x1F5DE, 0x1F5E1, 0x1F5E3, 0x1F5E8,
+ 0x1F5EF, 0x1F5F3, 0x1F5FA, 0x1F5FB, 0x1F5FC, 0x1F5FD, 0x1F5FE, 0x1F5FF, 0x1F600, 0x1F601,
+ 0x1F602, 0x1F603, 0x1F604, 0x1F605, 0x1F606, 0x1F607, 0x1F608, 0x1F609, 0x1F60A, 0x1F60B,
+ 0x1F60C, 0x1F60D, 0x1F60E, 0x1F60F, 0x1F610, 0x1F611, 0x1F612, 0x1F613, 0x1F614, 0x1F615,
+ 0x1F616, 0x1F617, 0x1F618, 0x1F619, 0x1F61A, 0x1F61B, 0x1F61C, 0x1F61D, 0x1F61E, 0x1F61F,
+ 0x1F620, 0x1F621, 0x1F622, 0x1F623, 0x1F624, 0x1F625, 0x1F626, 0x1F627, 0x1F628, 0x1F629,
+ 0x1F62A, 0x1F62B, 0x1F62C, 0x1F62D, 0x1F62E, 0x1F62F, 0x1F630, 0x1F631, 0x1F632, 0x1F633,
+ 0x1F634, 0x1F635, 0x1F636, 0x1F637, 0x1F638, 0x1F639, 0x1F63A, 0x1F63B, 0x1F63C, 0x1F63D,
+ 0x1F63E, 0x1F63F, 0x1F640, 0x1F641, 0x1F642, 0x1F643, 0x1F644, 0x1F645, 0x1F646, 0x1F647,
+ 0x1F648, 0x1F649, 0x1F64A, 0x1F64B, 0x1F64C, 0x1F64D, 0x1F64E, 0x1F64F, 0x1F680, 0x1F681,
+ 0x1F682, 0x1F683, 0x1F684, 0x1F685, 0x1F686, 0x1F687, 0x1F688, 0x1F689, 0x1F68A, 0x1F68B,
+ 0x1F68C, 0x1F68D, 0x1F68E, 0x1F68F, 0x1F690, 0x1F691, 0x1F692, 0x1F693, 0x1F694, 0x1F695,
+ 0x1F696, 0x1F697, 0x1F698, 0x1F699, 0x1F69A, 0x1F69B, 0x1F69C, 0x1F69D, 0x1F69E, 0x1F69F,
+ 0x1F6A0, 0x1F6A1, 0x1F6A2, 0x1F6A3, 0x1F6A4, 0x1F6A5, 0x1F6A6, 0x1F6A7, 0x1F6A8, 0x1F6A9,
+ 0x1F6AA, 0x1F6AB, 0x1F6AC, 0x1F6AD, 0x1F6AE, 0x1F6AF, 0x1F6B0, 0x1F6B1, 0x1F6B2, 0x1F6B3,
+ 0x1F6B4, 0x1F6B5, 0x1F6B6, 0x1F6B7, 0x1F6B8, 0x1F6B9, 0x1F6BA, 0x1F6BB, 0x1F6BC, 0x1F6BD,
+ 0x1F6BE, 0x1F6BF, 0x1F6C0, 0x1F6C1, 0x1F6C2, 0x1F6C3, 0x1F6C4, 0x1F6C5, 0x1F6CB, 0x1F6CC,
+ 0x1F6CD, 0x1F6CE, 0x1F6CF, 0x1F6D0, 0x1F6D1, 0x1F6D2, 0x1F6E0, 0x1F6E1, 0x1F6E2, 0x1F6E3,
+ 0x1F6E4, 0x1F6E5, 0x1F6E9, 0x1F6EB, 0x1F6EC, 0x1F6F0, 0x1F6F3, 0x1F6F4, 0x1F6F5, 0x1F6F6,
+ 0x1F910, 0x1F911, 0x1F912, 0x1F913, 0x1F914, 0x1F915, 0x1F916, 0x1F917, 0x1F918, 0x1F919,
+ 0x1F91A, 0x1F91B, 0x1F91C, 0x1F91D, 0x1F91E, 0x1F920, 0x1F921, 0x1F922, 0x1F923, 0x1F924,
+ 0x1F925, 0x1F926, 0x1F927, 0x1F930, 0x1F933, 0x1F934, 0x1F935, 0x1F936, 0x1F937, 0x1F938,
+ 0x1F939, 0x1F93A, 0x1F93B, 0x1F93C, 0x1F93D, 0x1F93E, 0x1F940, 0x1F941, 0x1F942, 0x1F943,
+ 0x1F944, 0x1F945, 0x1F946, 0x1F947, 0x1F948, 0x1F949, 0x1F94A, 0x1F94B, 0x1F950, 0x1F951,
+ 0x1F952, 0x1F953, 0x1F954, 0x1F955, 0x1F956, 0x1F957, 0x1F958, 0x1F959, 0x1F95A, 0x1F95B,
+ 0x1F95C, 0x1F95D, 0x1F95E, 0x1F980, 0x1F981, 0x1F982, 0x1F983, 0x1F984, 0x1F985, 0x1F986,
+ 0x1F987, 0x1F988, 0x1F989, 0x1F98A, 0x1F98B, 0x1F98C, 0x1F98D, 0x1F98E, 0x1F98F, 0x1F990,
+ 0x1F991, 0x1F9C0
};
// See http://www.unicode.org/Public/emoji/3.0/emoji-data.txt
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 3770a45d2172..2f327f3cb495 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -129,8 +129,8 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
// The offset is immediately before a variation selector.
final int STATE_BEFORE_VS = 6;
- // The offset is immediately before a ZWJ emoji.
- final int STATE_BEFORE_ZWJ_EMOJI = 7;
+ // The offset is immediately before an emoji.
+ final int STATE_BEFORE_EMOJI = 7;
// The offset is immediately before a ZWJ that were seen before a ZWJ emoji.
final int STATE_BEFORE_ZWJ = 8;
// The offset is immediately before a variation selector and a ZWJ that were seen before a
@@ -169,7 +169,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
} else if (codePoint == Emoji.COMBINING_ENCLOSING_KEYCAP) {
state = STATE_BEFORE_KEYCAP;
} else if (Emoji.isEmoji(codePoint)) {
- state = STATE_BEFORE_ZWJ_EMOJI;
+ state = STATE_BEFORE_EMOJI;
} else {
state = STATE_FINISHED;
}
@@ -232,7 +232,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
case STATE_BEFORE_VS:
if (Emoji.isEmoji(codePoint)) {
deleteCharCount += Character.charCount(codePoint);
- state = STATE_BEFORE_ZWJ_EMOJI;
+ state = STATE_BEFORE_EMOJI;
break;
}
@@ -242,7 +242,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
}
state = STATE_FINISHED;
break;
- case STATE_BEFORE_ZWJ_EMOJI:
+ case STATE_BEFORE_EMOJI:
if (codePoint == Emoji.ZERO_WIDTH_JOINER) {
state = STATE_BEFORE_ZWJ;
} else {
@@ -252,7 +252,8 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
case STATE_BEFORE_ZWJ:
if (Emoji.isEmoji(codePoint)) {
deleteCharCount += Character.charCount(codePoint) + 1; // +1 for ZWJ.
- state = STATE_BEFORE_ZWJ_EMOJI;
+ state = Emoji.isEmojiModifier(codePoint) ?
+ STATE_BEFORE_EMOJI_MODIFIER : STATE_BEFORE_EMOJI;
} else if (isVariationSelector(codePoint)) {
lastSeenVSCharCount = Character.charCount(codePoint);
state = STATE_BEFORE_VS_AND_ZWJ;
@@ -265,7 +266,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
// +1 for ZWJ.
deleteCharCount += lastSeenVSCharCount + 1 + Character.charCount(codePoint);
lastSeenVSCharCount = 0;
- state = STATE_BEFORE_ZWJ_EMOJI;
+ state = STATE_BEFORE_EMOJI;
} else {
state = STATE_FINISHED;
}
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index fb482b4e33ff..b0f15b5f2329 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -102,8 +102,8 @@ import com.android.internal.view.IDragAndDropPermissions;
* </tr>
* <tr>
* <td>ACTION_DRAG_ENDED</td>
- * <td style="text-align: center;">X</td>
- * <td style="text-align: center;">X</td>
+ * <td style="text-align: center;">&nbsp;</td>
+ * <td style="text-align: center;">&nbsp;</td>
* <td style="text-align: center;">&nbsp;</td>
* <td style="text-align: center;">&nbsp;</td>
* <td style="text-align: center;">&nbsp;</td>
@@ -359,7 +359,7 @@ public class DragEvent implements Parcelable {
* The drag handler or listener for a View can use the metadata in this object to decide if the
* View can accept the dragged View object's data.
* <p>
- * This method returns valid data for all event actions.
+ * This method returns valid data for all event actions except for {@link #ACTION_DRAG_ENDED}.
* @return The ClipDescription that was part of the ClipData sent to the system by startDrag().
*/
public ClipDescription getClipDescription() {
@@ -377,7 +377,7 @@ public class DragEvent implements Parcelable {
* The object is intended to provide local information about the drag and drop operation. For
* example, it can indicate whether the drag and drop operation is a copy or a move.
* <p>
- * This method returns valid data for all event actions.
+ * This method returns valid data for all event actions except for {@link #ACTION_DRAG_ENDED}.
* </p>
* @return The local state object sent to the system by startDrag().
*/
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index e3ff54d40316..9bc0bb4b38f7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -306,6 +306,11 @@ interface IWindowManager
boolean isRotationFrozen();
/**
+ * Screenshot the current wallpaper layer, including the whole screen.
+ */
+ Bitmap screenshotWallpaper();
+
+ /**
* Used only for assist -- request a screenshot of the current application.
*/
boolean requestAssistScreenshot(IAssistScreenshotReceiver receiver);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d4ac30076eaa..e6481147c295 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3744,7 +3744,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Flag indicating that a drag can cross window boundaries. When
* {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
- * with this flag set, all visible applications will be able to participate
+ * with this flag set, all visible applications with targetSdkVersion >=
+ * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
* in the drag operation and receive the dragged content.
*
* If this is the only flag set, then the drag recipient will only have access to text data
@@ -4214,25 +4215,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
setAlpha(a.getFloat(attr, 1f));
break;
case com.android.internal.R.styleable.View_transformPivotX:
- setPivotX(a.getDimensionPixelOffset(attr, 0));
+ setPivotX(a.getDimension(attr, 0));
break;
case com.android.internal.R.styleable.View_transformPivotY:
- setPivotY(a.getDimensionPixelOffset(attr, 0));
+ setPivotY(a.getDimension(attr, 0));
break;
case com.android.internal.R.styleable.View_translationX:
- tx = a.getDimensionPixelOffset(attr, 0);
+ tx = a.getDimension(attr, 0);
transformSet = true;
break;
case com.android.internal.R.styleable.View_translationY:
- ty = a.getDimensionPixelOffset(attr, 0);
+ ty = a.getDimension(attr, 0);
transformSet = true;
break;
case com.android.internal.R.styleable.View_translationZ:
- tz = a.getDimensionPixelOffset(attr, 0);
+ tz = a.getDimension(attr, 0);
transformSet = true;
break;
case com.android.internal.R.styleable.View_elevation:
- elevation = a.getDimensionPixelOffset(attr, 0);
+ elevation = a.getDimension(attr, 0);
transformSet = true;
break;
case com.android.internal.R.styleable.View_rotation:
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c42752287a42..209886b27c18 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1731,7 +1731,7 @@ public final class ViewRootImpl implements ViewParent,
}
boolean hwInitialized = false;
- boolean framesChanged = false;
+ boolean contentInsetsChanged = false;
boolean hadSurface = mSurface.isValid();
try {
@@ -1771,7 +1771,7 @@ public final class ViewRootImpl implements ViewParent,
final boolean overscanInsetsChanged = !mPendingOverscanInsets.equals(
mAttachInfo.mOverscanInsets);
- boolean contentInsetsChanged = !mPendingContentInsets.equals(
+ contentInsetsChanged = !mPendingContentInsets.equals(
mAttachInfo.mContentInsets);
final boolean visibleInsetsChanged = !mPendingVisibleInsets.equals(
mAttachInfo.mVisibleInsets);
@@ -1821,19 +1821,6 @@ public final class ViewRootImpl implements ViewParent,
+ mAttachInfo.mVisibleInsets);
}
- // If any of the insets changed, do a forceLayout on the view so that the
- // measure cache is cleared. We might have a pending MSG_RESIZED_REPORT
- // that is supposed to take care of it, but since pending insets are
- // already modified here, it won't detect the frame change after this.
- framesChanged = overscanInsetsChanged
- || contentInsetsChanged
- || stableInsetsChanged
- || visibleInsetsChanged
- || outsetsChanged;
- if (mAdded && mView != null && framesChanged) {
- forceLayout(mView);
- }
-
if (!hadSurface) {
if (mSurface.isValid()) {
// If we are creating a new surface, then we need to
@@ -2017,7 +2004,7 @@ public final class ViewRootImpl implements ViewParent,
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
(relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
- || mHeight != host.getMeasuredHeight() || framesChanged ||
+ || mHeight != host.getMeasuredHeight() || contentInsetsChanged ||
updatedConfiguration) {
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
@@ -2026,7 +2013,7 @@ public final class ViewRootImpl implements ViewParent,
+ mWidth + " measuredWidth=" + host.getMeasuredWidth()
+ " mHeight=" + mHeight
+ " measuredHeight=" + host.getMeasuredHeight()
- + " framesChanged=" + framesChanged);
+ + " coveredInsetsChanged=" + contentInsetsChanged);
// Ask host how big it wants to be
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
@@ -3186,7 +3173,7 @@ public final class ViewRootImpl implements ViewParent,
}
focusNode.recycle();
}
- if (mAccessibilityFocusedHost != null) {
+ if ((mAccessibilityFocusedHost != null) && (mAccessibilityFocusedHost != view)) {
// Clear accessibility focus in the view.
mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks(
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 7d7b8804cf12..b65f93309e04 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2316,22 +2316,24 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
/**
- * Get a view and have it show the data associated with the specified
- * position. This is called when we have already discovered that the view is
- * not available for reuse in the recycle bin. The only choices left are
+ * Gets a view and have it show the data associated with the specified
+ * position. This is called when we have already discovered that the view
+ * is not available for reuse in the recycle bin. The only choices left are
* converting an old view or making a new one.
*
- * @param position The position to display
- * @param isScrap Array of at least 1 boolean, the first entry will become true if
- * the returned view was taken from the "temporary detached" scrap heap, false if
- * otherwise.
+ * @param position the position to display
+ * @param outMetadata an array of at least 1 boolean where the first entry
+ * will be set {@code true} if the view is currently
+ * attached to the window, {@code false} otherwise (e.g.
+ * newly-inflated or remained scrap for multiple layout
+ * passes)
*
* @return A view displaying the data associated with the specified position
*/
- View obtainView(int position, boolean[] isScrap) {
+ View obtainView(int position, boolean[] outMetadata) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "obtainView");
- isScrap[0] = false;
+ outMetadata[0] = false;
// Check whether we have a transient state view. Attempt to re-bind the
// data and discard the view if we fail.
@@ -2350,7 +2352,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
- isScrap[0] = true;
+ outMetadata[0] = true;
// Finish the temporary detach started in addScrapView().
transientView.dispatchFinishTemporaryDetach();
@@ -2363,19 +2365,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (child != scrapView) {
// Failed to re-bind the data, return scrap to the heap.
mRecycler.addScrapView(scrapView, position);
- } else {
- if (child.isTemporarilyDetached()) {
- isScrap[0] = true;
-
- // Finish the temporary detach started in addScrapView().
- child.dispatchFinishTemporaryDetach();
- } else {
- // we set isScrap to "true" only if the view is temporarily detached.
- // if the view is fully detached, it is as good as a view created by the
- // adapter
- isScrap[0] = false;
- }
+ } else if (child.isTemporarilyDetached()) {
+ outMetadata[0] = true;
+ // Finish the temporary detach started in addScrapView().
+ child.dispatchFinishTemporaryDetach();
}
}
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 6d7313da0043..b95aa52c11e9 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1407,72 +1407,73 @@ public class GridView extends AbsListView {
/**
- * Obtain the view and add it to our list of children. The view can be made
- * fresh, converted from an unused view, or used as is if it was in the
- * recycle bin.
+ * Obtains the view and adds it to our list of children. The view can be
+ * made fresh, converted from an unused view, or used as is if it was in
+ * the recycle bin.
*
- * @param position Logical position in the list
- * @param y Top or bottom edge of the view to add
- * @param flow if true, align top edge to y. If false, align bottom edge to
- * y.
- * @param childrenLeft Left edge where children should be positioned
- * @param selected Is this position selected?
- * @param where to add new item in the list
+ * @param position logical position in the list
+ * @param y top or bottom edge of the view to add
+ * @param flow {@code true} to align top edge to y, {@code false} to align
+ * bottom edge to y
+ * @param childrenLeft left edge where children should be positioned
+ * @param selected {@code true} if the position is selected, {@code false}
+ * otherwise
+ * @param where position at which to add new item in the list
* @return View that was added
*/
private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
boolean selected, int where) {
- View child;
-
if (!mDataChanged) {
// Try to use an existing view for this position
- child = mRecycler.getActiveView(position);
- if (child != null) {
+ final View activeView = mRecycler.getActiveView(position);
+ if (activeView != null) {
// Found it -- we're using an existing child
// This just needs to be positioned
- setupChild(child, position, y, flow, childrenLeft, selected, true, where);
- return child;
+ setupChild(activeView, position, y, flow, childrenLeft, selected, true, where);
+ return activeView;
}
}
// Make a new view for this position, or convert an unused view if
- // possible
- child = obtainView(position, mIsScrap);
+ // possible.
+ final View child = obtainView(position, mIsScrap);
- // This needs to be positioned and measured
+ // This needs to be positioned and measured.
setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0], where);
return child;
}
/**
- * Add a view as a child and make sure it is measured (if necessary) and
+ * Adds a view as a child and make sure it is measured (if necessary) and
* positioned properly.
*
- * @param child The view to add
- * @param position The position of the view
- * @param y The y position relative to which this view will be positioned
- * @param flow if true, align top edge to y. If false, align bottom edge
- * to y.
- * @param childrenLeft Left edge where children should be positioned
- * @param selected Is this position selected?
- * @param recycled Has this view been pulled from the recycle bin? If so it
- * does not need to be remeasured.
- * @param where Where to add the item in the list
+ * @param child the view to add
+ * @param position the position of this child
+ * @param y the y position relative to which this view will be positioned
+ * @param flowDown {@code true} to align top edge to y, {@code false} to
+ * align bottom edge to y
+ * @param childrenLeft left edge where children should be positioned
+ * @param selected {@code true} if the position is selected, {@code false}
+ * otherwise
+ * @param isAttachedToWindow {@code true} if the view is already attached
+ * to the window, e.g. whether it was reused, or
+ * {@code false} otherwise
+ * @param where position at which to add new item in the list
*
*/
- private void setupChild(View child, int position, int y, boolean flow, int childrenLeft,
- boolean selected, boolean recycled, int where) {
+ private void setupChild(View child, int position, int y, boolean flowDown, int childrenLeft,
+ boolean selected, boolean isAttachedToWindow, int where) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "setupGridItem");
boolean isSelected = selected && shouldShowSelector();
final boolean updateChildSelected = isSelected != child.isSelected();
final int mode = mTouchMode;
- final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL &&
- mMotionPosition == position;
+ final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL
+ && mMotionPosition == position;
final boolean updateChildPressed = isPressed != child.isPressed();
-
- boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();
+ final boolean needToMeasure = !isAttachedToWindow || updateChildSelected
+ || child.isLayoutRequested();
// Respect layout params that are already in the view. Otherwise make
// some up...
@@ -1483,13 +1484,9 @@ public class GridView extends AbsListView {
p.viewType = mAdapter.getItemViewType(position);
p.isEnabled = mAdapter.isEnabled(position);
- if (recycled && !p.forceAdd) {
- attachViewToParent(child, where, p);
- } else {
- p.forceAdd = false;
- addViewInLayout(child, where, p, true);
- }
-
+ // Set up view state before attaching the view, since we may need to
+ // rely on the jumpDrawablesToCurrentState() call that occurs as part
+ // of view attachment.
if (updateChildSelected) {
child.setSelected(isSelected);
if (isSelected) {
@@ -1510,6 +1507,21 @@ public class GridView extends AbsListView {
}
}
+ if (isAttachedToWindow && !p.forceAdd) {
+ attachViewToParent(child, where, p);
+
+ // If the view isn't attached, or if it's attached but for a different
+ // position, then jump the drawables.
+ if (!isAttachedToWindow
+ || (((AbsListView.LayoutParams) child.getLayoutParams()).scrappedFromPosition)
+ != position) {
+ child.jumpDrawablesToCurrentState();
+ }
+ } else {
+ p.forceAdd = false;
+ addViewInLayout(child, where, p, true);
+ }
+
if (needToMeasure) {
int childHeightSpec = ViewGroup.getChildMeasureSpec(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
@@ -1525,7 +1537,7 @@ public class GridView extends AbsListView {
final int h = child.getMeasuredHeight();
int childLeft;
- final int childTop = flow ? y : y - h;
+ final int childTop = flowDown ? y : y - h;
final int layoutDirection = getLayoutDirection();
final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
@@ -1553,15 +1565,10 @@ public class GridView extends AbsListView {
child.offsetTopAndBottom(childTop - child.getTop());
}
- if (mCachingStarted) {
+ if (mCachingStarted && !child.isDrawingCacheEnabled()) {
child.setDrawingCacheEnabled(true);
}
- if (recycled && (((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition)
- != position) {
- child.jumpDrawablesToCurrentState();
- }
-
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 0e04e3003d7c..b8b7c553a1db 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1939,72 +1939,73 @@ public class ListView extends AbsListView {
}
/**
- * Obtain the view and add it to our list of children. The view can be made
- * fresh, converted from an unused view, or used as is if it was in the
- * recycle bin.
+ * Obtains the view and adds it to our list of children. The view can be
+ * made fresh, converted from an unused view, or used as is if it was in
+ * the recycle bin.
*
- * @param position Logical position in the list
- * @param y Top or bottom edge of the view to add
- * @param flow If flow is true, align top edge to y. If false, align bottom
- * edge to y.
- * @param childrenLeft Left edge where children should be positioned
- * @param selected Is this position selected?
- * @return View that was added
+ * @param position logical position in the list
+ * @param y top or bottom edge of the view to add
+ * @param flow {@code true} to align top edge to y, {@code false} to align
+ * bottom edge to y
+ * @param childrenLeft left edge where children should be positioned
+ * @param selected {@code true} if the position is selected, {@code false}
+ * otherwise
+ * @return the view that was added
*/
private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
boolean selected) {
- View child;
-
-
if (!mDataChanged) {
- // Try to use an existing view for this position
- child = mRecycler.getActiveView(position);
- if (child != null) {
- // Found it -- we're using an existing child
- // This just needs to be positioned
- setupChild(child, position, y, flow, childrenLeft, selected, true);
-
- return child;
+ // Try to use an existing view for this position.
+ final View activeView = mRecycler.getActiveView(position);
+ if (activeView != null) {
+ // Found it. We're reusing an existing child, so it just needs
+ // to be positioned like a scrap view.
+ setupChild(activeView, position, y, flow, childrenLeft, selected, true);
+ return activeView;
}
}
- // Make a new view for this position, or convert an unused view if possible
- child = obtainView(position, mIsScrap);
+ // Make a new view for this position, or convert an unused view if
+ // possible.
+ final View child = obtainView(position, mIsScrap);
- // This needs to be positioned and measured
+ // This needs to be positioned and measured.
setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]);
return child;
}
/**
- * Add a view as a child and make sure it is measured (if necessary) and
+ * Adds a view as a child and make sure it is measured (if necessary) and
* positioned properly.
*
- * @param child The view to add
- * @param position The position of this child
- * @param y The y position relative to which this view will be positioned
- * @param flowDown If true, align top edge to y. If false, align bottom
- * edge to y.
- * @param childrenLeft Left edge where children should be positioned
- * @param selected Is this position selected?
- * @param recycled Has this view been pulled from the recycle bin? If so it
- * does not need to be remeasured.
+ * @param child the view to add
+ * @param position the position of this child
+ * @param y the y position relative to which this view will be positioned
+ * @param flowDown {@code true} to align top edge to y, {@code false} to
+ * align bottom edge to y
+ * @param childrenLeft left edge where children should be positioned
+ * @param selected {@code true} if the position is selected, {@code false}
+ * otherwise
+ * @param isAttachedToWindow {@code true} if the view is already attached
+ * to the window, e.g. whether it was reused, or
+ * {@code false} otherwise
*/
private void setupChild(View child, int position, int y, boolean flowDown, int childrenLeft,
- boolean selected, boolean recycled) {
+ boolean selected, boolean isAttachedToWindow) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "setupListItem");
final boolean isSelected = selected && shouldShowSelector();
final boolean updateChildSelected = isSelected != child.isSelected();
final int mode = mTouchMode;
- final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL &&
- mMotionPosition == position;
+ final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL
+ && mMotionPosition == position;
final boolean updateChildPressed = isPressed != child.isPressed();
- final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();
+ final boolean needToMeasure = !isAttachedToWindow || updateChildSelected
+ || child.isLayoutRequested();
- // Respect layout params that are already in the view. Otherwise make some up...
- // noinspection unchecked
+ // Respect layout params that are already in the view. Otherwise make
+ // some up...
AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams();
if (p == null) {
p = (AbsListView.LayoutParams) generateDefaultLayoutParams();
@@ -2012,17 +2013,9 @@ public class ListView extends AbsListView {
p.viewType = mAdapter.getItemViewType(position);
p.isEnabled = mAdapter.isEnabled(position);
- if ((recycled && !p.forceAdd) || (p.recycledHeaderFooter
- && p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) {
- attachViewToParent(child, flowDown ? -1 : 0, p);
- } else {
- p.forceAdd = false;
- if (p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
- p.recycledHeaderFooter = true;
- }
- addViewInLayout(child, flowDown ? -1 : 0, p, true);
- }
-
+ // Set up view state before attaching the view, since we may need to
+ // rely on the jumpDrawablesToCurrentState() call that occurs as part
+ // of view attachment.
if (updateChildSelected) {
child.setSelected(isSelected);
}
@@ -2040,6 +2033,25 @@ public class ListView extends AbsListView {
}
}
+ if ((isAttachedToWindow && !p.forceAdd) || (p.recycledHeaderFooter
+ && p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) {
+ attachViewToParent(child, flowDown ? -1 : 0, p);
+
+ // If the view was previously attached for a different position,
+ // then manually jump the drawables.
+ if (isAttachedToWindow
+ && (((AbsListView.LayoutParams) child.getLayoutParams()).scrappedFromPosition)
+ != position) {
+ child.jumpDrawablesToCurrentState();
+ }
+ } else {
+ p.forceAdd = false;
+ if (p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
+ p.recycledHeaderFooter = true;
+ }
+ addViewInLayout(child, flowDown ? -1 : 0, p, true);
+ }
+
if (needToMeasure) {
final int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
mListPadding.left + mListPadding.right, p.width);
@@ -2073,11 +2085,6 @@ public class ListView extends AbsListView {
child.setDrawingCacheEnabled(true);
}
- if (recycled && (((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition)
- != position) {
- child.jumpDrawablesToCurrentState();
- }
-
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java
new file mode 100644
index 000000000000..03cd729db62b
--- /dev/null
+++ b/core/java/com/android/internal/app/NightDisplayController.java
@@ -0,0 +1,421 @@
+/*
+ * 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.internal.app;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings.Secure;
+import android.util.Slog;
+
+import com.android.internal.R;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * Controller for managing Night display settings.
+ * <p/>
+ * Night display tints your screen red at night. This makes it easier to look at your screen in
+ * dim light and may help you fall asleep more easily.
+ */
+public final class NightDisplayController {
+
+ private static final String TAG = "NightDisplayController";
+ private static final boolean DEBUG = false;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ AUTO_MODE_DISABLED, AUTO_MODE_CUSTOM, AUTO_MODE_TWILIGHT })
+ public @interface AutoMode {}
+
+ /**
+ * Auto mode value to prevent Night display from being automatically activated. It can still
+ * be activated manually via {@link #setActivated(boolean)}.
+ *
+ * @see #setAutoMode(int)
+ */
+ public static final int AUTO_MODE_DISABLED = 0;
+ /**
+ * Auto mode value to automatically activate Night display at a specific start and end time.
+ *
+ * @see #setAutoMode(int)
+ * @see #setCustomStartTime(LocalTime)
+ * @see #setCustomEndTime(LocalTime)
+ */
+ public static final int AUTO_MODE_CUSTOM = 1;
+ /**
+ * Auto mode value to automatically activate Night display from sunset to sunrise.
+ *
+ * @see #setAutoMode(int)
+ */
+ public static final int AUTO_MODE_TWILIGHT = 2;
+
+ private final Context mContext;
+ private final int mUserId;
+
+ private final ContentObserver mContentObserver;
+
+ private Callback mCallback;
+
+ public NightDisplayController(@NonNull Context context) {
+ this(context, UserHandle.myUserId());
+ }
+
+ public NightDisplayController(@NonNull Context context, int userId) {
+ mContext = context.getApplicationContext();
+ mUserId = userId;
+
+ mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+
+ final String setting = uri == null ? null : uri.getLastPathSegment();
+ if (setting != null) {
+ onSettingChanged(setting);
+ }
+ }
+ };
+ }
+
+ /**
+ * Returns {@code true} when Night display is activated (the display is tinted red).
+ */
+ public boolean isActivated() {
+ return Secure.getIntForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_ACTIVATED, 0, mUserId) == 1;
+ }
+
+ /**
+ * Sets whether Night display should be activated.
+ *
+ * @param activated {@code true} if Night display should be activated
+ * @return {@code true} if the activated value was set successfully
+ */
+ public boolean setActivated(boolean activated) {
+ return Secure.putIntForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_ACTIVATED, activated ? 1 : 0, mUserId);
+ }
+
+ /**
+ * Returns the current auto mode value controlling when Night display will be automatically
+ * activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM}, or
+ * {@link #AUTO_MODE_TWILIGHT}.
+ */
+ public @AutoMode int getAutoMode() {
+ int autoMode = Secure.getIntForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_AUTO_MODE, -1, mUserId);
+ if (autoMode == -1) {
+ if (DEBUG) {
+ Slog.d(TAG, "Using default value for setting: " + Secure.NIGHT_DISPLAY_AUTO_MODE);
+ }
+ autoMode = mContext.getResources().getInteger(
+ R.integer.config_defaultNightDisplayAutoMode);
+ }
+
+ if (autoMode != AUTO_MODE_DISABLED
+ && autoMode != AUTO_MODE_CUSTOM
+ && autoMode != AUTO_MODE_TWILIGHT) {
+ Slog.e(TAG, "Invalid autoMode: " + autoMode);
+ autoMode = AUTO_MODE_DISABLED;
+ }
+
+ return autoMode;
+ }
+
+ /**
+ * Sets the current auto mode value controlling when Night display will be automatically
+ * activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM}, or
+ * {@link #AUTO_MODE_TWILIGHT}.
+ *
+ * @param autoMode the new auto mode to use
+ * @return {@code true} if new auto mode was set successfully
+ */
+ public boolean setAutoMode(@AutoMode int autoMode) {
+ if (autoMode != AUTO_MODE_DISABLED
+ && autoMode != AUTO_MODE_CUSTOM
+ && autoMode != AUTO_MODE_TWILIGHT) {
+ throw new IllegalArgumentException("Invalid autoMode: " + autoMode);
+ }
+
+ return Secure.putIntForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_AUTO_MODE, autoMode, mUserId);
+ }
+
+ /**
+ * Returns the local time when Night display will be automatically activated when using
+ * {@link #AUTO_MODE_CUSTOM}.
+ */
+ public @NonNull LocalTime getCustomStartTime() {
+ int startTimeValue = Secure.getIntForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, -1, mUserId);
+ if (startTimeValue == -1) {
+ if (DEBUG) {
+ Slog.d(TAG, "Using default value for setting: "
+ + Secure.NIGHT_DISPLAY_CUSTOM_START_TIME);
+ }
+ startTimeValue = mContext.getResources().getInteger(
+ R.integer.config_defaultNightDisplayCustomStartTime);
+ }
+
+ return LocalTime.valueOf(startTimeValue);
+ }
+
+ /**
+ * Sets the local time when Night display will be automatically activated when using
+ * {@link #AUTO_MODE_CUSTOM}.
+ *
+ * @param startTime the local time to automatically activate Night display
+ * @return {@code true} if the new custom start time was set successfully
+ */
+ public boolean setCustomStartTime(@NonNull LocalTime startTime) {
+ if (startTime == null) {
+ throw new IllegalArgumentException("startTime cannot be null");
+ }
+ return Secure.putIntForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_CUSTOM_START_TIME, startTime.toMillis(), mUserId);
+ }
+
+ /**
+ * Returns the local time when Night display will be automatically deactivated when using
+ * {@link #AUTO_MODE_CUSTOM}.
+ */
+ public @NonNull LocalTime getCustomEndTime() {
+ int endTimeValue = Secure.getIntForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, -1, mUserId);
+ if (endTimeValue == -1) {
+ if (DEBUG) {
+ Slog.d(TAG, "Using default value for setting: "
+ + Secure.NIGHT_DISPLAY_CUSTOM_END_TIME);
+ }
+ endTimeValue = mContext.getResources().getInteger(
+ R.integer.config_defaultNightDisplayCustomEndTime);
+ }
+
+ return LocalTime.valueOf(endTimeValue);
+ }
+
+ /**
+ * Sets the local time when Night display will be automatically deactivated when using
+ * {@link #AUTO_MODE_CUSTOM}.
+ *
+ * @param endTime the local time to automatically deactivate Night display
+ * @return {@code true} if the new custom end time was set successfully
+ */
+ public boolean setCustomEndTime(@NonNull LocalTime endTime) {
+ if (endTime == null) {
+ throw new IllegalArgumentException("endTime cannot be null");
+ }
+ return Secure.putIntForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_CUSTOM_END_TIME, endTime.toMillis(), mUserId);
+ }
+
+ private void onSettingChanged(@NonNull String setting) {
+ if (DEBUG) {
+ Slog.d(TAG, "onSettingChanged: " + setting);
+ }
+
+ if (mCallback != null) {
+ switch (setting) {
+ case Secure.NIGHT_DISPLAY_ACTIVATED:
+ mCallback.onActivated(isActivated());
+ break;
+ case Secure.NIGHT_DISPLAY_AUTO_MODE:
+ mCallback.onAutoModeChanged(getAutoMode());
+ break;
+ case Secure.NIGHT_DISPLAY_CUSTOM_START_TIME:
+ mCallback.onCustomStartTimeChanged(getCustomStartTime());
+ break;
+ case Secure.NIGHT_DISPLAY_CUSTOM_END_TIME:
+ mCallback.onCustomEndTimeChanged(getCustomEndTime());
+ break;
+ }
+ }
+ }
+
+ /**
+ * Register a callback to be invoked whenever the Night display settings are changed.
+ */
+ public void setListener(Callback callback) {
+ final Callback oldCallback = mCallback;
+ if (oldCallback != callback) {
+ mCallback = callback;
+
+ if (callback == null) {
+ // Stop listening for changes now that there IS NOT a listener.
+ mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+ } else if (oldCallback == null) {
+ // Start listening for changes now that there IS a listener.
+ final ContentResolver cr = mContext.getContentResolver();
+ cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_ACTIVATED),
+ false /* notifyForDescendants */, mContentObserver, mUserId);
+ cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_AUTO_MODE),
+ false /* notifyForDescendants */, mContentObserver, mUserId);
+ cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_START_TIME),
+ false /* notifyForDescendants */, mContentObserver, mUserId);
+ cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_CUSTOM_END_TIME),
+ false /* notifyForDescendants */, mContentObserver, mUserId);
+ }
+ }
+ }
+
+ /**
+ * Returns {@code true} if Night display is supported by the device.
+ */
+ public static boolean isAvailable(Context context) {
+ return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
+ }
+
+ /**
+ * A time without a time-zone or date.
+ */
+ public static class LocalTime {
+
+ /**
+ * The hour of the day from 0 - 23.
+ */
+ public final int hourOfDay;
+ /**
+ * The minute within the hour from 0 - 59.
+ */
+ public final int minute;
+
+ public LocalTime(int hourOfDay, int minute) {
+ if (hourOfDay < 0 || hourOfDay > 23) {
+ throw new IllegalArgumentException("Invalid hourOfDay: " + hourOfDay);
+ } else if (minute < 0 || minute > 59) {
+ throw new IllegalArgumentException("Invalid minute: " + minute);
+ }
+
+ this.hourOfDay = hourOfDay;
+ this.minute = minute;
+ }
+
+ /**
+ * Returns the first date time corresponding to this local time that occurs before the
+ * provided date time.
+ *
+ * @param time the date time to compare against
+ * @return the prior date time corresponding to this local time
+ */
+ public Calendar getDateTimeBefore(Calendar time) {
+ final Calendar c = Calendar.getInstance();
+ c.set(Calendar.YEAR, time.get(Calendar.YEAR));
+ c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR));
+
+ c.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ c.set(Calendar.MINUTE, minute);
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+
+ // Check if the local time has past, if so return the same time tomorrow.
+ if (c.after(time)) {
+ c.add(Calendar.DATE, -1);
+ }
+
+ return c;
+ }
+
+ /**
+ * Returns the first date time corresponding to this local time that occurs after the
+ * provided date time.
+ *
+ * @param time the date time to compare against
+ * @return the next date time corresponding to this local time
+ */
+ public Calendar getDateTimeAfter(Calendar time) {
+ final Calendar c = Calendar.getInstance();
+ c.set(Calendar.YEAR, time.get(Calendar.YEAR));
+ c.set(Calendar.DAY_OF_YEAR, time.get(Calendar.DAY_OF_YEAR));
+
+ c.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ c.set(Calendar.MINUTE, minute);
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+
+ // Check if the local time has past, if so return the same time tomorrow.
+ if (c.before(time)) {
+ c.add(Calendar.DATE, 1);
+ }
+
+ return c;
+ }
+
+ /**
+ * Returns a local time corresponding the given number of milliseconds from midnight.
+ *
+ * @param millis the number of milliseconds from midnight
+ * @return the corresponding local time
+ */
+ private static LocalTime valueOf(int millis) {
+ final int hourOfDay = (millis / 3600000) % 24;
+ final int minutes = (millis / 60000) % 60;
+ return new LocalTime(hourOfDay, minutes);
+ }
+
+ /**
+ * Returns the local time represented as milliseconds from midnight.
+ */
+ private int toMillis() {
+ return hourOfDay * 3600000 + minute * 60000;
+ }
+
+ @Override
+ public String toString() {
+ return String.format(Locale.US, "%02d:%02d", hourOfDay, minute);
+ }
+ }
+
+ /**
+ * Callback invoked whenever the Night display settings are changed.
+ */
+ public interface Callback {
+ /**
+ * Callback invoked when the activated state changes.
+ *
+ * @param activated {@code true} if Night display is activated
+ */
+ default void onActivated(boolean activated) {}
+ /**
+ * Callback invoked when the auto mode changes.
+ *
+ * @param autoMode the auto mode to use
+ */
+ default void onAutoModeChanged(int autoMode) {}
+ /**
+ * Callback invoked when the time to automatically activate Night display changes.
+ *
+ * @param startTime the local time to automatically activate Night display
+ */
+ default void onCustomStartTimeChanged(LocalTime startTime) {}
+ /**
+ * Callback invoked when the time to automatically deactivate Night display changes.
+ *
+ * @param endTime the local time to automatically deactivate Night display
+ */
+ default void onCustomEndTimeChanged(LocalTime endTime) {}
+ }
+}
diff --git a/core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl b/core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl
new file mode 100644
index 000000000000..79717cf2b0c9
--- /dev/null
+++ b/core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+/** {@hide} */
+oneway interface ICheckCredentialProgressCallback {
+ void onCredentialVerified();
+}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 05b839df9fa4..9fa558e89ae7 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -17,6 +17,7 @@
package com.android.internal.widget;
import android.app.trust.IStrongAuthTracker;
+import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.VerifyCredentialResponse;
/** {@hide} */
@@ -29,10 +30,12 @@ interface ILockSettings {
String getString(in String key, in String defaultValue, in int userId);
void setLockPattern(in String pattern, in String savedPattern, int userId);
void resetKeyStore(int userId);
- VerifyCredentialResponse checkPattern(in String pattern, int userId);
+ VerifyCredentialResponse checkPattern(in String pattern, int userId,
+ in ICheckCredentialProgressCallback progressCallback);
VerifyCredentialResponse verifyPattern(in String pattern, long challenge, int userId);
void setLockPassword(in String password, in String savedPassword, int userId);
- VerifyCredentialResponse checkPassword(in String password, int userId);
+ VerifyCredentialResponse checkPassword(in String password, int userId,
+ in ICheckCredentialProgressCallback progressCallback);
VerifyCredentialResponse verifyPassword(in String password, long challenge, int userId);
VerifyCredentialResponse verifyTiedProfileChallenge(String password, boolean isPattern, long challenge, int userId);
boolean checkVoldPassword(int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternChecker.java b/core/java/com/android/internal/widget/LockPatternChecker.java
index 713f56f46266..df9b0ddc1804 100644
--- a/core/java/com/android/internal/widget/LockPatternChecker.java
+++ b/core/java/com/android/internal/widget/LockPatternChecker.java
@@ -14,6 +14,13 @@ public final class LockPatternChecker {
* Interface for a callback to be invoked after security check.
*/
public interface OnCheckCallback {
+
+ /**
+ * Invoked as soon as possible we know that the credentials match. This will be called
+ * earlier than {@link #onChecked} but only if the credentials match.
+ */
+ default void onEarlyMatched() {}
+
/**
* Invoked when a security check is finished.
*
@@ -92,7 +99,7 @@ public final class LockPatternChecker {
@Override
protected Boolean doInBackground(Void... args) {
try {
- return utils.checkPattern(pattern, userId);
+ return utils.checkPattern(pattern, userId, callback::onEarlyMatched);
} catch (RequestThrottledException ex) {
mThrottleTimeout = ex.getTimeoutMs();
return false;
@@ -199,7 +206,7 @@ public final class LockPatternChecker {
@Override
protected Boolean doInBackground(Void... args) {
try {
- return utils.checkPassword(password, userId);
+ return utils.checkPassword(password, userId, callback::onEarlyMatched);
} catch (RequestThrottledException ex) {
mThrottleTimeout = ex.getTimeoutMs();
return false;
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2e0dfa5fa731..0059d4df79f7 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -17,6 +17,7 @@
package com.android.internal.widget;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.app.admin.DevicePolicyManager;
import android.app.trust.IStrongAuthTracker;
import android.app.trust.TrustManager;
@@ -32,7 +33,6 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.IMountService;
@@ -149,6 +149,7 @@ public class LockPatternUtils {
private DevicePolicyManager mDevicePolicyManager;
private ILockSettings mLockSettingsService;
private UserManager mUserManager;
+ private final Handler mHandler;
/**
* Use {@link TrustManager#isTrustUsuallyManaged(int)}.
@@ -230,6 +231,9 @@ public class LockPatternUtils {
public LockPatternUtils(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
+
+ Looper looper = Looper.myLooper();
+ mHandler = looper != null ? new Handler(looper) : null;
}
private ILockSettings getLockSettings() {
@@ -341,10 +345,23 @@ public class LockPatternUtils {
*/
public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId)
throws RequestThrottledException {
+ return checkPattern(pattern, userId, null /* progressCallback */);
+ }
+
+ /**
+ * Check to see if a pattern matches the saved pattern. If no pattern exists,
+ * always returns true.
+ * @param pattern The pattern to check.
+ * @return Whether the pattern matches the stored one.
+ */
+ public boolean checkPattern(List<LockPatternView.Cell> pattern, int userId,
+ @Nullable CheckCredentialProgressCallback progressCallback)
+ throws RequestThrottledException {
throwIfCalledOnMainThread();
try {
VerifyCredentialResponse response =
- getLockSettings().checkPattern(patternToString(pattern), userId);
+ getLockSettings().checkPattern(patternToString(pattern), userId,
+ wrapCallback(progressCallback));
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
return true;
@@ -423,10 +440,22 @@ public class LockPatternUtils {
* @return Whether the password matches the stored one.
*/
public boolean checkPassword(String password, int userId) throws RequestThrottledException {
+ return checkPassword(password, userId, null /* progressCallback */);
+ }
+
+ /**
+ * Check to see if a password matches the saved password. If no password exists,
+ * always returns true.
+ * @param password The password to check.
+ * @return Whether the password matches the stored one.
+ */
+ public boolean checkPassword(String password, int userId,
+ @Nullable CheckCredentialProgressCallback progressCallback)
+ throws RequestThrottledException {
throwIfCalledOnMainThread();
try {
VerifyCredentialResponse response =
- getLockSettings().checkPassword(password, userId);
+ getLockSettings().checkPassword(password, userId, wrapCallback(progressCallback));
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
return true;
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
@@ -1475,6 +1504,37 @@ public class LockPatternUtils {
return (getStrongAuthForUser(userId) & ~StrongAuthTracker.ALLOWING_FINGERPRINT) == 0;
}
+ private ICheckCredentialProgressCallback wrapCallback(
+ final CheckCredentialProgressCallback callback) {
+ if (callback == null) {
+ return null;
+ } else {
+ if (mHandler == null) {
+ throw new IllegalStateException("Must construct LockPatternUtils on a looper thread"
+ + " to use progress callbacks.");
+ }
+ return new ICheckCredentialProgressCallback.Stub() {
+
+ @Override
+ public void onCredentialVerified() throws RemoteException {
+ mHandler.post(callback::onEarlyMatched);
+ }
+ };
+ }
+ }
+
+ /**
+ * Callback to be notified about progress when checking credentials.
+ */
+ public interface CheckCredentialProgressCallback {
+
+ /**
+ * Called as soon as possible when we know that the credentials match but the user hasn't
+ * been fully unlocked.
+ */
+ void onEarlyMatched();
+ }
+
/**
* Tracks the global strong authentication state.
*/
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 898cf77cb32d..85092ad4fdd4 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -768,6 +768,21 @@ namespace PaintGlue {
return false;
}
+ // Don't count glyphs that are the recommended "space" glyph and are zero width.
+ // This logic makes assumptions about HarfBuzz layout, but does correctly handle
+ // cases where ligatures form and zero width space glyphs are left in as
+ // placeholders.
+ static size_t countNonSpaceGlyphs(const Layout& layout) {
+ size_t count = 0;
+ static unsigned int kSpaceGlyphId = 3;
+ for (size_t i = 0; i < layout.nGlyphs(); i++) {
+ if (layout.getGlyphId(i) != kSpaceGlyphId || layout.getCharAdvance(i) != 0.0) {
+ count++;
+ }
+ }
+ return count;
+ }
+
// Returns true if the given string is exact one pair of regional indicators.
static bool isFlag(const jchar* str, size_t length) {
const jchar RI_LEAD_SURROGATE = 0xD83C;
@@ -831,7 +846,7 @@ namespace PaintGlue {
Layout layout;
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, str.get(), 0, str.size(),
str.size());
- size_t nGlyphs = layout.nGlyphs();
+ size_t nGlyphs = countNonSpaceGlyphs(layout);
if (nGlyphs != 1 && nChars > 1) {
// multiple-character input, and was not a ligature
// TODO: handle ZWJ/ZWNJ characters specially so we can detect certain ligatures
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index a56eba6c133f..46f76de87a2f 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -21,28 +21,34 @@
#include <inttypes.h>
#include <jni.h>
-#include <queue>
-#include <unordered_map>
+#include <mutex>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unordered_map>
+#include <queue>
#include <cutils/log.h>
#include "JNIHelp.h"
#include "core_jni_helpers.h"
-static constexpr int OS_APP_ID=-1;
+static constexpr int OS_APP_ID = -1;
+static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF);
+
+static constexpr int MIN_APP_ID = 1;
+static constexpr int MAX_APP_ID = 128;
-static constexpr int MIN_APP_ID=1;
-static constexpr int MAX_APP_ID=128;
+static constexpr size_t MSG_HEADER_SIZE = 4;
+static constexpr size_t HEADER_FIELD_MSG_TYPE = 0;
+static constexpr size_t HEADER_FIELD_MSG_VERSION = 1;
+static constexpr size_t HEADER_FIELD_HUB_HANDLE = 2;
+static constexpr size_t HEADER_FIELD_APP_INSTANCE = 3;
-static constexpr size_t MSG_HEADER_SIZE=4;
-static constexpr int HEADER_FIELD_MSG_TYPE=0;
-//static constexpr int HEADER_FIELD_MSG_VERSION=1;
-static constexpr int HEADER_FIELD_HUB_HANDLE=2;
-static constexpr int HEADER_FIELD_APP_INSTANCE=3;
+static constexpr size_t HEADER_FIELD_LOAD_APP_ID_LO = MSG_HEADER_SIZE;
+static constexpr size_t HEADER_FIELD_LOAD_APP_ID_HI = MSG_HEADER_SIZE + 1;
+static constexpr size_t MSG_HEADER_SIZE_LOAD_APP = MSG_HEADER_SIZE + 2;
namespace android {
@@ -83,6 +89,7 @@ struct jniInfo_s {
jmethodID contextHubServiceMsgReceiptCallback;
jmethodID contextHubServiceAddAppInstance;
+ jmethodID contextHubServiceDeleteAppInstance;
};
struct context_hub_info_s {
@@ -93,10 +100,53 @@ struct context_hub_info_s {
};
struct app_instance_info_s {
- uint32_t hubHandle; // Id of the hub this app is on
- int instanceId; // systemwide unique instance id - assigned
+ uint64_t truncName; // Possibly truncated name for logging
+ uint32_t hubHandle; // Id of the hub this app is on
+ int instanceId; // system wide unique instance id - assigned
struct hub_app_info appInfo; // returned from the HAL
- uint64_t truncName; // Possibly truncated name - logging
+};
+
+/*
+ * TODO(ashutoshj): From original code review:
+ *
+ * So, I feel like we could possible do a better job of organizing this code,
+ * and being more C++-y. Consider something like this:
+ * class TxnManager {
+ * public:
+ * TxnManager();
+ * ~TxnManager();
+ * int add(hub_message_e identifier, void *data);
+ * int close();
+ * bool isPending() const;
+ * int fetchData(hub_message_e *identifier, void **data) const;
+ *
+ * private:
+ * bool mPending;
+ * mutable std::mutex mLock;
+ * hub_message_e mIdentifier;
+ * void *mData;
+ * };
+ *
+ * And then, for example, we'd have things like:
+ * TxnManager::TxnManager() : mPending(false), mLock(), mIdentifier(), mData(nullptr) {}
+ * int TxnManager::add(hub_message_e identifier, void *data) {
+ * std::lock_guard<std::mutex> lock(mLock);
+ * mPending = true;
+ * mData = txnData;
+ * mIdentifier = txnIdentifier;
+ * return 0;
+ * }
+ * And then calling code would look like:
+ * if (!db.txnManager.add(CONTEXT_HUB_LOAD_APP, txnInfo)) {
+ *
+ * This would make it clearer the nothing is manipulating any state within TxnManager
+ * unsafely and outside of these couple of calls.
+ */
+struct txnManager_s {
+ bool txnPending; // Is a transaction pending
+ std::mutex m; // mutex for manager
+ hub_messages_e txnIdentifier; // What are we doing
+ void *txnData; // Details
};
struct contextHubServiceDb_s {
@@ -105,12 +155,69 @@ struct contextHubServiceDb_s {
jniInfo_s jniInfo;
std::queue<int> freeIds;
std::unordered_map<int, app_instance_info_s> appInstances;
+ txnManager_s txnManager;
};
} // unnamed namespace
static contextHubServiceDb_s db;
+static bool initTxnManager() {
+ txnManager_s *mgr = &db.txnManager;
+
+ mgr->txnData = nullptr;
+ mgr->txnPending = false;
+ return true;
+}
+
+static int addTxn(hub_messages_e txnIdentifier, void *txnData) {
+ txnManager_s *mgr = &db.txnManager;
+
+ std::lock_guard<std::mutex>lock(mgr->m);
+
+ mgr->txnPending = true;
+ mgr->txnData = txnData;
+ mgr->txnIdentifier = txnIdentifier;
+
+ return 0;
+}
+
+static int closeTxn() {
+ txnManager_s *mgr = &db.txnManager;
+ std::lock_guard<std::mutex>lock(mgr->m);
+ mgr->txnPending = false;
+ free(mgr->txnData);
+ mgr->txnData = nullptr;
+
+ return 0;
+}
+
+static bool isTxnPending() {
+ txnManager_s *mgr = &db.txnManager;
+ std::lock_guard<std::mutex>lock(mgr->m);
+ return mgr->txnPending;
+}
+
+static int fetchTxnData(hub_messages_e *id, void **data) {
+ txnManager_s *mgr = &db.txnManager;
+
+ if (!id || !data) {
+ ALOGW("Null params id %p, data %p", id, data);
+ return -1;
+ }
+
+ std::lock_guard<std::mutex>lock(mgr->m);
+ if (!mgr->txnPending) {
+ ALOGW("No Transactions pending");
+ return -1;
+ }
+
+ // else
+ *id = mgr->txnIdentifier;
+ *data = mgr->txnData;
+ return 0;
+}
+
int context_hub_callback(uint32_t hubId, const struct hub_message_t *msg,
void *cookie);
@@ -152,13 +259,21 @@ static int get_hub_id_for_hub_handle(int hubHandle) {
}
}
-static int get_hub_id_for_app_instance(int id) {
+static int get_hub_handle_for_app_instance(int id) {
if (!db.appInstances.count(id)) {
ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id);
return -1;
}
- int hubHandle = db.appInstances[id].hubHandle;
+ return db.appInstances[id].hubHandle;
+}
+
+static int get_hub_id_for_app_instance(int id) {
+ int hubHandle = get_hub_handle_for_app_instance(id);
+
+ if (hubHandle < 0) {
+ return -1;
+ }
return db.hubInfo.hubs[hubHandle].hub_id;
}
@@ -184,7 +299,7 @@ static int set_dest_app(hub_message_t *msg, int id) {
return 0;
}
-static void send_query_for_apps() {
+static void query_hub_for_apps(uint64_t appId, uint32_t hubHandle) {
hub_message_t msg;
query_apps_request_t queryMsg;
@@ -194,23 +309,31 @@ static void send_query_for_apps() {
msg.message_len = sizeof(queryMsg);
msg.message = &queryMsg;
+ ALOGD("Sending query for apps to hub %" PRIu32, hubHandle);
+ set_os_app_as_destination(&msg, hubHandle);
+ if (send_msg_to_hub(&msg, hubHandle) != 0) {
+ ALOGW("Could not query hub %" PRIu32 " for apps", hubHandle);
+ }
+}
+
+static void sendQueryForApps(uint64_t appId) {
for (int i = 0; i < db.hubInfo.numHubs; i++ ) {
- ALOGD("Sending query for apps to hub %d", i);
- set_os_app_as_destination(&msg, i);
- if (send_msg_to_hub(&msg, i) != 0) {
- ALOGW("Could not query hub %i for apps", i);
- }
+ query_hub_for_apps(appId, i);
}
}
static int return_id(int id) {
// Note : This method is not thread safe.
- // id returned is guarenteed to be in use
- db.freeIds.push(id);
- return 0;
+ // id returned is guaranteed to be in use
+ if (id >= 0) {
+ db.freeIds.push(id);
+ return 0;
+ }
+
+ return -1;
}
-static int generate_id(void) {
+static int generate_id() {
// Note : This method is not thread safe.
int retVal = -1;
@@ -222,23 +345,31 @@ static int generate_id(void) {
return retVal;
}
-int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, JNIEnv *env) {
+
+static int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle,
+ int appInstanceHandle, JNIEnv *env) {
+
+ ALOGI("Loading App");
+
// Not checking if the apps are indeed distinct
app_instance_info_s entry;
- int appInstanceHandle = generate_id();
-
assert(appInfo);
- if (appInstanceHandle < 0) {
- ALOGE("Cannot find resources to add app instance %d",
- appInstanceHandle);
- return -1;
+ if (db.appInstances.count(appInstanceHandle) == 0) {
+ appInstanceHandle = generate_id();
+ if (appInstanceHandle < 0) {
+ ALOGE("Cannot find resources to add app instance %d",
+ appInstanceHandle);
+ return -1;
+ }
}
entry.appInfo = *appInfo;
+
entry.instanceId = appInstanceHandle;
entry.truncName = appInfo->app_name.id;
entry.hubHandle = hubHandle;
+
db.appInstances[appInstanceHandle] = entry;
// Finally - let the service know of this app instance
@@ -254,17 +385,70 @@ int add_app_instance(const hub_app_info *appInfo, uint32_t hubHandle, JNIEnv *en
return appInstanceHandle;
}
-int delete_app_instance(int id) {
+int delete_app_instance(int id, JNIEnv *env) {
if (!db.appInstances.count(id)) {
+ ALOGW("Cannot find App id : %d", id);
return -1;
}
return_id(id);
db.appInstances.erase(id);
+ if (env->CallIntMethod(db.jniInfo.jContextHubService,
+ db.jniInfo.contextHubServiceDeleteAppInstance,
+ id) != 0) {
+ ALOGW("Could not delete App id : %d", id);
+ return -1;
+ }
+
+ ALOGI("Deleted App id : %d", id);
+
+ return 0;
+}
+
+static int startLoadAppTxn(uint64_t appId, int hubHandle) {
+ app_instance_info_s *txnInfo = (app_instance_info_s *)malloc(sizeof(app_instance_info_s));
+ int instanceId = generate_id();
+
+ if (!txnInfo || instanceId < 0) {
+ return_id(instanceId);
+ free(txnInfo);
+ return -1;
+ }
+
+ txnInfo->truncName = appId;
+ txnInfo->hubHandle = hubHandle;
+ txnInfo->instanceId = instanceId;
+
+ txnInfo->appInfo.app_name.id = appId;
+ txnInfo->appInfo.num_mem_ranges = 0;
+ txnInfo->appInfo.version = -1; // Awaited
+
+ if (!addTxn(CONTEXT_HUB_LOAD_APP, txnInfo)) {
+ return_id(instanceId);
+ free(txnInfo);
+ return -1;
+ }
return 0;
}
+static int startUnloadAppTxn(uint32_t appInstanceHandle) {
+ uint32_t *txnData = (uint32_t *) malloc(sizeof(uint32_t));
+ if (!txnData) {
+ ALOGW("Cannot allocate memory to start unload transaction");
+ return -1;
+ }
+
+ *txnData = appInstanceHandle;
+
+ if (addTxn(CONTEXT_HUB_UNLOAD_APP, txnData) != 0) {
+ free(txnData);
+ ALOGW("Cannot start transaction to unload app");
+ return -1;
+ }
+
+ return 0;
+}
static void initContextHubService() {
int err = 0;
@@ -285,6 +469,7 @@ static void initContextHubService() {
db.freeIds.push(i);
}
+ initTxnManager();
if (db.hubInfo.contextHubModule) {
int retNumHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule,
&db.hubInfo.hubs);
@@ -302,6 +487,7 @@ static void initContextHubService() {
for (i = 0; i < db.hubInfo.numHubs; i++) {
db.hubInfo.cookies[i] = db.hubInfo.hubs[i].hub_id;
+ ALOGI("Subscribing to hubHandle %d with OS App name %" PRIu64, i, db.hubInfo.hubs[i].os_app_name.id);
if (db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id,
context_hub_callback,
&db.hubInfo.cookies[i]) == 0) {
@@ -309,7 +495,7 @@ static void initContextHubService() {
}
}
- send_query_for_apps();
+ sendQueryForApps(ALL_APPS);
} else {
ALOGW("No Context Hub Module present");
}
@@ -346,7 +532,8 @@ static int onMessageReceipt(uint32_t *header, size_t headerLen, char *msg, size_
return ret;
}
-int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) {
+int handle_query_apps_response(const uint8_t *msg, int msgLen,
+ uint32_t hubHandle) {
JNIEnv *env;
if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
return -1;
@@ -354,53 +541,201 @@ int handle_query_apps_response(char *msg, int msgLen, uint32_t hubHandle) {
int numApps = msgLen/sizeof(hub_app_info);
hub_app_info info;
- hub_app_info *unalignedInfoAddr = (hub_app_info*)msg;
+ const hub_app_info *unalignedInfoAddr = (const hub_app_info*)msg;
for (int i = 0; i < numApps; i++, unalignedInfoAddr++) {
memcpy(&info, unalignedInfoAddr, sizeof(info));
- add_app_instance(&info, hubHandle, env);
+ // We will only have one instance of the app
+ // TODO : Change this logic once we support multiple instances of the same app
+ int appInstance = get_app_instance_for_app_id(info.app_name.id);
+ add_app_instance(&info, hubHandle, appInstance, env);
}
return 0;
}
+static void passOnOsResponse(uint32_t hubHandle, uint32_t msgType,
+ status_response_t *rsp, int8_t *additionalData,
+ size_t additionalDataLen) {
+ JNIEnv *env;
-int handle_os_message(uint32_t msgType, uint32_t hubHandle,
- char *msg, int msgLen) {
- int retVal;
+ if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
+ ALOGW("Cannot latch to JNI env, dropping OS response %" PRIu32, msgType);
+ return;
+ }
- //ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
- // hubHandle, msgType, msgLen);
+ uint32_t header[MSG_HEADER_SIZE];
+ memset(header, 0, sizeof(header));
- switch(msgType) {
- case CONTEXT_HUB_APPS_ENABLE:
- retVal = 0;
- break;
+ if (!additionalData) {
+ additionalDataLen = 0; // clamp
+ }
+ int msgLen = 1 + additionalDataLen;
- case CONTEXT_HUB_APPS_DISABLE:
- retVal = 0;
- break;
+ int8_t *msg = new int8_t[msgLen];
- case CONTEXT_HUB_LOAD_APP:
- retVal = 0;
- break;
+ if (!msg) {
+ ALOGW("Unexpected : Ran out of memory, cannot send response");
+ return;
+ }
+
+ header[HEADER_FIELD_MSG_TYPE] = msgType;
+ header[HEADER_FIELD_MSG_VERSION] = 0;
+ header[HEADER_FIELD_HUB_HANDLE] = hubHandle;
+ header[HEADER_FIELD_APP_INSTANCE] = OS_APP_ID;
+
+ msg[0] = rsp->result;
+
+ if (additionalData) {
+ memcpy(&msg[1], additionalData, additionalDataLen);
+ }
+
+ jbyteArray jmsg = env->NewByteArray(msgLen);
+ jintArray jheader = env->NewIntArray(sizeof(header));
+
+ env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg);
+ env->SetIntArrayRegion(jheader, 0, sizeof(header), (jint *)header);
+
+ ALOGI("Passing msg type %" PRIu32 " from app %" PRIu32 " from hub %" PRIu32,
+ header[HEADER_FIELD_MSG_TYPE], header[HEADER_FIELD_APP_INSTANCE],
+ header[HEADER_FIELD_HUB_HANDLE]);
+
+ env->CallIntMethod(db.jniInfo.jContextHubService,
+ db.jniInfo.contextHubServiceMsgReceiptCallback,
+ jheader, jmsg);
+
+ delete[] msg;
+}
+
+void closeUnloadTxn(bool success) {
+ void *txnData = nullptr;
+ hub_messages_e txnId;
+
+ if (success && fetchTxnData(&txnId, &txnData) == 0 &&
+ txnId == CONTEXT_HUB_UNLOAD_APP) {
+ db.appInstances.erase(*(uint32_t *)txnData);
+ } else {
+ ALOGW("Could not unload the app successfully ! success %d, txnData %p", success, txnData);
+ }
+
+ closeTxn();
+}
+
+void closeLoadTxn(bool success, int *appInstanceHandle) {
+ void *txnData;
+ hub_messages_e txnId;
+
+ if (success && fetchTxnData(&txnId, &txnData) == 0 &&
+ txnId == CONTEXT_HUB_LOAD_APP) {
+ app_instance_info_s *info = (app_instance_info_s *)txnData;
+ *appInstanceHandle = info->instanceId;
+
+ JNIEnv *env;
+ if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) == JNI_OK) {
+ add_app_instance(&info->appInfo, info->hubHandle, info->instanceId, env);
+ } else {
+ ALOGW("Could not attach to JVM !");
+ }
+ sendQueryForApps(info->appInfo.app_name.id);
+ } else {
+ ALOGW("Could not load the app successfully ! Unexpected failure");
+ }
+
+ closeTxn();
+}
+
+static bool isValidOsStatus(const uint8_t *msg, size_t msgLen,
+ status_response_t *rsp) {
+ // Workaround a bug in some HALs
+ if (msgLen == 1) {
+ rsp->result = msg[0];
+ return true;
+ }
+
+ if (!msg || msgLen != sizeof(*rsp)) {
+ ALOGW("Received invalid response %p of size %zu", msg, msgLen);
+ return false;
+ }
+
+ memcpy(rsp, msg, sizeof(*rsp));
+
+ // No sanity checks on return values
+ return true;
+}
+
+static void invalidateNanoApps(uint32_t hubHandle) {
+ JNIEnv *env;
+
+ if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
+ ALOGW("Could not attach to JVM !");
+ }
+
+ auto end = db.appInstances.end();
+ for (auto current = db.appInstances.begin(); current != end; ) {
+ app_instance_info_s info = current->second;
+ current++;
+ if (info.hubHandle == hubHandle) {
+ delete_app_instance(info.instanceId, env);
+ }
+ }
+}
- case CONTEXT_HUB_UNLOAD_APP:
- retVal = 0;
- break;
+static int handle_os_message(uint32_t msgType, uint32_t hubHandle,
+ const uint8_t *msg, int msgLen) {
+ int retVal = -1;
- case CONTEXT_HUB_QUERY_APPS:
- retVal = handle_query_apps_response(msg, msgLen, hubHandle);
- break;
+ ALOGD("Rcd OS message from hubHandle %" PRIu32 " type %" PRIu32 " length %d",
+ hubHandle, msgType, msgLen);
- case CONTEXT_HUB_QUERY_MEMORY:
- retVal = 0;
- break;
+ struct status_response_t rsp;
- default:
- retVal = -1;
- break;
+ switch(msgType) {
+ case CONTEXT_HUB_APPS_ENABLE:
+ case CONTEXT_HUB_APPS_DISABLE:
+ case CONTEXT_HUB_LOAD_APP:
+ case CONTEXT_HUB_UNLOAD_APP:
+ if (isValidOsStatus(msg, msgLen, &rsp)) {
+ if (msgType == CONTEXT_HUB_LOAD_APP) {
+ int appInstanceHandle;
+ closeLoadTxn(rsp.result == 0, &appInstanceHandle);
+ passOnOsResponse(hubHandle, msgType, &rsp, (int8_t *)(&appInstanceHandle),
+ sizeof(appInstanceHandle));
+ } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
+ closeUnloadTxn(rsp.result == 0);
+ passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
+ } else {
+ passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
+ }
+ retVal = 0;
+ }
+ break;
+
+ case CONTEXT_HUB_QUERY_APPS:
+ rsp.result = 0;
+ retVal = handle_query_apps_response(msg, msgLen, hubHandle);
+ passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
+ break;
+
+ case CONTEXT_HUB_QUERY_MEMORY:
+ // Deferring this use
+ retVal = 0;
+ break;
+
+ case CONTEXT_HUB_OS_REBOOT:
+ if (isValidOsStatus(msg, msgLen, &rsp)) {
+ rsp.result = 0;
+ ALOGW("Context Hub handle %d restarted", hubHandle);
+ passOnOsResponse(hubHandle, msgType, &rsp, nullptr, 0);
+ invalidateNanoApps(hubHandle);
+ query_hub_for_apps(ALL_APPS, hubHandle);
+ retVal = 0;
+ }
+ break;
+
+ default:
+ retVal = -1;
+ break;
}
return retVal;
@@ -420,10 +755,12 @@ static bool sanity_check_cookie(void *cookie, uint32_t hub_id) {
}
}
+
int context_hub_callback(uint32_t hubId,
const struct hub_message_t *msg,
void *cookie) {
if (!msg) {
+ ALOGW("NULL message");
return -1;
}
if (!sanity_check_cookie(cookie, hubId)) {
@@ -433,11 +770,12 @@ int context_hub_callback(uint32_t hubId,
return -1;
}
+
uint32_t messageType = msg->message_type;
uint32_t hubHandle = *(uint32_t*) cookie;
if (messageType < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) {
- handle_os_message(messageType, hubHandle, (char*) msg->message, msg->message_len);
+ handle_os_message(messageType, hubHandle, (uint8_t*) msg->message, msg->message_len);
} else {
int appHandle = get_app_instance_for_app_id(msg->app_name.id);
if (appHandle < 0) {
@@ -528,7 +866,9 @@ static int init_jni(JNIEnv *env, jobject instance) {
env->GetMethodID(db.jniInfo.contextHubServiceClass,
"addAppInstance", "(IIJI)I");
-
+ db.jniInfo.contextHubServiceDeleteAppInstance =
+ env->GetMethodID(db.jniInfo.contextHubServiceClass,
+ "deleteAppInstance", "(I)I");
return 0;
}
@@ -538,8 +878,6 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
jintArray jintBuf;
jobjectArray jmemBuf;
- int dummyConnectedSensors[] = {1, 2, 3, 4, 5};
-
jobject jHub = env->NewObject(db.jniInfo.contextHubInfoClass,
db.jniInfo.contextHubInfoCtor);
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub->hub_id);
@@ -569,11 +907,21 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
hub->max_supported_msg_len);
- // TODO : jintBuf = env->NewIntArray(hub->num_connected_sensors);
- // TODO : env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors,
- // hub->connected_sensors);
- jintBuf = env->NewIntArray(array_length(dummyConnectedSensors));
- env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, dummyConnectedSensors);
+ jintBuf = env->NewIntArray(hub->num_connected_sensors);
+ int *connectedSensors = new int[hub->num_connected_sensors];
+
+ if (!connectedSensors) {
+ ALOGW("Cannot allocate memory! Unexpected");
+ assert(false);
+ } else {
+ for (unsigned int i = 0; i < hub->num_connected_sensors; i++) {
+ connectedSensors[i] = hub->connected_sensors[i].sensor_id;
+ }
+ }
+
+ env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors,
+ connectedSensors);
+
env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSupportedSensors, jintBuf);
env->DeleteLocalRef(jintBuf);
@@ -584,6 +932,7 @@ static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t
env->DeleteLocalRef(jmemBuf);
+ delete[] connectedSensors;
return jHub;
}
@@ -622,33 +971,96 @@ static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_,
jbyte *data = env->GetByteArrayElements(data_, 0);
int dataBufferLength = env->GetArrayLength(data_);
+ if (numHeaderElements < MSG_HEADER_SIZE) {
+ ALOGW("Malformed header len");
+ return -1;
+ }
+
+ uint32_t appInstanceHandle = header[HEADER_FIELD_APP_INSTANCE];
+ uint32_t msgType = header[HEADER_FIELD_MSG_TYPE];
+ int hubHandle = -1;
+ int hubId;
+ uint64_t appId;
+
+ if (msgType == CONTEXT_HUB_UNLOAD_APP) {
+ hubHandle = get_hub_handle_for_app_instance(appInstanceHandle);
+ } else if (msgType == CONTEXT_HUB_LOAD_APP) {
+ if (numHeaderElements < MSG_HEADER_SIZE_LOAD_APP) {
+ return -1;
+ }
+ uint64_t appIdLo = header[HEADER_FIELD_LOAD_APP_ID_LO];
+ uint64_t appIdHi = header[HEADER_FIELD_LOAD_APP_ID_HI];
+ appId = appIdHi << 32 | appIdLo;
+
+ hubHandle = header[HEADER_FIELD_HUB_HANDLE];
+ } else {
+ hubHandle = header[HEADER_FIELD_HUB_HANDLE];
+ }
+
+ if (hubHandle < 0) {
+ ALOGD("Invalid hub Handle %d", hubHandle);
+ return -1;
+ }
+
+ if (msgType == CONTEXT_HUB_LOAD_APP ||
+ msgType == CONTEXT_HUB_UNLOAD_APP) {
+
+ if (isTxnPending()) {
+ ALOGW("Cannot load or unload app while a transaction is pending !");
+ return -1;
+ }
- if (numHeaderElements >= MSG_HEADER_SIZE) {
- bool setAddressSuccess;
- int hubId;
- hub_message_t msg;
+ if (msgType == CONTEXT_HUB_LOAD_APP) {
+ if (startLoadAppTxn(appId, hubHandle) != 0) {
+ return -1;
+ }
+ } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
+ if (startUnloadAppTxn(appInstanceHandle) != 0) {
+ return -1;
+ }
+ }
+ }
+
+ bool setAddressSuccess = false;
+ hub_message_t msg;
+
+ msg.message_type = msgType;
+
+ if (msgType == CONTEXT_HUB_UNLOAD_APP) {
+ msg.message_len = sizeof(db.appInstances[appInstanceHandle].appInfo.app_name);
+ msg.message = &db.appInstances[appInstanceHandle].appInfo.app_name;
+ setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0);
+ hubId = get_hub_id_for_hub_handle(hubHandle);
+ } else {
+ msg.message_len = dataBufferLength;
+ msg.message = data;
if (header[HEADER_FIELD_APP_INSTANCE] == OS_APP_ID) {
- setAddressSuccess = (set_os_app_as_destination(&msg, header[HEADER_FIELD_HUB_HANDLE]) == 0);
- hubId = get_hub_id_for_hub_handle(header[HEADER_FIELD_HUB_HANDLE]);
+ setAddressSuccess = (set_os_app_as_destination(&msg, hubHandle) == 0);
+ hubId = get_hub_id_for_hub_handle(hubHandle);
} else {
setAddressSuccess = (set_dest_app(&msg, header[HEADER_FIELD_APP_INSTANCE]) == 0);
hubId = get_hub_id_for_app_instance(header[HEADER_FIELD_APP_INSTANCE]);
}
+ }
- if (setAddressSuccess && hubId >= 0) {
- msg.message_type = header[HEADER_FIELD_MSG_TYPE];
- msg.message_len = dataBufferLength;
- msg.message = data;
- retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
- } else {
- ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d",
- header[HEADER_FIELD_APP_INSTANCE],
- header[HEADER_FIELD_HUB_HANDLE],
- (int)setAddressSuccess);
- }
+ if (setAddressSuccess && hubId >= 0) {
+ ALOGD("Asking HAL to remove app");
+ retVal = db.hubInfo.contextHubModule->send_message(hubId, &msg);
} else {
- ALOGD("Malformed header len");
+ ALOGD("Could not find app instance %d on hubHandle %d, setAddress %d",
+ header[HEADER_FIELD_APP_INSTANCE],
+ header[HEADER_FIELD_HUB_HANDLE],
+ (int)setAddressSuccess);
+ }
+
+ if (retVal != 0) {
+ ALOGD("Send Message failure - %d", retVal);
+ if (msgType == CONTEXT_HUB_LOAD_APP) {
+ closeLoadTxn(false, nullptr);
+ } else if (msgType == CONTEXT_HUB_UNLOAD_APP) {
+ closeUnloadTxn(false);
+ }
}
env->ReleaseIntArrayElements(header_, header, 0);
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index 651330446382..092aaf62bbc0 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -20,18 +20,20 @@
#include <system/audio.h>
// keep these values in sync with AudioFormat.java
-#define ENCODING_PCM_16BIT 2
-#define ENCODING_PCM_8BIT 3
-#define ENCODING_PCM_FLOAT 4
-#define ENCODING_AC3 5
-#define ENCODING_E_AC3 6
-#define ENCODING_DTS 7
-#define ENCODING_DTS_HD 8
-#define ENCODING_MP3 9
-#define ENCODING_AAC_LC 10
-#define ENCODING_AAC_HE_V1 11
-#define ENCODING_AAC_HE_V2 12
-#define ENCODING_IEC61937 13
+#define ENCODING_PCM_16BIT 2
+#define ENCODING_PCM_8BIT 3
+#define ENCODING_PCM_FLOAT 4
+#define ENCODING_AC3 5
+#define ENCODING_E_AC3 6
+#define ENCODING_DTS 7
+#define ENCODING_DTS_HD 8
+#define ENCODING_MP3 9
+#define ENCODING_AAC_LC 10
+#define ENCODING_AAC_HE_V1 11
+#define ENCODING_AAC_HE_V2 12
+#define ENCODING_IEC61937 13
+#define ENCODING_DOLBY_TRUEHD 14
+
#define ENCODING_INVALID 0
#define ENCODING_DEFAULT 1
@@ -65,6 +67,8 @@ static inline audio_format_t audioFormatToNative(int audioFormat)
return AUDIO_FORMAT_AAC_HE_V1;
case ENCODING_AAC_HE_V2:
return AUDIO_FORMAT_AAC_HE_V2;
+ case ENCODING_DOLBY_TRUEHD:
+ return AUDIO_FORMAT_DOLBY_TRUEHD;
case ENCODING_IEC61937:
return AUDIO_FORMAT_IEC61937;
case ENCODING_DEFAULT:
@@ -108,6 +112,8 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat)
return ENCODING_AAC_HE_V2;
case AUDIO_FORMAT_IEC61937:
return ENCODING_IEC61937;
+ case AUDIO_FORMAT_DOLBY_TRUEHD:
+ return ENCODING_DOLBY_TRUEHD;
case AUDIO_FORMAT_DEFAULT:
return ENCODING_DEFAULT;
default:
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 23647871df87..679e88299992 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -125,6 +125,99 @@ static void android_net_utils_attachRaFilter(JNIEnv *env, jobject clazz, jobject
}
}
+static void android_net_utils_setupRaSocket(JNIEnv *env, jobject clazz, jobject javaFd,
+ jint ifIndex)
+{
+ static const int kLinkLocalHopLimit = 255;
+
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+
+ // Set an ICMPv6 filter that only passes Router Solicitations.
+ struct icmp6_filter rs_only;
+ ICMP6_FILTER_SETBLOCKALL(&rs_only);
+ ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &rs_only);
+ socklen_t len = sizeof(rs_only);
+ if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &rs_only, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(ICMP6_FILTER): %s", strerror(errno));
+ return;
+ }
+
+ // Most/all of the rest of these options can be set via Java code, but
+ // because we're here on account of setting an icmp6_filter go ahead
+ // and do it all natively for now.
+ //
+ // TODO: Consider moving these out to Java.
+
+ // Set the multicast hoplimit to 255 (link-local only).
+ int hops = kLinkLocalHopLimit;
+ len = sizeof(hops);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_MULTICAST_HOPS): %s", strerror(errno));
+ return;
+ }
+
+ // Set the unicast hoplimit to 255 (link-local only).
+ hops = kLinkLocalHopLimit;
+ len = sizeof(hops);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_UNICAST_HOPS): %s", strerror(errno));
+ return;
+ }
+
+ // Explicitly disable multicast loopback.
+ int off = 0;
+ len = sizeof(off);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_MULTICAST_LOOP): %s", strerror(errno));
+ return;
+ }
+
+ // Specify the IPv6 interface to use for outbound multicast.
+ len = sizeof(ifIndex);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifIndex, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_MULTICAST_IF): %s", strerror(errno));
+ return;
+ }
+
+ // Additional options to be considered:
+ // - IPV6_TCLASS
+ // - IPV6_RECVPKTINFO
+ // - IPV6_RECVHOPLIMIT
+
+ // Bind to [::].
+ const struct sockaddr_in6 sin6 = {
+ .sin6_family = AF_INET6,
+ .sin6_port = 0,
+ .sin6_flowinfo = 0,
+ .sin6_addr = IN6ADDR_ANY_INIT,
+ .sin6_scope_id = 0,
+ };
+ auto sa = reinterpret_cast<const struct sockaddr *>(&sin6);
+ len = sizeof(sin6);
+ if (bind(fd, sa, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "bind(IN6ADDR_ANY): %s", strerror(errno));
+ return;
+ }
+
+ // Join the all-routers multicast group, ff02::2%index.
+ struct ipv6_mreq all_rtrs = {
+ .ipv6mr_multiaddr = {{{0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2}}},
+ .ipv6mr_interface = ifIndex,
+ };
+ len = sizeof(all_rtrs);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &all_rtrs, len) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(IPV6_JOIN_GROUP): %s", strerror(errno));
+ return;
+ }
+}
+
static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId)
{
return (jboolean) !setNetworkForProcess(netId);
@@ -173,6 +266,7 @@ static const JNINativeMethod gNetworkUtilMethods[] = {
{ "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
{ "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
{ "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
+ { "setupRaSocket", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_setupRaSocket },
};
int register_android_net_NetworkUtils(JNIEnv* env)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3c71dd9312a5..8388f05fd131 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -478,7 +478,7 @@
<protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNAVAILABLE" />
<protected-broadcast android:name="com.android.server.pm.DISABLE_QUIET_MODE_AFTER_UNLOCK" />
- <protected-broadcast android:name="com.android.server.am.ACTION_RESET_DEMO" />
+ <protected-broadcast android:name="com.android.server.retaildemo.ACTION_RESET_DEMO" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
diff --git a/core/res/res/layout-watch/preference_material.xml b/core/res/res/layout-watch/preference_material.xml
index 5da64fcc4310..ad217dbbace9 100644
--- a/core/res/res/layout-watch/preference_material.xml
+++ b/core/res/res/layout-watch/preference_material.xml
@@ -29,34 +29,42 @@
<LinearLayout
android:id="@+id/icon_frame"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginStart="-4dp"
- android:minWidth="32dp"
- android:gravity="start|center_vertical"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:gravity="center"
android:orientation="horizontal"
- android:paddingEnd="8dp"
- android:paddingTop="4dp"
- android:paddingBottom="4dp">
+ android:layout_marginEnd="8dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp">
<com.android.internal.widget.PreferenceImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:maxWidth="24dp"
- android:maxHeight="24dp" />
+ android:maxWidth="40dp"
+ android:maxHeight="40dp" />
</LinearLayout>
+ <!-- Preference should place its actual preference widget here. -->
+ <LinearLayout android:id="@+id/widget_frame"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:gravity="center"
+ android:orientation="horizontal"
+ android:layout_marginEnd="8dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp" />
+
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:paddingTop="16dp"
- android:paddingBottom="16dp">
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp">
<TextView android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:maxLines="2"
+ android:maxLines="3"
android:textAppearance="?attr/textAppearanceListItem"
android:ellipsize="end" />
@@ -70,13 +78,4 @@
android:maxLines="10" />
</RelativeLayout>
-
- <!-- Preference should place its actual preference widget here. -->
- <LinearLayout android:id="@+id/widget_frame"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="end|center_vertical"
- android:paddingStart="4dp"
- android:orientation="vertical" />
-
</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 6eabd528a658..d5c1dd89c71e 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimeer tans berging."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android gradeer tans op"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Sommige programme sal dalk nie behoorlik werk voordat die opgradering voltooi is nie"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimeer program <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Berei tans <xliff:g id="APPNAME">%1$s</xliff:g> voor."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Begin programme."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index e3cae6a4aa5f..a90d0564a692 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"ማከማቻን በማመቻቸት ላይá¢"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android በማላቅ ላይ áŠá‹"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"አንዳንድ መተáŒá‰ áˆªá‹«á‹Žá‰½ ማላበእስኪጠናቀቅ ድረስ በአáŒá‰£á‰¡ ላይሰሩ ይችላሉ"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"መተáŒá‰ áˆªá‹«á‹Žá‰½ በአáŒá‰£á‰¡ በመጠቀሠላይ <xliff:g id="NUMBER_0">%1$d</xliff:g> ከ <xliff:g id="NUMBER_1">%2$d</xliff:g> á¡á¡"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>ን ማዘጋጀትá¢"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"መተáŒá‰ áˆªá‹«á‹Žá‰½áŠ• በማስጀመር ላይá¡á¡"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 1778e0cb032a..10cb7c5fa75d 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1116,6 +1116,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"جار٠تحسين السعة التخزينية."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"â€Ø¬Ø§Ø±Ù ترقية Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"قد لا تعمل بعض التطبيقات بشكل مناسب إلا بعد انتهاء الترقية"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"جار٠تحسين التطبيق <xliff:g id="NUMBER_0">%1$d</xliff:g> من <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"جار٠تحضير <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"بدء التطبيقات."</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index a1e851bb530e..53a238b54280 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Yaddaş optimallaşdırılır."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android təkmilləşdirilir"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Güncəllənmə tamamlanana kimi bəzi tətbiqlər düzgün işləməyə bilər"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> əddədən <xliff:g id="NUMBER_0">%1$d</xliff:g> tətbiq optimallaşır."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> proqramının hazırlanması."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Tətbiqlər başladılır."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 17dfef1e4c30..54c471004209 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Хранилището Ñе оптимизира."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android Ñе надÑтройва"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"ÐÑкои Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶Ðµ да не работÑÑ‚ правилно, докато надÑтройването не завърши"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Оптимизира Ñе приложение <xliff:g id="NUMBER_0">%1$d</xliff:g> от <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> Ñе подготвÑ."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"ПриложениÑта Ñе Ñтартират."</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 8435f96c5321..292fefd42e44 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"সঞà§à¦šà¦¯à¦¼à¦¸à§à¦¥à¦¾à¦¨ অপà§à¦Ÿà¦¿à¦®à¦¾à¦‡à¦œ করা হচà§à¦›à§‡à§·"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android আপগà§à¦°à§‡à¦¡ করা হচà§à¦›à§‡"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"আপগà§à¦°à§‡à¦¡ সমà§à¦ªà¦¨à§à¦¨ না হওয়া পরà§à¦¯à¦¨à§à¦¤ কিছৠঅà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•েশান সঠিকভাবে কাজ নাও করতে পারে"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>টির মধà§à¦¯à§‡ <xliff:g id="NUMBER_0">%1$d</xliff:g>টি অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•েশান অপà§à¦Ÿà¦¿à¦®à¦¾à¦‡à¦œ করা হচà§à¦›à§‡à§·"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> পà§à¦°à¦¸à§à¦¤à§à¦¤ করা হচà§à¦›à§‡à§·"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"অà§à¦¯à¦¾à¦ªà§à¦²à¦¿à¦•েশানগà§à¦²à¦¿ শà§à¦°à§ করা হচà§à¦›à§‡à§·"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 59f7d956614a..789006818a31 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"S\'està optimitzant l\'emmagatzematge."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android s\'està actualitzant"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Pot ser que algunes aplicacions no funcionin correctament fins que no es completi l\'actualització"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"S\'està optimitzant l\'aplicació <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"S\'està preparant <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"S\'estan iniciant les aplicacions."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 1eb497f91027..f5e74ce47e7b 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1070,6 +1070,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Probíhá optimalizace úložiště."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android se upgraduje"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"PÅ™ed dokonÄením upgradu nemusí nÄ›které aplikace fungovat správnÄ›"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimalizování aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Příprava aplikace <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Spouštění aplikací."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f5b7788fdad4..446c950cb66b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Lageret optimeres."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android opgraderes"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Nogle apps fungerer muligvis ikke korrekt, før opgraderingen er gennemført"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimerer app <xliff:g id="NUMBER_0">%1$d</xliff:g> ud af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Forbereder <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Ã…bner dine apps."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 1345f7676185..25f3912a2087 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Speicher wird optimiert"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android wird aktualisiert"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Einige Apps funktionieren unter Umständen nicht richtig, bis das Upgrade abgeschlossen ist"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> von <xliff:g id="NUMBER_1">%2$d</xliff:g> wird optimiert..."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> wird vorbereitet"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Apps werden gestartet..."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 8434fffcf3a3..3e220da2df44 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Βελτιστοποίηση Î±Ï€Î¿Î¸Î·ÎºÎµÏ…Ï„Î¹ÎºÎ¿Ï Ï‡ÏŽÏου."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Το Android αναβαθμίζεται"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"ΟÏισμένες εφαÏμογές ενδέχεται να μην λειτουÏγοÏν σωστά μέχÏι την ολοκλήÏωση της αναβάθμισης"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Βελτιστοποίηση της εφαÏμογής <xliff:g id="NUMBER_0">%1$d</xliff:g> από <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"ΠÏοετοιμασία <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"ΈναÏξη εφαÏμογών."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 6c693bc2bb25..60e9e86c576a 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimising storage."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android is upgrading"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Some apps may not work properly until the upgrade finishes"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starting apps."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 6c693bc2bb25..60e9e86c576a 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimising storage."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android is upgrading"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Some apps may not work properly until the upgrade finishes"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starting apps."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 6c693bc2bb25..60e9e86c576a 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimising storage."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android is upgrading"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Some apps may not work properly until the upgrade finishes"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimising app <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Preparing <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starting apps."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index fcfc752b2485..c5dc2109a161 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizando almacenamiento"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android se está actualizando"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Es posible que algunas apps no funcionen correctamente hasta que termine la actualización"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizando la aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando aplicaciones"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 21b4af37d751..9e1859bc4df8 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizando almacenamiento."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Actualizando Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Es posible que algunas aplicaciones no funcionen correctamente hasta que finalice la actualización"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>..."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando aplicaciones"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index e96c93fcfabb..aa1a25216c4d 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1024,6 +1024,7 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Salvestusruumi optimeerimine."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android viiakse üle uuemale versioonile"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Mõned rakendused ei pruugi enne uuemale versioonile ülemineku lõpetamist korralikult töötada"</string>
+ <string name="app_upgrading_toast" msgid="3008139776215597053">"Rakenduse <xliff:g id="APPLICATION">%1$s</xliff:g> versiooni uuendatakse …"</string>
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. rakenduse <xliff:g id="NUMBER_1">%2$d</xliff:g>-st optimeerimine."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Rakenduse <xliff:g id="APPNAME">%1$s</xliff:g> ettevalmistamine."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Rakenduste käivitamine."</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 49ee82fecce1..70ee2833719c 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Memoria optimizatzen."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android bertsioa berritzen ari gara"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Aplikazio batzuek agian ez dute behar bezala funtzionatuko bertsioa berritzen amaitu arte"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> aplikazio optimizatzen."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> prestatzen."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Aplikazioak abiarazten."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 71bdc2e5d5e5..aa9c1484b4b2 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -937,7 +937,7 @@
<string name="selectAll" msgid="6876518925844129331">"انتخاب همه"</string>
<string name="cut" msgid="3092569408438626261">"برش"</string>
<string name="copy" msgid="2681946229533511987">"کپی"</string>
- <string name="paste" msgid="5629880836805036433">"جای گذاری"</string>
+ <string name="paste" msgid="5629880836805036433">"جای‌گذاری"</string>
<string name="paste_as_plain_text" msgid="5427792741908010675">"جای‌گذاری به عنوان متن ساده"</string>
<string name="replace" msgid="5781686059063148930">"جایگزین شود..."</string>
<string name="delete" msgid="6098684844021697789">"حذÙ"</string>
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"بهینه‌سازی ÙØ¶Ø§ÛŒ ذخیره‌سازی."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"â€Android درحال ارتقا است"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"تا پایان ارتقا، ممکن است برخی از برنامه‌ها به‌درستی کار نکنند."</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"در حال بهینه‌سازی برنامهٔ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"آماده‌سازی <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"در حال آغاز برنامه‌ها."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 62c148e0abdb..1aca741afdc4 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimoidaan tallennustilaa."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Androidia päivitetään"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Kaikki sovellukset eivät ehkä toimi oikein, ennen kuin päivitys on valmis."</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimoidaan sovellusta <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Valmistellaan: <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Käynnistetään sovelluksia."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 2df36800e8e5..7b194a09ead6 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimisation du stockage."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Installation de la m. à niveau d\'Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Il se peut que certaines applications ne fonctionnent pas correctement jusqu\'à ce que la mise à niveau soit terminée"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimisation de l\'application <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>…"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Préparation de <xliff:g id="APPNAME">%1$s</xliff:g> en cours…"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Lancement des applications…"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 90def0d0e44d..ff0876e24b76 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimisation du stockage en cours…"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Mise à jour d\'Android…"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Certaines applications peuvent ne pas fonctionner correctement jusqu\'à ce que la mise à jour soit terminée."</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimisation de l\'application <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>…"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Préparation de <xliff:g id="APPNAME">%1$s</xliff:g> en cours…"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Lancement des applications…"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 85be7f3ac207..abe09ded063d 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizando almacenamento."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Estase actualizando Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"É posible que algunhas aplicacións non funcionen correctamente ata que finalice o proceso de actualización"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizando aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando aplicacións."</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index e611f307b447..1589426d4412 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"સંગà«àª°àª¹ ઓપà«àªŸàª¿àª®àª¾àª‡àª કરી રહà«àª¯à«àª‚ છે."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android અપગà«àª°à«‡àª¡ થઈ રહà«àª¯à«àª‚ છે"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"અપગà«àª°à«‡àª¡ સમાપà«àª¤ ન થાય તà«àª¯àª¾àª‚ સà«àª§à«€ કેટલીક àªàªªà«àª²àª¿àª•ેશનો કદાચ યોગà«àª¯ રીતે કામ ન કરે"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> માંથી <xliff:g id="NUMBER_0">%1$d</xliff:g> àªàªªà«àª²àª¿àª•ેશન ઓપà«àªŸàª¿àª®àª¾àª‡àª કરી રહà«àª¯à«àª‚ છે."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> તૈયાર કરી રહà«àª¯à«àª‚ છે."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"àªàªªà«àª²àª¿àª•ેશનો શરૂ કરી રહà«àª¯àª¾àª‚ છે."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 76bc028e7194..7a81b476863f 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"मेमोरी ऑपà¥â€à¤Ÿà¤¿à¤®à¤¾à¤‡à¤œà¤¼ हो रही है."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android अपगà¥à¤°à¥‡à¤¡ हो रहा है"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"जब तक अपगà¥à¤°à¥‡à¤¡ पूरा नहीं हो जाता, तब तक संभव है कि कà¥à¤› à¤à¤ªà¥à¤²à¤¿à¤•ेशन ठीक से कारà¥à¤¯ ना करें"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> में से <xliff:g id="NUMBER_0">%1$d</xliff:g> à¤à¤ªà¥à¤¸ अनà¥à¤•ूलित हो रहा है."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> तैयार हो रहा है."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"à¤à¤ªà¥à¤¸ पà¥à¤°à¤¾à¤°à¤‚भ होने वाले हैं"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 461888a1f60f..9ff8363156c9 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1047,6 +1047,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimiziranje pohrane."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android se nadograđuje"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Neke aplikacije možda neće funkcionirati pravilno dok nadogradnja ne završi"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimiziranje aplikacije <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Pripremanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Pokretanje aplikacija."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 920fc39ed402..ce4bef5a5b84 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1024,6 +1024,7 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Tárhely-optimalizálás."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android frissítése folyamatban"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"A frissítés befejezéséig előfordulhat, hogy egyes alkalmazások nem megfelelően működnek."</string>
+ <string name="app_upgrading_toast" msgid="3008139776215597053">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> frissítése folyamatban van"</string>
<string name="android_upgrading_apk" msgid="7904042682111526169">"Alkalmazás optimalizálása: <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"A(z) <xliff:g id="APPNAME">%1$s</xliff:g> előkészítése."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Kezdő alkalmazások."</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 2f6efcb76dc9..76bc42e8c405 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"ÕŠÕ¡Õ°Õ¥Õ½Õ¿Õ« Ö…ÕºÕ¿Õ«Õ´Õ¡Õ¬Õ¡ÖÕ¸Ö‚Õ´:"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android-Õ¨ Õ¶Õ¸Ö€Õ¡ÖÕ¾Õ¸Ö‚Õ´ Õ§"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Õ€Õ¶Õ¡Ö€Õ¡Õ¾Õ¸Ö€ Õ§Õ Õ¸Ö€Õ¸Õ· Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¶Õ¥Ö€ Õ´Õ«Õ¶Õ¹Ö‡ Õ¶Õ¸Ö€Õ¡ÖÕ´Õ¡Õ¶ Õ¡Õ¾Õ¡Ö€Õ¿Õ¨ Õ³Õ«Õ·Õ¿ Õ¹Õ¡Õ·Õ­Õ¡Õ¿Õ¥Õ¶"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Õ•ÕºÕ¿Õ«Õ´Õ¡Õ¬Õ¡ÖÕ¾Õ¸Ö‚Õ´ Õ§ Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ® <xliff:g id="NUMBER_0">%1$d</xliff:g>-Õ¨ <xliff:g id="NUMBER_1">%2$d</xliff:g>-Õ«Ö:"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¨ ÕºÕ¡Õ¿Ö€Õ¡Õ½Õ¿Õ¾Õ¸Ö‚Õ´ Õ§:"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Õ€Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ¶Õ¥Ö€Õ¨ Õ´Õ¥Õ¯Õ¶Õ¡Ö€Õ¯Õ¸Ö‚Õ´ Õ¥Õ¶:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 9a6f48e5c201..d780b8c66232 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Mengoptimalkan penyimpanan."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android sedang meningkatkan versi"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Beberapa aplikasi mungkin tidak berfungsi dengan baik jika peningkatan versi belum selesai"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Mengoptimalkan aplikasi <xliff:g id="NUMBER_0">%1$d</xliff:g> dari <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Menyiapkan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Memulai aplikasi."</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index a40db198e710..33b47832be3e 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Fínstillir geymslu."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android er að uppfæra"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Hugsanlega virka sum forrit ekki fyrr en uppfærslunni lýkur"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Fínstillir forrit <xliff:g id="NUMBER_0">%1$d</xliff:g> af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Undirbýr <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Ræsir forrit."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 12e18db75ec5..d03b91d69a41 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Ottimizzazione archiviazione."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Aggiornamento di Android in corso"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Alcune app potrebbero non funzionare correttamente fino al completamento dell\'upgrade"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Ottimizzazione applicazione <xliff:g id="NUMBER_0">%1$d</xliff:g> di <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> in preparazione."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Avvio applicazioni."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 6efa2462b213..6df7a0fc3505 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1070,6 +1070,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"מתבצעת ×ופטימיזציה של ×”×חסון."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"â€Android מבצע שדרוג"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"ייתכן ש×פליקציות מסוימות ×œ× ×™×¤×¢×œ×• כר×וי עד ×¡×™×•× ×”×©×“×¨×•×’"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"מבצע ×ופטימיזציה של ×פליקציה <xliff:g id="NUMBER_0">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"מכין ×ת <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"מפעיל ×פליקציות."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index ef63264828f2..e08520e803be 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"ストレージを最é©åŒ–ã—ã¦ã„ã¾ã™ã€‚"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android ã®ã‚¢ãƒƒãƒ—グレード中"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"アップグレードãŒå®Œäº†ã™ã‚‹ã¾ã§ä¸€éƒ¨ã®ã‚¢ãƒ—ãƒªãŒæ­£å¸¸ã«å‹•作ã—ãªã„å¯èƒ½æ€§ãŒã‚りã¾ã™"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>個中<xliff:g id="NUMBER_0">%1$d</xliff:g>個ã®ã‚¢ãƒ—リを最é©åŒ–ã—ã¦ã„ã¾ã™ã€‚"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>をペア設定ã—ã¦ã„ã¾ã™ã€‚"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"アプリを起動ã—ã¦ã„ã¾ã™ã€‚"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 2091e4a217f0..9ab0f2b20a0d 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"მეხსიერების áƒáƒžáƒ¢áƒ˜áƒ›áƒ˜áƒ–ირებáƒ."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android áƒáƒ®áƒáƒš ვერსიáƒáƒ–ე გáƒáƒ“áƒáƒ“ის"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"áƒáƒ®áƒáƒš ვერსიáƒáƒ–ე გáƒáƒ“áƒáƒ¡áƒ•ლის დáƒáƒ¡áƒ áƒ£áƒšáƒ”ბáƒáƒ›áƒ“ე, ზáƒáƒ’იერთმრáƒáƒžáƒ›áƒ შეიძლებრáƒáƒ áƒáƒ¡áƒ¬áƒáƒ áƒáƒ“ იმუშáƒáƒáƒ¡"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"მიმდინáƒáƒ áƒ”áƒáƒ‘ს áƒáƒžáƒšáƒ˜áƒ™áƒáƒªáƒ˜áƒ”ბის áƒáƒžáƒ¢áƒ˜áƒ›áƒ˜áƒ–áƒáƒªáƒ˜áƒ. დáƒáƒ¡áƒ áƒ£áƒšáƒ”ბულირ<xliff:g id="NUMBER_0">%1$d</xliff:g>, სულ <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"ემზáƒáƒ“ებრ<xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"áƒáƒžáƒ”ბის ჩáƒáƒ áƒ—ვáƒ"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index d8faa1a7c8b5..49d713919643 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Қойманы оңтайландыру."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android жаңартылуда"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Жаңарту аÑқталғанға дейін кейбір қолданбалар Ð´Ò±Ñ€Ñ‹Ñ Ð¶Ò±Ð¼Ñ‹Ñ Ñ–Ñтемеуі мүмкін"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ішінен <xliff:g id="NUMBER_0">%1$d</xliff:g> қолданба оңтайландырылуда."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> дайындалуда."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Қолданбалар Ñ–Ñке қоÑылуда."</string>
@@ -1217,7 +1219,7 @@
<string name="forward_intent_to_work" msgid="621480743856004612">"ОÑÑ‹ қолданбаны Ð¶Ò±Ð¼Ñ‹Ñ Ð¿Ñ€Ð¾Ñ„Ð¸Ð»Ñ–Ò£Ñ–Ð·Ð´Ðµ пайдаланып жатырÑыз"</string>
<string name="input_method_binding_label" msgid="1283557179944992649">"Енгізу әдіÑÑ–"</string>
<string name="sync_binding_label" msgid="3687969138375092423">"Синх"</string>
- <string name="accessibility_binding_label" msgid="4148120742096474641">"Қол жетімділік"</string>
+ <string name="accessibility_binding_label" msgid="4148120742096474641">"Ðрнайы мүмкіндіктер"</string>
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Ðртқы фоны"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Ðртқы фонын өзгерту"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Хабар бақылағыш"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 4584d21864ad..3ffa5612eebb 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -975,7 +975,7 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"កែសម្រួល​ជាមួយ​ %1$s"</string>
<string name="whichEditApplicationLabel" msgid="7183524181625290300">"កែសម្រួល"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"ចែករំលែក​ជាមួយ"</string>
- <string name="whichSendApplicationNamed" msgid="2799370240005424391">"ចែករំលែក​ជាមួយ"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"ចែករំលែក​ជាមួយ %1$s"</string>
<string name="whichSendApplicationLabel" msgid="4579076294675975354">"ចែករំលែក"</string>
<string name="whichSendToApplication" msgid="8272422260066642057">"ផ្ញើដោយប្រើ"</string>
<string name="whichSendToApplicationNamed" msgid="7768387871529295325">"ផ្ញើដោយប្រើ %1$s"</string>
@@ -1026,6 +1026,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"កំពុងធ្វើឲ្យឧបករណáŸáž•្ទុកមានប្រសិទ្ធភាព។"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android កំពុងអាប់គ្រáŸáž..."</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"កម្មវិធីមួយចំនួនអាចនឹងមិនដំណើរការប្រក្រážáž¸áž“ោះទ០រហូážážŠáž›áŸ‹áž€áž¶ážšáž¢áž¶áž”់គ្រáŸážáž”ញ្ចប់"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"ធ្វើ​ឲ្យ​កម្មវិធី​ប្រសើរ​ឡើង <xliff:g id="NUMBER_0">%1$d</xliff:g> នៃ <xliff:g id="NUMBER_1">%2$d</xliff:g> ។"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"កំពុងរៀបចំ <xliff:g id="APPNAME">%1$s</xliff:g>។"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"ចាប់ផ្ដើម​កម្មវិធី។"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index a6d754dc4f73..7960cbab7a09 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"ಸಂಗà³à²°à²¹à²£à³†à²¯à²¨à³à²¨à³ ಆಪà³à²Ÿà²¿à²®à³ˆà²¸à³ ಮಾಡಲಾಗà³à²¤à³à²¤à²¿à²¦à³†."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android ಅಪà³â€Œà²—à³à²°à³‡à²¡à³â€Œ ಮಾಡಲಾಗà³à²¤à³à²¤à²¿à²¦à³†"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"ಅಪà³â€Œà²—à³à²°à³‡à²¡à³ ಮà³à²—ಿಯà³à²µ ತನಕ ಕೆಲವೠಅಪà³à²²à²¿à²•ೇಶನà³â€Œà²—ಳೠಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡದಿರಬಹà³à²¦à³"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ರಲà³à²²à²¿ <xliff:g id="NUMBER_0">%1$d</xliff:g> ಅಪà³à²²à²¿à²•ೇಶನà³â€Œ ಆಪà³à²Ÿà²¿à²®à³ˆà²¸à³ ಮಾಡಲಾಗà³à²¤à³à²¤à²¿à²¦à³†."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> ಸಿದà³à²§à²ªà²¡à²¿à²¸à²²à²¾à²—à³à²¤à³à²¤à²¿à²¦à³†."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"ಅಪà³à²²à²¿à²•ೇಶನà³â€Œà²—ಳನà³à²¨à³ ಪà³à²°à²¾à²°à²‚ಭಿಸಲಾಗà³à²¤à³à²¤à²¿à²¦à³†."</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 6d077139b0c9..2e58e82d899a 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"저장소 최ì í™” 중"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android 업그레ì´ë“œ 중"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"특정 ì•±ì€ ì—…ê·¸ë ˆì´ë“œê°€ ì™„ë£Œë  ë•Œê¹Œì§€ 제대로 ìž‘ë™í•˜ì§€ ì•Šì„ ìˆ˜ 있습니다."</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"앱 <xliff:g id="NUMBER_1">%2$d</xliff:g>ê°œ 중 <xliff:g id="NUMBER_0">%1$d</xliff:g>ê°œ 최ì í™” 중"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> 준비 중..."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"ì•±ì„ ì‹œìž‘í•˜ëŠ” 중입니다."</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index a024db69bb4f..5ba942726ba8 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Сактагыч ыңгайлаштырылууда."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android жаңыртылууда"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Жаңыртуу аÑгына чыкмайынча айрым колдонмолор талаптагыдай иштебей калышы мүмкүн"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_0">%1$d</xliff:g> колдонмо ыңгайлаштырылууда."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> даÑрдалууда."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Колдонмолорду иштетип баштоо"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 0be687507e63..aa4d46858daf 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1024,6 +1024,7 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"àºàº²àº™â€‹àº›àº±àºšâ€‹àºšà»ˆàº­àº™â€‹à»€àºàº±àºšâ€‹àº‚à»à»‰â€‹àº¡àº¹àº™â€‹à»ƒàº«à»‰â€‹à»€à»àº²àº°â€‹àºªàº»àº¡."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"àºàº³àº¥àº±àº‡àº­àº±àºšà»€àºàº£àº” Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"ບາງà»àº­àº±àºšàº­àº²àº”ບà»à»ˆàºªàº²àº¡àº²àº”ເຮັດວຽàºà»„ດ້ປົàºàºàº°àº•ິຈົນàºàº§à»ˆàº²àºˆàº°àº­àº±àºšà»€àºàº£àº”ສຳເລັດ"</string>
+ <string name="app_upgrading_toast" msgid="3008139776215597053">"àºàº³àº¥àº±àº‡àº­àº±àºšà»€àºàº£àº”<xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
<string name="android_upgrading_apk" msgid="7904042682111526169">"àºàº³àº¥àº±àº‡â€‹àº›àº±àºšàº›àº¸àº‡â€‹àº›àº°àºªàº´àº”ທິພາບ​à»àº­àº±àºšàº¯â€‹àº—ີ <xliff:g id="NUMBER_0">%1$d</xliff:g> ຈາàºâ€‹àº—ັງ​à»àº»àº” <xliff:g id="NUMBER_1">%2$d</xliff:g> à»àº­àº±àºšàº¯."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"àºàº³â€‹àº¥àº±àº‡â€‹àºàº½àº¡ <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"àºàº³àº¥àº±àº‡à»€àº›àºµàº”à»àº­àº±àºšàº¯."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index f4da72e39f03..c8e35329ff4b 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1070,6 +1070,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimizuojama saugykla."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"„Android“ naujovinama"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Kai kurios programos gali tinkamai neveikti, kol naujovinimo procesas nebus baigtas"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimizuojama <xliff:g id="NUMBER_0">%1$d</xliff:g> progr. iš <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Ruošiama „<xliff:g id="APPNAME">%1$s</xliff:g>“."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Paleidžiamos programos."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index dba8bebb59dc..e48261810dcf 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1047,6 +1047,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Notiek krÄtuves optimizēšana."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Notiek Android jauninÄÅ¡ana..."</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"KamÄ“r jauninÄÅ¡ana nebÅ«s pabeigta, dažas lietotnes, iespÄ“jams, nedarbosies pareizi."</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Tiek optimizēta <xliff:g id="NUMBER_0">%1$d</xliff:g>. lietotne no <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Notiek lietotnes <xliff:g id="APPNAME">%1$s</xliff:g> sagatavošana."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Notiek lietotņu palaišana."</string>
diff --git a/core/res/res/values-mcc466-mnc01/config.xml b/core/res/res/values-mcc466-mnc01/config.xml
new file mode 100644
index 000000000000..3c379d14ce04
--- /dev/null
+++ b/core/res/res/values-mcc466-mnc01/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <bool name="config_use_sim_language_file">false</bool>
+</resources>
diff --git a/core/res/res/values-mcc466-mnc02/config.xml b/core/res/res/values-mcc466-mnc02/config.xml
new file mode 100644
index 000000000000..3c379d14ce04
--- /dev/null
+++ b/core/res/res/values-mcc466-mnc02/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <bool name="config_use_sim_language_file">false</bool>
+</resources>
diff --git a/core/res/res/values-mcc466-mnc03/config.xml b/core/res/res/values-mcc466-mnc03/config.xml
new file mode 100644
index 000000000000..3c379d14ce04
--- /dev/null
+++ b/core/res/res/values-mcc466-mnc03/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <bool name="config_use_sim_language_file">false</bool>
+</resources>
diff --git a/core/res/res/values-mcc466-mnc06/config.xml b/core/res/res/values-mcc466-mnc06/config.xml
new file mode 100644
index 000000000000..3c379d14ce04
--- /dev/null
+++ b/core/res/res/values-mcc466-mnc06/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <bool name="config_use_sim_language_file">false</bool>
+</resources>
diff --git a/core/res/res/values-mcc466-mnc07/config.xml b/core/res/res/values-mcc466-mnc07/config.xml
new file mode 100644
index 000000000000..3c379d14ce04
--- /dev/null
+++ b/core/res/res/values-mcc466-mnc07/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <bool name="config_use_sim_language_file">false</bool>
+</resources>
diff --git a/core/res/res/values-mcc466-mnc11/config.xml b/core/res/res/values-mcc466-mnc11/config.xml
new file mode 100644
index 000000000000..3c379d14ce04
--- /dev/null
+++ b/core/res/res/values-mcc466-mnc11/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <bool name="config_use_sim_language_file">false</bool>
+</resources>
diff --git a/core/res/res/values-mcc466-mnc92/config.xml b/core/res/res/values-mcc466-mnc92/config.xml
new file mode 100644
index 000000000000..3c379d14ce04
--- /dev/null
+++ b/core/res/res/values-mcc466-mnc92/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+ <bool name="config_use_sim_language_file">false</bool>
+</resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index a6a7793f2ea2..4ebd66bb1ebb 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Оптимизирање на Ñкладирањето."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android Ñе ажурира"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Ðекои апликации може да не работат правилно додека не Ñе заврши надградбата"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Се оптимизира апликација <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Се подготвува <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Се Ñтартуваат апликациите."</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 284db98e914d..ac9018cf9559 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"à´¸àµà´±àµà´±àµ‹à´±àµ‡à´œàµ à´’à´ªàµâ€Œà´±àµà´±à´¿à´®àµˆà´¸àµ ചെയàµà´¯àµà´¨àµà´¨àµ."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android à´…à´ªàµà´—àµà´°àµ‡à´¡àµà´šàµ†à´¯àµà´¯àµà´¨àµà´¨àµ"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"à´…à´ªàµâ€Œà´—àµà´°àµ‡à´¡àµ പൂർതàµà´¤à´¿à´¯à´¾à´•àµà´¨àµà´¨à´¤àµ വരെ à´šà´¿à´² ആപàµâ€Œà´¸àµ ശരിയായി à´ªàµà´°à´µàµ¼à´¤àµà´¤à´¿à´šàµà´šàµ‡à´•àµà´•à´¿à´²àµà´²"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> à´…à´ªàµà´²à´¿à´•àµà´•േഷൻ à´“à´ªàµà´±àµà´±à´¿à´®àµˆà´¸àµ ചെയàµà´¯àµà´¨àµà´¨àµ."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> തയàµà´¯à´¾à´±à´¾à´•àµà´•àµà´¨àµà´¨àµ."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"à´…à´ªàµà´²à´¿à´•àµà´•േഷനàµà´•ൾ ആരംഭികàµà´•àµà´¨àµà´¨àµ."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 8160813853c7..0b55a7a73ff1 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Хадгалалтыг Ñайжруулж байна."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Ðндройдыг дÑвшүүлж байна"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"ШинÑчилж дууÑтал зарим апп Ñ…Ñвийн Ð±ÑƒÑ Ð°Ð¶Ð¸Ð»Ð»Ð°Ð¶ болзошгүй"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>-н <xliff:g id="NUMBER_0">%1$d</xliff:g> апп-г тохируулж байна."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"БÑлдÑж байна <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Ðпп-г Ñхлүүлж байна."</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 7d0fa6da1e80..a1269e19301f 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"संचयन ऑपà¥à¤Ÿà¤¿à¤®à¤¾à¤‡à¤ करत आहे."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android शà¥à¤°à¥‡à¤£à¥€à¤¸à¥à¤§à¤¾à¤°à¤¿à¤¤ होत आहे"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"शà¥à¤°à¥‡à¤£à¥€à¤¸à¥à¤§à¤¾à¤°à¤£à¤¾ पूरà¥à¤£ होईपरà¥à¤¯à¤‚त काही अॅपà¥à¤¸ योगà¥à¤¯à¤°à¤¿à¤¤à¥à¤¯à¤¾ कारà¥à¤¯ करणार नाहीत"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> पैकी <xliff:g id="NUMBER_0">%1$d</xliff:g> अॅप ऑपà¥à¤Ÿà¤¿à¤®à¤¾à¤‡à¤ करत आहे."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> तयार करीत आहे."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"अॅपà¥à¤¸ पà¥à¤°à¤¾à¤°à¤‚भ करत आहे."</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index b66ea933e710..3f9e156ff3f0 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Mengoptimumkan storan."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android sedang ditingkatkan"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Sesetengah apl mungkin tidak berfungsi dengan betul sehingga peningkatan selesai"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Mengoptimumkan apl <xliff:g id="NUMBER_0">%1$d</xliff:g> daripada <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Menyediakan <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Memulakan apl."</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 664985a4f92c..d7d59021ad44 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -124,7 +124,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"ဆားဗစ်အားရှာဖွေနေသည်"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi á€á€±á€«á€ºá€†á€­á€¯á€™á€¾á€¯"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Wi-Fi သုံးá ဖုန်းá€á€±á€«á€ºá€†á€­á€¯á€›á€”်နှင့် မက်စေ့ဂျ်များပို့ရန်አဤá€á€”်ဆောင်မှုအား စá€á€„်သုံးနိုင်ရန်အá€á€½á€€á€º သင့် မိုဘိုင်းá€á€”်ဆောင်မှုအား ဦးစွာမေးမြန်းပါዠထို့နောက် ဆက်á€á€„်မှá€á€†á€„့် Wi-Fi á€á€±á€«á€ºá€†á€­á€¯á€™á€¾á€¯á€¡á€¬á€¸ ထပ်ဖွင့်ပါá‹"</item>
+ <item msgid="2254967670088539682">"Wi-Fi သုံးá ဖုန်းá€á€±á€«á€ºá€†á€­á€¯á€›á€”်နှင့် မက်ဆေ့ဂျ်များပို့ရန်አဤá€á€”်ဆောင်မှုအား စá€á€„်သုံးနိုင်ရန်အá€á€½á€€á€º သင့် မိုဘိုင်းá€á€”်ဆောင်မှုအား ဦးစွာမေးမြန်းပါዠထို့နောက် ဆက်á€á€„်မှá€á€†á€„့် Wi-Fi á€á€±á€«á€ºá€†á€­á€¯á€™á€¾á€¯á€¡á€¬á€¸ ထပ်ဖွင့်ပါá‹"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"သင့် မိုဘိုင်းá€á€”်ဆောင်မှုဖြင့် မှá€á€ºá€•ုံá€á€„်ရန်"</item>
@@ -193,9 +193,9 @@
<string name="silent_mode_silent" msgid="319298163018473078">"ဖုန်းမြည်သံပိá€á€ºá€‘ားသည်"</string>
<string name="silent_mode_vibrate" msgid="7072043388581551395">"á€á€¯á€”်á€á€«á€á€¼á€„်း ဖုန်းမြည်သံ"</string>
<string name="silent_mode_ring" msgid="8592241816194074353">"ဖုန်းမြည်သံဖွင့်ထားသည်"</string>
- <string name="reboot_to_update_title" msgid="6212636802536823850">"Android စနစ်အဆင့်မြှင့်á€á€¼á€„်း"</string>
- <string name="reboot_to_update_prepare" msgid="6305853831955310890">"အဆင့်မြှင့်á€á€„်ရန် ပြင်ဆင်နေသည်…"</string>
- <string name="reboot_to_update_package" msgid="3871302324500927291">"ပက်ကေ့ အဆင့်မြှင့်á€á€¼á€„်း စီမံဆောင်ရွက်နေစဉ်…"</string>
+ <string name="reboot_to_update_title" msgid="6212636802536823850">"Android စနစ်အပ်ဒိá€á€ºá€œá€¯á€•်á€á€¼á€„်း"</string>
+ <string name="reboot_to_update_prepare" msgid="6305853831955310890">"အပ်ဒိá€á€ºá€œá€¯á€•်ရန် ပြင်ဆင်နေသည်…"</string>
+ <string name="reboot_to_update_package" msgid="3871302324500927291">"အပ်ဒိá€á€ºá€•က်ကေ့ဂျ်ကို စီမံဆောင်ရွက်နေဆဲ…"</string>
<string name="reboot_to_update_reboot" msgid="6428441000951565185">"ပြန်လည်စá€á€„်နေ…"</string>
<string name="reboot_to_reset_title" msgid="4142355915340627490">"စက်ရုံထုá€á€ºá€¡á€á€¼á€±á€¡á€”ေပြန်ယူá€á€¼á€„်း"</string>
<string name="reboot_to_reset_message" msgid="2432077491101416345">"ပြန်လည်စá€á€„်နေ…"</string>
@@ -264,12 +264,12 @@
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"သင် အပြန်အလှန်လုပ်နေသော á€á€„်းဒိုးမှာပါရှိသည်များကို သေá€á€»á€¬á€…ွာ ကြည့်ရှုစစ်ဆေးပါ"</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"ထိá€á€­á€¯á€·á€á€¼á€„်းဖြင့် ရှာဖွေပေးနိုင်á€á€¬á€€á€­á€¯ ဖွင့်လိုက်ပါ"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"á€á€­á€¯á€·á€œá€­á€¯á€€á€ºá€žá€Šá€·á€ºá€¡á€›á€¬á€™á€»á€¬á€¸á€€á€­á€¯ အသံထွက်ဖá€á€ºá€•ေးပါလိမ့်မည်ዠလက်ဟန်အမူအရာများကို အသုံးပြုá မျက်နှာပြင်ကို လေ့လာနိုင်ပါသည်á‹"</string>
- <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"ပိုမိုကောင်းမွန်သော á€á€€á€ºá€˜á€ºá€¡á€™á€»á€¬á€¸á€žá€¯á€¶á€¸á€…ွဲနိုင်မှုကို ဖွင့်ရန်"</string>
+ <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"ပိုမိုကောင်းမွန်သော á€á€˜á€ºá€›á€šá€°á€žá€¯á€¶á€¸á€…ွဲနိုင်မှုကို ဖွင့်ရန်"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"အပလီကေးရှင်းကို ပိုမိုပြည့်စုံစေရန် စကရစ်များကို သွင်းနိုင်ပါá€á€šá€º"</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"ရိုက်သောစာများကို သေá€á€»á€¬á€…ွာ စစ်ဆေးပါ"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"အရေးကြီးသော ကိုယ်ရေးအá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€–ြစ်á€á€²á€· á€á€›á€€á€ºá€’စ်ကဒ်နံပါá€á€ºá€™á€»á€¬á€¸á€”ှင့် စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸ ပါá€á€„်ပါá€á€šá€º."</string>
<string name="capability_title_canControlMagnification" msgid="3593493281059424855">"မျက်နှာပြင် á€á€»á€²á€·á€á€¼á€„်းကို ထိန်းá€á€»á€¯á€•်ပါ"</string>
- <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"မျက်နှာပြင် á€á€»á€²á€·á€á€¼á€„်းနှင့် နေရာá€á€»á€‘ားá€á€¼á€„်းကို ထိန်းá€á€»á€¯á€•်ပါ"</string>
+ <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"မျက်နှာပြင် ဇူးမ်အရွယ်နှင့် နေရာá€á€»á€‘ားá€á€¼á€„်းကို ထိန်းá€á€»á€¯á€•်ပါá‹"</string>
<string name="capability_title_canPerformGestures" msgid="7418984730362576862">"လက်ဟန်များ အသုံးပြုပါ"</string>
<string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"á€á€­á€¯á€·á€á€¼á€„်းአပွá€á€ºá€†á€½á€²á€á€¼á€„်းአနှင့် အá€á€¼á€¬á€¸ လက်ဟန်များကို အသုံးပြုနိုင်ပါသည်á‹"</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"အá€á€¼á€±á€¡á€”ေပြဘားအား အလုပ်မလုပ်á€á€­á€¯á€„်းရန်သို့မဟုá€á€º မွမ်းမံရန်"</string>
@@ -293,7 +293,7 @@
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"အမည်သွင်းထားသောဖိဖ့်များကို ဖá€á€ºá€á€¼á€„်း"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"အက်ပ်အား လောလောဆယ် စင့်က် လုပ်ပြီးသား ထည့်သွင်းမှုများ ဆိုင်ရာ အသေးစိá€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ရယူá€á€½á€„့်ပြုသည်á‹"</string>
<string name="permlab_sendSms" msgid="7544599214260982981">"SMS စာများကို ပို့ကာ ကြည့်မည်"</string>
- <string name="permdesc_sendSms" msgid="7094729298204937667">"အပလီကေးရှင်းအား စာá€á€­á€¯á€•ို့á€á€½á€„့် ပြုပါዠမမျှော်လင့်သော ကုန်ကျမှု ဖြစ်နိုင်ပါသည်ዠအန္á€á€›á€¬á€šá€ºá€›á€¾á€­ အပလီကေးရှင်းများမှ သင် မသိပဲ စာပို့á€á€¼á€„်းများ ပြုလုပ်á€á€¼á€„်းကြောင့် ပိုက်ဆံ အပို ကုန်စေနိုင်သည်"</string>
+ <string name="permdesc_sendSms" msgid="7094729298204937667">"အက်ပ်အား စာá€á€­á€¯á€•ို့á€á€½á€„့် ပြုပါዠမမျှော်လင့်သော ကုန်ကျမှု ဖြစ်နိုင်ပါသည်ዠအန္á€á€›á€¬á€šá€ºá€›á€¾á€­ အက်ပ်များမှ သင် မသိပဲ စာပို့á€á€¼á€„်းများ ပြုလုပ်á€á€¼á€„်းကြောင့် ပိုက်ဆံ အပို ကုန်စေနိုင်သည်"</string>
<string name="permlab_readSms" msgid="8745086572213270480">"သင့်ရဲ့ စာပေးပို့á€á€¼á€„်းများ ဖá€á€ºá€á€¼á€„်း (စာá€á€­á€¯ နှင့် ရုပ်သံစာ)"</string>
<string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"အပလီကေးရှင်းအား á€á€€á€ºá€˜á€œá€€á€º သို့မဟုá€á€º ဆင်းမ်ကဒ်မှာ သိမ်းဆည်းထားသော စာá€á€­á€¯á€™á€»á€¬á€¸ ဖá€á€ºá€›á€¾á€¯á€á€½á€„့်ပြုပါዠအပလီကေးရှင်းအနေဖြင့် အကြာင်းအရာ သို့မဟုá€á€º ယုံကြည်စိá€á€ºá€á€»á€›á€™á€¾á€¯á€€á€­á€¯ ဂရုမပြုပဲ စာá€á€­á€¯á€¡á€¬á€¸á€œá€¯á€¶á€¸á€€á€­á€¯ ဖá€á€ºá€”ိုင်ပါလိမ်မည်á‹"</string>
<string name="permdesc_readSms" product="tv" msgid="5102425513647038535">"သင့်á€á€®á€—ွီ သို့မဟုá€á€º ဆင်းမ်ကဒ်á€á€½á€„် သိမ်းထားသည့် SMS စာများကို အက်ပ်အား ဖá€á€ºá€á€½á€„့်ပြုပါዠထိုသို့á€á€½á€„့်ပြုá€á€¼á€„်းဖြင့် အက်ပ်သည် အကြောင်းအရာ သို့မဟုá€á€º ယုံကြည်စိá€á€ºá€á€»á€›á€™á€¾á€¯ á€á€­á€¯á€·á€”ှင့် မသက်ဆိုင်ဘဲአSMS စာများအားလုံးကို ဖá€á€ºá€”ိုင်မည်ဖြစ်áá‹"</string>
@@ -325,9 +325,9 @@
<string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"စနစ် စá€á€„်ပြီးသည်နှင့် á€á€…်ပြိုင်နက် အလိုလို အစပြုရန် အက်ပ်အားá€á€½á€„့်ပြုပါዠထိုသို့á€á€½á€„့်ပြုá€á€¼á€„်းဖြင့် á€á€®á€—ွီအား စရန် အá€á€»á€­á€”်ကြာစေပြီး အစဉ်အမြဲဖွင့်ထားá€á€¼á€„်းဖြင့် á€á€€á€ºá€˜á€œá€€á€ºá€¡á€¬á€¸ နှေးသွားစေရန် အက်ပ်အား á€á€½á€„့်ပြုပါá‹"</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"အက်ပ်အား စနစ်á စá€á€„်မှု ပြီးဆုံးသည့်နှင့် မိမိကိုမိမိ စá€á€„်á€á€½á€„့် ပြုသည်ዠသို့ဖြစ်á ဖုန်း စá€á€„်မှုမှာ အá€á€»á€­á€”် ပိုကြာနိုင်ပြီး အက်ပ်က á€á€á€»á€­á€”်လုံး အလုပ်လုပ်နေá€á€¼á€„်းကြောင့် ဖုန်းá အလုပ် á€á€…်á€á€¯á€œá€¯á€¶á€¸á€€á€­á€¯ နှေးကွေးလာစေနိုင်သည်á‹"</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"ကြာရှည်á€á€¶ ထုá€á€ºá€œá€½á€¾á€á€ºá€™á€¾á€¯ အားပေးပို့á€á€¼á€„်း"</string>
- <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"အပလီကေးရှင်းအား ကြာရှည်á€á€¶ ထုá€á€ºá€œá€½á€¾á€„့်မှု ပြုပါዠဒီထုá€á€ºá€œá€½á€¾á€„့်မှုများဟာ ထုá€á€ºá€œá€½á€¾á€„့်မှု ပြီးဆုံးပြီးသွားá€á€Šá€·á€ºá€á€­á€¯á€„် ကျန်နေမည် ဖြစ်ပါသည်ዠအလွန်အကျွံသုံးá€á€¼á€„်းကြောင့် မက်မိုရီ အသုံးများပြီး á€á€€á€ºá€˜á€œá€€á€ºá€”ှေးá€á€¼á€„်းአမá€á€Šá€ºá€„ြိမ်á€á€¼á€„်း ဖြစ်နိုင်ပါသည်"</string>
+ <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"အက်ပ်အား ကြာရှည်á€á€¶ ထုá€á€ºá€œá€½á€¾á€„့်မှု ပြုပါዠဒီထုá€á€ºá€œá€½á€¾á€„့်မှုများဟာ ထုá€á€ºá€œá€½á€¾á€„့်မှု ပြီးဆုံးပြီးသွားá€á€Šá€·á€ºá€á€­á€¯á€„် ကျန်နေမည် ဖြစ်ပါသည်ዠအလွန်အကျွံသုံးá€á€¼á€„်းကြောင့် မက်မိုရီ အသုံးများပြီး á€á€€á€ºá€˜á€œá€€á€ºá€”ှေးá€á€¼á€„်းአမá€á€Šá€ºá€„ြိမ်á€á€¼á€„်း ဖြစ်နိုင်ပါသည်"</string>
<string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"ထုá€á€ºá€œá€½á€¾á€„့်á€á€¼á€„်းများ ပြီးဆုံးသည့်နောက် ဆက်လက်ရှိနေသည့်አá€á€Šá€ºá€™á€¼á€² ထုá€á€ºá€œá€½á€¾á€„့်မှုများပို့ရန် အက်ပ်အား á€á€½á€„့်ပြုပါዠအလွန်အကျွံ လုပ်ဆောင်ပါက á€á€®á€—ွီ နှေးသွားá€á€¼á€„်း သို့မဟုá€á€º မှá€á€ºá€‰á€¬á€á€ºá€¡á€žá€¯á€¶á€¸á€™á€»á€¬á€¸á€™á€¾á€¯á€€á€¼á€±á€¬á€„့် မá€á€Šá€ºá€™á€„ြိမ်ဖြစ်á€á€¼á€„်းများ ဖြစ်á€á€á€ºáá‹"</string>
- <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"အပလီကေးရှင်းအား ကြာရှည်á€á€¶ ထုá€á€ºá€œá€½á€¾á€„့်မှု ပြုပါዠဒီထုá€á€ºá€œá€½á€¾á€„့်မှုများဟာ ထုá€á€ºá€œá€½á€¾á€„့်မှု ပြီးဆုံးပြီးသွားá€á€Šá€·á€ºá€á€­á€¯á€„် ကျန်နေမည် ဖြစ်ပါသည်ዠအလွန်အကျွံသုံးá€á€¼á€„်းကြောင့် မှá€á€ºá€‰á€¬á€á€ºá€¡á€žá€¯á€¶á€¸á€™á€»á€¬á€¸á€•ြီး ဖုန်းနှေးá€á€¼á€„်းአမá€á€Šá€ºá€„ြိမ်á€á€¼á€„်း ဖြစ်နိုင်ပါသည်"</string>
+ <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"အက်ပ်အား ကြာရှည်á€á€¶ ထုá€á€ºá€œá€½á€¾á€„့်မှု ပြုပါዠဤထုá€á€ºá€œá€½á€¾á€„့်မှုများဟာ ထုá€á€ºá€œá€½á€¾á€„့်မှု ပြီးဆုံးပြီးသွားá€á€Šá€·á€ºá€á€­á€¯á€„် ကျန်နေမည် ဖြစ်ပါသည်ዠအလွန်အကျွံသုံးá€á€¼á€„်းကြောင့် မှá€á€ºá€‰á€¬á€á€ºá€¡á€žá€¯á€¶á€¸á€™á€»á€¬á€¸á€•ြီး ဖုန်းနှေးá€á€¼á€„်းአမá€á€Šá€ºá€„ြိမ်á€á€¼á€„်း ဖြစ်နိုင်ပါသည်"</string>
<string name="permlab_readContacts" msgid="8348481131899886131">"အဆက်အသွယ်များအား ဖá€á€ºá€á€¼á€„်း"</string>
<string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"အပလီကေးရှင်းအား á€á€±á€«á€ºá€†á€­á€¯á€žá€±á€¬ အကြိမ်ရေአအီးမေးလ်အကြိမ်ရေአá€á€á€¼á€¬á€¸á€†á€€á€ºá€žá€½á€šá€ºá€™á€¾á€¯á€™á€»á€¬á€¸á€…သည်ကဲ့သို့ သင့်á€á€€á€ºá€˜á€œá€€á€ºá€™á€¾á€¬ သိမ်းဆည်းထားသော အဆက်အသွယ်များရဲ့ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯ ဖá€á€ºá€á€½á€„့်ပြုပါዠဤသို့á€á€½á€„့်ပြုá€á€¼á€„်းအားဖြင့် အပလီကေးရှင်းများကို သင့် အဆက်အသွယ်á အá€á€»á€€á€ºá€™á€œá€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ သိမ်းဆည်းရန် á€á€½á€„့်ပြုပြီး အန္á€á€›á€¬á€šá€ºá€›á€¾á€­á€žá€±á€¬ အပလီကေးရှင်းများမှ ထိုအá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸ ကို သင် မသိစေပဲ ဖြန့်á€á€±á€”ိုင််မည် ဖြစ်ပါသည်á‹"</string>
<string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"á€á€…်ဦးá€á€…်​ယောက်ထံ သင်á€á€±á€«á€ºá€‘ားသောአအီးမေးိပု့ထားသောአသို့မဟုá€á€º á€á€…်á€á€¼á€¬á€¸á€”ည်းဖြင့် အဆက်အသွယ်ပြုထားသော အကြိမ်အရေအá€á€½á€€á€º အပါအá€á€„်አသင့်á€á€®á€—ွီá€á€½á€„် သိမ်းထားသည့် အဆက်အသွယ်ဆိုင်ရာ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸ ဖá€á€ºá€›á€”် အက်ပ်အား á€á€½á€„့်ပြုပါዠဤနည်းဖြင့် သင့် အဆက်အသွယ် အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ သိမ်းဆည်းရန် အက်ပ်အား á€á€½á€„့်ပြုထားá€á€¼á€„်းဖြစ်ပြီးአအဆက်အသွယ် အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ အန္á€á€›á€¬á€šá€ºá€›á€¾á€­á€žá€±á€¬ အက်ပ်များက သင်မသိဘဲ á€á€±á€™á€»á€¾á€”ိုင်သည်á‹"</string>
@@ -351,9 +351,9 @@
<string name="permdesc_readCalendar" product="tv" msgid="3191352452242394196">"သူငယ်á€á€»á€„်းများ သို့မဟုá€á€º လုပ်ဖော်ကိုင်ဖက်များá ဖြစ်ရပ်များ အပါအá€á€„်አသင့် á€á€®á€—ွီá€á€½á€„် သိမ်းထားသော ပြက္á€á€’ိန်ရှိ ဖြစ်ရပ်များအား ဖá€á€ºá€›á€”် အက်ပ်အား á€á€½á€„့်ပြုပါዠဤနည်းဖြင့် ယုံကြည်စိá€á€ºá€á€»á€›á€™á€¾á€¯ သို့မဟုá€á€º ထိá€á€­á€¯á€€á€ºá€œá€½á€šá€ºá€™á€¾á€¯á€á€­á€¯á€·á€”ှင့် မသက်ဆိုင်ဘဲአသင့် ပြက္á€á€’ိန်ရှိ ဒေá€á€¬á€€á€­á€¯ á€á€±á€™á€»á€¾á€›á€”် သို့မဟုá€á€º သိမ်းဆည်းရန် အက်ပ်အား á€á€½á€„့်ပြုသည်á‹"</string>
<string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"အပလီကေးရှင်းအားဖုန်းထဲá€á€½á€„် သိမ်းထားသော သူငယ်á€á€»á€„်းနှင့် လုပ်ဖော်ကိုင်ဘက်များá ပြက္á€á€’ိန် အဖြစ်အပျက်များအပါအá€á€„် အားလုံးကို ဖá€á€ºá€›á€¾á€¯á€á€½á€„့်ပြုပါዠဒီá€á€½á€„့်ပြုá€á€»á€€á€ºá€€á€¼á€±á€¬á€„့် အပလီကေးရှင်းမှ ပြက္á€á€’ိန် အဖြစ်အပျက်များအား လျှို့á€á€¾á€€á€ºá€™á€¾á€¯ သို့ ဂရုပြုမှု ကို ထည့်သွင်းမစဉ်းစားပဲ သိမ်းဆည်းá€á€¼á€„်းአမျှá€á€±á€á€¼á€„်း ပြုလုပ်စေနိုင်ပါသည်"</string>
<string name="permlab_writeCalendar" msgid="8438874755193825647">"ပြက္á€á€’ိန်အဖြစ်အပျက်များကို ထပ်ထည့်ရန် သို့မဟုá€á€º မွမ်းမံရန်နှင့် ပိုင်ရှင်áအသိမပေးပဲ ဧည့်သည်များထံ အီးမေးလ်ပို့ရန်"</string>
- <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"အပလီကေးရှင်းအား သင်á á€á€€á€ºá€˜á€œá€€á€ºá€á€½á€„် သူငယ်á€á€»á€„်း အလုပ်ဖော်များ အပါအá€á€„် သင်á ပြောင်းလဲအဖြစ်အပျက်များအား ထည့်á€á€¼á€„်းአထုá€á€ºá€á€¼á€„်းအား á€á€½á€„့်ပြုရန်ዠဤá€á€½á€„့်ပြုá€á€»á€€á€ºá€žá€Šá€º အပလီကေးရှင်းအား သá€á€„်းများပို့á€á€¼á€„်းကို ပြက္á€á€’ိန်ပိုင်ရှင်ဆီမှ လာသလို အနေဖြင့် ပေးပို့á€á€¼á€„်း သို့မဟုá€á€º အဖြစ်အပျက်များကို ပိုင်ရှင်မသိပဲ ပြင်ဆင်နိုင်ပါသည်á‹"</string>
+ <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"အက်ပ်အား သင်á á€á€€á€ºá€˜á€œá€€á€ºá€á€½á€„် မိá€á€ºá€†á€½á€± အလုပ်ဖော်များ အပါအá€á€„် သင်á ပြောင်းလဲအဖြစ်အပျက်များအား ထည့်á€á€¼á€„်းአထုá€á€ºá€á€¼á€„်းအား á€á€½á€„့်ပြုရန်ዠဤá€á€½á€„့်ပြုá€á€»á€€á€ºá€žá€Šá€º အက်ပ်အား သá€á€„်းများပို့á€á€¼á€„်းကို ပြက္á€á€’ိန်ပိုင်ရှင်ဆီမှ လာသလို အနေဖြင့် ပေးပို့á€á€¼á€„်း သို့မဟုá€á€º အဖြစ်အပျက်များကို ပိုင်ရှင်မသိပဲ ပြင်ဆင်နိုင်ပါသည်á‹"</string>
<string name="permdesc_writeCalendar" product="tv" msgid="1273290605500902507">"သင့် သူငယ်á€á€»á€„်းများ သို့မဟုá€á€º လုပ်ဖော်ကိုင်ဖက်များá လှုပ်ရှားမှုများ အပါအá€á€„်አသင့်á€á€®á€—ွီရှိ လှုပ်ရှားမှုများကို ထပ်ထည့်ရန်አဖယ်ထုá€á€ºá€›á€”်አပြောင်းလဲရန် အက်ပ်အား á€á€½á€„့်ပြုပါዠဤသို့ပြုပါက ပြက္á€á€’ိန် ပိုင်ရှင်ဆီမှ စာá€á€­á€¯á€™á€»á€¬á€¸ လာသကဲ့သို့ စာများပို့ရန်አသို့မဟုá€á€º ပိုင်ရှင်á á€á€½á€„့်ပြုá€á€»á€€á€ºá€™á€›á€¾á€­á€˜á€² လှုပ်ရှားမှုများကို ပြင်ဆင်ရန် အက်ပ်အား á€á€½á€„့်ပြုထားá€á€¼á€„်း ဖြစ်áá‹"</string>
- <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"အပလီကေးရှင်းအား သင်á ဖုန်းá€á€½á€„် သူငယ်á€á€»á€„်း အလုပ်ဖော်များ အပါအá€á€„် သင်á ပြောင်းလဲအဖြစ်အပျက်များအား ထည့်á€á€¼á€„်းአထုá€á€ºá€á€¼á€„်းအား á€á€½á€„့်ပြုရန်ዠဤá€á€½á€„့်ပြုá€á€»á€€á€ºá€žá€Šá€º အပလီကေးရှင်းအား သá€á€„်းများပို့á€á€¼á€„်းကို ပြက္á€á€’ိန်ပိုင်ရှင်ဆီမှ လာသလို အနေဖြင့် ပေးပို့á€á€¼á€„်း သို့မဟုá€á€º အဖြစ်အပျက်များကို ပိုင်ရှင်မသိပဲ ပြင်ဆင်နိုင်ပါသည်á‹"</string>
+ <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"အက်ပ်အား သင်á ဖုန်းá€á€½á€„် မိá€á€ºá€†á€½á€± အလုပ်ဖော်များ အပါအá€á€„် သင်á ပြောင်းလဲအဖြစ်အပျက်များအား ထည့်á€á€¼á€„်းአထုá€á€ºá€á€¼á€„်းအား á€á€½á€„့်ပြုရန်ዠဤá€á€½á€„့်ပြုá€á€»á€€á€ºá€žá€Šá€º အက်ပ်အား သá€á€„်းများပို့á€á€¼á€„်းကို ပြက္á€á€’ိန်ပိုင်ရှင်ဆီမှ လာသလို အနေဖြင့် ပေးပို့á€á€¼á€„်း သို့မဟုá€á€º အဖြစ်အပျက်များကို ပိုင်ရှင်မသိပဲ ပြင်ဆင်နိုင်ပါသည်á‹"</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"á€á€Šá€ºá€”ေရာပံ့ပိုးမှုညွှန်ကြားá€á€»á€€á€ºá€¡á€•ိုအား á€á€„်ရောက်ကြည့်á€á€¼á€„်း"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"အက်ပ်အား á€á€Šá€ºá€”ေရာ စီမံပေးရေး ညွှန်ကြားá€á€»á€€á€º အပိုများကို ရယူá€á€½á€„့်ပြုသည်ዠသို့ဖြစ်á အက်ပ်သည် GPS သို့မဟုá€á€º အá€á€¼á€¬á€¸ á€á€Šá€ºá€”ေရာ ရင်းမြစ်ကို သုံးကြသူá€á€­á€¯á€·á လုပ်ငန်းများကို á€á€„်စွက်á€á€½á€„့် ပြုနိုင်သည်á‹"</string>
<string name="permlab_accessFineLocation" msgid="251034415460950944">"á€á€­á€€á€»á€á€²á€· á€á€Šá€ºá€”ေရာ (GPS နှင့် ကွန်ရက် အá€á€¼á€±á€á€¶)ကို ရယူသုံးရန်"</string>
@@ -365,7 +365,7 @@
<string name="permlab_recordAudio" msgid="3876049771427466323">"အသံဖမ်းá€á€¼á€„်း"</string>
<string name="permdesc_recordAudio" msgid="4906839301087980680">"အပလီကေးရှင်းအား မိုက်á€á€›á€­á€¯á€–ုန်းဖြင့် အသံသွင်းá€á€½á€„့် ပြုပါዠအပလီကေးရှင်းအနေဖြင့် သင့် á€á€½á€„့်ပြုá€á€»á€€á€º မပါပဲ အá€á€»á€­á€”်မရွေး အသံဖမ်းနိုင်ပါမည်"</string>
<string name="permlab_sim_communication" msgid="2935852302216852065">"SIM ထံသို့ ညွှန်ကြားá€á€»á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ပို့ပါ"</string>
- <string name="permdesc_sim_communication" msgid="5725159654279639498">"အပလီကေးရှင်းအား ဆင်းမ်ကဒ်ဆီသို့ အမိန့်များ ပေးပို့á€á€½á€„့် ပြုá€á€¼á€„်းዠဒီ á€á€½á€„့်ပြုမှုဟာ အန်á€á€›á€šá€º အလွန် ရှိပါသည်á‹."</string>
+ <string name="permdesc_sim_communication" msgid="5725159654279639498">"အက်ပ်အား ဆင်းမ်ကဒ်ဆီသို့ အမိန့်များ ပေးပို့á€á€½á€„့် ပြုá€á€¼á€„်းዠဤá€á€½á€„့်ပြုမှုမှာ အန္á€á€›á€¬á€šá€ºá€¡á€œá€½á€”် ရှိပါသည်á‹"</string>
<string name="permlab_camera" msgid="3616391919559751192">"ဓါá€á€ºá€•ုံနှင့်ဗွီဒီယိုရိုက်á€á€¼á€„်း"</string>
<string name="permdesc_camera" msgid="8497216524735535009">"အပလီကေးရှင်းအား အလိုအလျောက် ဓာá€á€ºá€•ုံရိုက်á€á€½á€„့်አဗီဒီယို ရိုက်ကူးá€á€½á€„့် ပြုပါዠဒီá€á€½á€„့်ပြုá€á€»á€€á€ºá€€ အပလီကေးရှင်းကို အá€á€»á€­á€”်မရွေး ကင်မရာအား á€á€½á€„့်ပြုá€á€»á€€á€º မလိုအပ်ပဲ သုံးá€á€½á€„့်ပြုပါသည်á‹"</string>
<string name="permlab_vibrate" msgid="7696427026057705834">"á€á€¯á€”်á€á€¯á€”်မှုအား ထိန်းá€á€»á€¯á€•်á€á€¼á€„်း"</string>
@@ -401,7 +401,7 @@
<string name="permlab_accessNetworkState" msgid="4951027964348974773">"ကွန်ရက် á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€™á€»á€¬á€¸á€¡á€¬á€¸ ကြည့်ရန်"</string>
<string name="permdesc_accessNetworkState" msgid="8318964424675960975">"အပလီကေးရှင်းအား မည်သည့်ကွန်ရက်နက်á€á€˜á€ºá€›á€¾á€­á€žá€œá€²áŠ á€™á€Šá€ºá€žá€Šá€·á€ºá€€á€½á€”á€ºá€›á€€á€ºá€”á€¾á€„á€·á€º á€á€»á€­á€á€ºá€†á€€á€ºá€‘ားလဲ စသည်ဖြင့် ကွန်ရက်á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€™á€»á€¬á€¸á သá€á€„်းအá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ကြည့်á€á€½á€„့်ပေးရန်"</string>
<string name="permlab_createNetworkSockets" msgid="7934516631384168107">"ကွန်ရက်ကို အပြည့်အဠရယူသုံးနိုင်"</string>
- <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"အပလီကေးရှင်းအား ကွန်ရက်ဆော့ကá€á€ºá€™á€»á€¬á€¸ á€á€Šá€ºá€†á€±á€¬á€€á€ºá€á€½á€„့်አá€á€žá€®á€¸á€á€žá€”့် ကွန်ရက် ပရိုá€á€­á€¯á€€á€±á€¬á€œá€ºá€™á€»á€¬á€¸ သုံးá€á€½á€„့် ပြုပါዠအင်á€á€¬á€”က်မှ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸ ပေးပို့á€á€¼á€„်းကို ဘရောက်ဇာနှင့် á€á€á€¼á€¬á€¸ အပလီကေးရှင်းများက လုပ်ဆောင်ပေးသောကြောင့် ဒီá€á€½á€„့်ပြုá€á€»á€€á€ºá€€ အင်á€á€¬á€”က်မှ အá€á€»á€€á€ºá€¡á€œá€€á€º ပေးပို့á€á€¼á€„်း မလိုအပ်ပါ"</string>
+ <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"အက်ပ်အား ကွန်ရက်ဆော့ကá€á€ºá€™á€»á€¬á€¸ á€á€Šá€ºá€†á€±á€¬á€€á€ºá€á€½á€„့်አá€á€žá€®á€¸á€á€žá€”့် ကွန်ရက် ပရိုá€á€­á€¯á€€á€±á€¬á€œá€ºá€™á€»á€¬á€¸ သုံးá€á€½á€„့် ပြုပါዠအင်á€á€¬á€”က်မှ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸ ပေးပို့á€á€¼á€„်းကို ဘရောက်ဇာနှင့် á€á€á€¼á€¬á€¸ အက်ပ်များက လုပ်ဆောင်ပေးသောကြောင့် ဒီá€á€½á€„့်ပြုá€á€»á€€á€ºá€€ အင်á€á€¬á€”က်မှ အá€á€»á€€á€ºá€¡á€œá€€á€º ပေးပို့á€á€¼á€„်း မလိုအပ်ပါ"</string>
<string name="permlab_changeNetworkState" msgid="958884291454327309">"ကွန်ယက်ဆက်သွယ်မှုအားပြောင်းá€á€¼á€„်း"</string>
<string name="permdesc_changeNetworkState" msgid="6789123912476416214">"အက်ပ်အား ကွန်ရက် á€á€»á€­á€á€ºá€†á€€á€ºá€”ိုင်စွမ်း အá€á€¼á€±á€¡á€”ေကို ပြောင်းလဲá€á€½á€„့် ပြုသည်á‹"</string>
<string name="permlab_changeTetherState" msgid="5952584964373017960">"á€á€…်ဆင့်ပွါးဆက်သွယ်မှုအားပြောင်းá€á€¼á€„်း"</string>
@@ -488,37 +488,37 @@
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ကွန်ယက်အသုံးပြုမှုစာရင်းအား မွမ်းမံá€á€¼á€„်း"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"အပလီကေးရှင်းအား á€á€á€¼á€¬á€¸á€¡á€•လီကေးရှင်းများမှ ကွန်ရက်အသုံးပြုမှု á€á€½á€€á€ºá€á€»á€€á€ºá€á€¼á€„်းအား ပြင်ဆင်á€á€½á€„့် ပြုပါዠပုံမှန် အပလီကေးရှင်းများအá€á€½á€€á€º မလိုအပ်ပါá‹"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"သá€á€­á€•ေးá€á€»á€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ အသုံးပြုá€á€½á€„့်"</string>
- <string name="permdesc_accessNotifications" msgid="458457742683431387">"အပလီကေးရှင်းကို အကြောင်းကြားá€á€»á€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ထုá€á€ºá€œá€¯á€•်ရန်አလေ့လာရန်አဖျက်ပစ်ရန် á€á€½á€„့်ပြုá€á€¼á€„်းዠá€á€á€¼á€¬á€¸ အပလီကေးရှင်းများမှ သá€á€­á€•ေးá€á€»á€€á€ºá€™á€»á€¬á€¸á€œá€Šá€ºá€¸ ပါá€á€„်ပါသည်"</string>
+ <string name="permdesc_accessNotifications" msgid="458457742683431387">"အပလီကေးရှင်းကို အကြောင်းကြားá€á€»á€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ထုá€á€ºá€œá€¯á€•်ရန်አလေ့လာရန်አဖျက်ရန် á€á€½á€„့်ပြုá€á€¼á€„်းዠá€á€á€¼á€¬á€¸ အပလီကေးရှင်းများမှ သá€á€­á€•ေးá€á€»á€€á€ºá€™á€»á€¬á€¸á€œá€Šá€ºá€¸ ပါá€á€„်ပါသည်"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"သá€á€­á€•ေးá€á€»á€€á€º နားထောင်á€á€¼á€„်း ဆားဗစ် နှင့် ပူးပေါင်းá€á€¼á€„်း"</string>
- <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ဖုန်းကိုင်ထားသူနှင့် အကြောင်းကြားá€á€»á€€á€º နားစွင့်သော ဆားဗစ်မှ ထိပ်ပိုင်းအင်á€á€¬á€–ေ့စ် ကို ပူးပေါင်းá€á€½á€„့်ပေးá€á€¼á€„်းዠပုံမှန် အပလီကေးရှင်းများမှာ မလိုအပ်ပါ"</string>
+ <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ဖုန်းကိုင်ထားသူနှင့် အကြောင်းကြားá€á€»á€€á€º နားစွင့်သော ဆားဗစ်မှ ထိပ်ပိုင်းအင်á€á€¬á€–ေ့စ် ကို ပူးပေါင်းá€á€½á€„့်ပေးá€á€¼á€„်းዠပုံမှန် အက်ပ်များအá€á€½á€€á€º ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်ပါ"</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"အá€á€¼á€±á€¡á€”ေ စီမံပေးရေး á€á€”်ဆောင်မှု á€á€…်á€á€¯á€†á€®á€žá€­á€¯á€· á€á€»á€­á€á€ºá€á€½á€²á€á€¼á€„်း"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"စွဲကိုင်ထားသူအား အá€á€¼á€±á€¡á€”ေကို စီမံပေးသူá ထိပ်သီး အဆင့် အင်á€á€¬á€–ေ့စ်သို့ á€á€»á€­á€á€ºá€á€½á€²á€á€½á€„့်ကို ပေးသည်ዠသာမန် အက်ပ်များ အá€á€½á€€á€º ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်နိုင်ပါá‹"</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"အိပ်မက် á€á€”်ဆောင်မှုသို့ ပေါင်းစည်းမည်"</string>
- <string name="permdesc_bindDreamService" msgid="7325825272223347863">"အိမ်မက်á€á€”်ဆောင်မှုá ထိပ်á€á€”်းအဆင့် မျက်နှာပြင်အား ကိုင်ဆောင်သူမှ ပေါင်းစည်းရန် á€á€½á€„့်ပြုမည်ዠသာမန် အပလီကေးရှင်းများá€á€½á€„် မလိုအပ်ပါá‹"</string>
+ <string name="permdesc_bindDreamService" msgid="7325825272223347863">"အိမ်မက်á€á€”်ဆောင်မှုá ထိပ်á€á€”်းအဆင့် မျက်နှာပြင်အား ကိုင်ဆောင်သူမှ ပေါင်းစည်းရန် á€á€½á€„့်ပြုမည်ዠသာမန် အက်ပ်များá€á€½á€„်ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်ပါá‹"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"မိုဘိုင်းဆက်သွယ်ရေးá€á€”်ဆောင်မှုဌာန မှ ထည့်သွင်းပေးသော အá€á€¼á€±á€¡á€”ေများအား ပယ်ဖျက်á€á€¼á€„်း"</string>
- <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ကိုင်ဆောင်သူအားမိုဘိုင်းဆက်သွယ်ရေးá€á€”်ဆောင်မှုဌာနမှ ထည့်သွင်းထားá€á€²á€· အပြင်အဆင်အား ပယ်ဖျက်á€á€½á€„့် ပေးá€á€¼á€„်းዠပုံမှန် အပလီကေးရှင်းများမှာ မလိုပါ"</string>
+ <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ကိုင်ဆောင်သူအားမိုဘိုင်းဆက်သွယ်ရေးá€á€”်ဆောင်မှုဌာနမှ ထည့်သွင်းထားá€á€²á€· အပြင်အဆင်အား ပယ်ဖျက်á€á€½á€„့် ပေးá€á€¼á€„်းዠပုံမှန် အက်ပ်များအá€á€½á€€á€º ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်ပါá‹"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ကွန်ယက်အá€á€¼á€±á€¡á€”ေအား လေ့လာနေမှုအား နားထောင်á€á€½á€„့်"</string>
- <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"အက်ပ်ကို နက်á€á€±á€«á€· ပေါ်က အá€á€¼á€±á€¡á€”ေကို သá€á€­á€‘ားá€á€½á€„့် ပေးá€á€¼á€„်းáŠ. ပုံမှန် အက်ပ်များá€á€½á€„် မလိုအပ်ပါ"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"အပလီကေးရှင်းကို ကွန်ရက်ပေါ်က အá€á€¼á€±á€¡á€”ေစောင့်ကြည့်á€á€½á€„့်ပေးá€á€¼á€„်းአပုံမှန် အက်ပ်များá€á€½á€„် ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်ပါ"</string>
<string name="permlab_setInputCalibration" msgid="4902620118878467615">"change ထည့်သွင်းရေး ကိရိယာ á€á€­á€¯á€„်းထွာညှိနှိုင်းမှု ပြောင်းလဲá€á€¼á€„်း"</string>
- <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"အက်ပ်အား á€á€­á€¯á€·á€‘ိရေး မျက်နှာပြင် á€á€­á€¯á€„်းထွာစံညှိမှုကို မွမ်းမံá€á€½á€„့် ပြုသည်ዠသာမန် အက်ပ်များ ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်နိုင်ပါá‹"</string>
+ <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"အက်ပ်အား á€á€­á€¯á€·á€‘ိရေး မျက်နှာပြင် á€á€­á€¯á€„်းထွာစံညှိမှုကို မွမ်းမံá€á€½á€„့် ပြုသည်ዠသာမန် အက်ပ်များအá€á€½á€€á€º ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်နိုင်ပါá‹"</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM လက်မှá€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ရယူသုံးá€á€¼á€„်း"</string>
- <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"အက်ပ်á€á€…်á€á€¯á€¡á€¬á€¸ စီမံလုပ်ကိုင်á€á€½á€„့် DRM လက်မှá€á€ºá€™á€»á€¬á€¸ သုံးá€á€½á€„့် ပြုသည်ዠသာမန် အက်ပ်များ အá€á€½á€€á€º ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်နိုင်ပါá‹"</string>
+ <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"အပလီကေးရှင်းá€á€…်á€á€¯á€¡á€¬á€¸ စီမံလုပ်ကိုင်á€á€½á€„့် DRM လက်မှá€á€ºá€™á€»á€¬á€¸ သုံးá€á€½á€„့် ပြုသည်ዠသာမန် အက်ပ်များ အá€á€½á€€á€º ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်နိုင်ပါá‹"</string>
<string name="permlab_handoverStatus" msgid="7820353257219300883">"Android ရဲ့ အလင်းá€á€”်းထိုး လွှဲပြောင်းမှု အá€á€¼á€±á€¡á€”ေကို ရယူရန်"</string>
<string name="permdesc_handoverStatus" msgid="4788144087245714948">"ဒီအပလီကေးရှင်းအား အန်ဒရွိုက်á လက်ရှိ အလင်းá€á€”်းထိုး လွှဲပြောင်းမှု အကြောင်း အá€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯ ရယူá€á€½á€„့် ပြုသည်"</string>
<string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"DRM လက်မှá€á€ºá€™á€»á€¬á€¸ ဖယ်ရှားရန်"</string>
<string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"အပလီကေးရှင်းအား DRM လက်မှá€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ဖယ်ရှားá€á€½á€„့် ပြုသည်ዠသာမန် အက်ပ်များ အá€á€½á€€á€º ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်နိုင်ပါá‹"</string>
<string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"စာပို့စာယူ ဆက်သွယ်ရေးá€á€”်ဆောင်မှုá€á€…်á€á€¯á€¡á€¬á€¸ ပူးပေါင်းá€á€½á€„့်ပြုရန်"</string>
- <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"စာပို့စာယူဆက်သွယ်ရေးá€á€”်ဆောင်မှုá€á€…်á€á€¯á ထိပ်ဆုံးရှိအင်á€á€¬á€–ေ့စ်ဖြင့် ပူးပေါင်းရန် ပိုင်ရှင်အားá€á€½á€„့်ပြုပါዠပုံမှန် အက်ပ်များအá€á€½á€€á€º မလိုအပ်ပါá‹"</string>
+ <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"စာပို့စာယူဆက်သွယ်ရေးá€á€”်ဆောင်မှုá€á€…်á€á€¯á ထိပ်ဆုံးရှိအင်á€á€¬á€–ေ့စ်ဖြင့် ပူးပေါင်းရန် ပိုင်ရှင်အားá€á€½á€„့်ပြုပါዠပုံမှန် အက်ပ်များအá€á€½á€€á€º ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်ပါá‹"</string>
<string name="permlab_bindCarrierServices" msgid="3233108656245526783">"မိုဘိုင်းဖုန်းá€á€”်ဆောင်မှုပေးသူများနှင့် ပူးပေါင်းá€á€½á€„့်ပြုရန်"</string>
- <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"မိုဘိုင်းဖုန်းá€á€”်ဆောင်မှုစနစ်á€á€…်á€á€¯á€¡á€¬á€¸ ပူးပေါင်းá€á€½á€„့်ပြုရန် ကိုင်ဆောင်ထားသူအား á€á€½á€„့်ပြုပါዠသာမန် အက်ပ်များ အá€á€½á€€á€º မည်သည့်အá€á€«á€™á€»á€¾ မလိုအပ်ပါá‹"</string>
+ <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"မိုဘိုင်းဖုန်းá€á€”်ဆောင်မှုစနစ်á€á€…်á€á€¯á€¡á€¬á€¸ ပူးပေါင်းá€á€½á€„့်ပြုရန် ကိုင်ဆောင်ထားသူအား á€á€½á€„့်ပြုပါዠသာမန် အက်ပ်များ အá€á€½á€€á€º ဘယ်á€á€±á€¬á€·á€™á€¾ မလိုအပ်ပါá‹"</string>
<string name="permlab_access_notification_policy" msgid="4247510821662059671">"မနှောင့်ယှက်ရန်ကို အသုံးပြုမည်"</string>
<string name="permdesc_access_notification_policy" msgid="3296832375218749580">"မနှောင့်ယှက်ရန် á€á€»á€­á€”်ညှိမှုကို အပ်ဖ်များ ဖá€á€ºá€á€¼á€„်း ပြင်á€á€¼á€„်းပြုလုပ်နိုင်ရန် á€á€½á€„့်ပြုမည်á‹"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"စကားá€á€¾á€€á€ºá€…ည်းမျဥ်းကိုသá€á€ºá€™á€¾á€á€ºá€›á€”်"</string>
<string name="policydesc_limitPassword" msgid="2502021457917874968">"မျက်နှာပြင်သော့á€á€á€ºá€žá€Šá€·á€º စကားá€á€¾á€€á€ºá€™á€»á€¬á€¸á€”ှင့် PINများရှိ á€á€½á€„့်ပြုထားသည့် စာလုံးအရေအá€á€½á€€á€ºá€”ှင့် အက္á€á€›á€¬á€™á€»á€¬á€¸á€¡á€¬á€¸ ထိန်းá€á€»á€¯á€•်ရန်á‹"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"မော်နီá€á€¬á€™á€»á€€á€ºá€”ှာပြင်ဖွင့်ရန် ကြိုးစားá€á€½á€„့်များ"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"မျက်နှာပြင်ကို သော့ဖွင့်ရန် အá€á€½á€€á€º စကားá€á€¾á€€á€º မမှန်မကန် ထည့်သွင်းမှု အရေအá€á€½á€€á€ºá€€á€­á€¯ စောင့်ကြည့်လျက်አစကားá€á€¾á€€á€º ရိုက်ထည့်မှု သိပ်များနေလျှင် á€á€€á€ºá€˜á€œá€€á€ºá€€á€­á€¯ သော့á€á€á€ºá€›á€”် သို့မဟုá€á€º á€á€€á€ºá€˜á€œá€€á€º ဒေá€á€¬ အားလုံးကို ဖျက်ပစ်ရန်á‹"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"မျက်နှာပြင်ကို သော့ဖွင့်ရန် အá€á€½á€€á€º စကားá€á€¾á€€á€º မမှန်မကန် ထည့်သွင်းမှု အရေအá€á€½á€€á€ºá€€á€­á€¯ စောင့်ကြည့်လျက်አစကားá€á€¾á€€á€º ရိုက်ထည့်မှု သိပ်များနေလျှင် á€á€€á€ºá€˜á€œá€€á€ºá€€á€­á€¯ သော့á€á€á€ºá€›á€”် သို့မဟုá€á€º á€á€€á€ºá€˜á€œá€€á€º ဒေá€á€¬ အားလုံးကို ဖျက်ရန်á‹"</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"ဖန်မျက်နှာပြင်အား သော့ဖွင့်စဉ် လျှို့á€á€¾á€€á€ºá€€á€¯á€’်အမှားများ ရိုက်သွင်းမှုအား စောင့်ကြည့်ရန်နှင့်አလျှို့á€á€¾á€€á€ºá€€á€¯á€’်အမှားများ များစွာ ရိုက်သွင်းပါက á€á€®á€—ွီအား သော့á€á€»á€á€¼á€„်း သို့မဟုá€á€º á€á€®á€—ွီá အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ဖျက်ပစ်á€á€¼á€„်းများ ပြုရန်á‹"</string>
- <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"မျက်နှာပြင်ကို သော့ဖွင့်ရန် အá€á€½á€€á€º စကားá€á€¾á€€á€º မမှန်မကန် ထည့်သွင်းမှု အရေအá€á€½á€€á€ºá€€á€­á€¯ စောင့်ကြည့်လျက်አစကားá€á€¾á€€á€º ရိုက်ထည့်မှု သိပ်များနေလျှင် ဖုန်းကို သော့á€á€á€ºá€›á€”် သို့မဟုá€á€º ဖုန်း ဒေá€á€¬ အားလုံးကို ဖျက်ပစ်ရန်á‹"</string>
+ <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"မျက်နှာပြင်ကို သော့ဖွင့်ရန် အá€á€½á€€á€º စကားá€á€¾á€€á€º မမှန်မကန် ထည့်သွင်းမှု အရေအá€á€½á€€á€ºá€€á€­á€¯ စောင့်ကြည့်လျက်አစကားá€á€¾á€€á€º ရိုက်ထည့်မှု သိပ်များနေလျှင် ဖုန်းကို သော့á€á€á€ºá€›á€”် သို့မဟုá€á€º ဖုန်း ဒေá€á€¬ အားလုံးကို ဖျက်ရန်á‹"</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"ဖန်မျက်နှာပြင်အား သော့ဖွင့်စဉ် လျှို့á€á€¾á€€á€ºá€€á€¯á€’်အမှားများ ရိုက်သွင်းမှုအား စောင့်ကြည့်ရန်နှင့်አလျှို့á€á€¾á€€á€ºá€€á€¯á€’်အမှားများ များစွာ ရိုက်သွင်းပါက á€á€€á€ºá€˜á€œá€€á€ºá€¡á€¬á€¸ သော့á€á€»á€á€¼á€„်း သို့မဟုá€á€º á€á€€á€ºá€˜á€œá€€á€ºá အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ဖျက်ပစ်á€á€¼á€„်းများ ပြုလုပ်မည်á‹"</string>
<string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"ဖန်မျက်နှာပြင်အား သော့ဖွင့်စဉ် လျှို့á€á€¾á€€á€ºá€€á€¯á€’်အမှားများ ရိုက်သွင်းမှုအား စောင့်ကြည့်ရန်နှင့်አလျှို့á€á€¾á€€á€ºá€€á€¯á€’်အမှားများ များစွာ ရိုက်သွင်းပါက á€á€®á€—ွီအား သော့á€á€»á€á€¼á€„်း သို့မဟုá€á€º á€á€®á€—ွီá အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ဖျက်ပစ်á€á€¼á€„်းများ ပြုလုပ်မည်á‹"</string>
<string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"ဖန်မျက်နှာပြင်အား သော့ဖွင့်စဉ် လျှို့á€á€¾á€€á€ºá€€á€¯á€’်အမှားများ ရိုက်သွင်းမှုအား စောင့်ကြည့်ရန်နှင့်አလျှို့á€á€¾á€€á€ºá€€á€¯á€’်အမှားများ များစွာ ရိုက်သွင်းပါက ဖုန်းအား သော့á€á€»á€á€¼á€„်း သို့မဟုá€á€º ဖုန်းá အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ဖျက်ပစ်á€á€¼á€„်းများ ပြုလုပ်မည်á‹"</string>
@@ -657,7 +657,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"ပင်မစာမျက်နှာ"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"အလုပ်အကိုင်"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"á€á€á€¼á€¬á€¸"</string>
- <string name="quick_contacts_not_available" msgid="746098007828579688">"ဒီအဆက်အသွယ်အား ကြည့်ရှုရန် အက်ပ်မá€á€½á€±á€·á€•ါ"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"ဤအဆက်အသွယ်အား ကြည့်ရှုရန် အပလီကေးရှင်းမá€á€½á€±á€·á€•ါ"</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN ကုဒ် ရိုက်ထည့်ပါ"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK နှင့် PIN ကုဒ် အသစ်ကို ရိုက်ထည့်ပါ"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK နံပါá€á€º"</string>
@@ -771,7 +771,7 @@
<string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"ဒီစာမျက်နှာပေါ်မှာ ဆက်နေပါ"</string>
<string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nဒီစာမျက်နှာကနေ သွားဖို့ သေá€á€»á€¬á€•ါသလား?"</string>
<string name="save_password_label" msgid="6860261758665825069">"အá€á€Šá€ºá€•ြုသည်"</string>
- <string name="double_tap_toast" msgid="4595046515400268881">"အကြံပေးá€á€»á€€á€º: အကြီးအသေး á€á€»á€¯á€¶á€·áŠá€á€»á€²á€· ရန် နှစ်á€á€« á€á€­á€¯á€·á€•ါ"</string>
+ <string name="double_tap_toast" msgid="4595046515400268881">"အကြံပေးá€á€»á€€á€º- ဇူးမ်ဆွဲရန်နှင့် ဖြုá€á€ºá€›á€”် နှစ်ကြိမ်ဆက်á€á€­á€¯á€€á€º á€á€­á€¯á€·á€•ါ"</string>
<string name="autofill_this_form" msgid="4616758841157816676">"အလိုအလျောက်ဖြည့်ပါ"</string>
<string name="setup_autofill" msgid="7103495070180590814">"အလိုအလျောက်ဖြည့်ရန် သá€á€ºá€™á€¾á€á€ºá€žá€Šá€º"</string>
<string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
@@ -794,31 +794,31 @@
<string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"အပလီကေးရှင်းအား ဘရောင်ဇာမှ ယá€á€„် သွားရောက်ထားသော URLများአနေရာ အမှá€á€ºá€¡á€žá€¬á€¸á€™á€»á€¬á€¸á€¡á€¬á€¸ ကြည့်ရှုá€á€½á€„့်ပြုပါዠမှá€á€ºá€á€»á€€á€ºá‹ ဒီá€á€½á€„့်ပြုá€á€»á€€á€ºá€€á€­á€¯ á€á€á€­á€šá€•ါá€á€® ဘရောင်ဇာများ နှင့် á€á€á€¼á€¬á€¸ အပလီကေးရှင်းများမှ လုပ်ဆောင်မည် မဟုá€á€ºá€•ါá‹"</string>
<string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"သင့်ရဲ့ á€á€˜á€º အမှá€á€ºá€”ေရာများနှင့် သွားလာသော မှá€á€ºá€á€™á€ºá€¸ ရေးá€á€¼á€„်း"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"အပလီကေးရှင်းအား ဘရောင်ဇာမှ မှá€á€ºá€á€™á€ºá€¸ သို့ မှá€á€ºá€žá€¬á€¸á€™á€¾á€¯ အမှá€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ပြင်ဆင်á€á€½á€„့် ပေးá€á€¼á€„်းዠအပလီကေးရှင်းမှ ဘရောင်ဇာ မှá€á€ºá€á€™á€ºá€¸á€™á€»á€¬á€¸á€€á€­á€¯ ဖျက်ပစ်á€á€½á€„့် သို့ ပြင်ဆင်á€á€½á€„့် ရှိပါမည်ዠမှá€á€ºá€á€»á€€á€ºá‹ ဤá€á€½á€„့်ပြုá€á€»á€€á€ºá€€á€­á€¯ á€á€á€­á€šá€•ါá€á€® ဘရောင်ဇာများአá€á€á€¼á€¬á€¸ အပလီကေးရှင်းများမှ သုံးမည် မဟုá€á€ºá€•ါá‹"</string>
- <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"ဘရောင်ဇာáမှá€á€ºá€á€™á€ºá€¸ သို့မဟုá€á€º á€á€®á€—ွီá€á€½á€„်သိမ်းထားသည့် မှá€á€ºá€žá€¬á€¸á€á€»á€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ပြင်ဆင်ရန် အက်ပ်အား á€á€½á€„့်ပြုပါዠဤသို့ပြုá€á€¼á€„်းသည် ဘရောင်ဇာá အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ဖျက်ပစ်ရန် သို့မဟုá€á€º ပြင်ဆင်ရန် အက်ပ်အား á€á€½á€„့်ပြုထားá€á€¼á€„်းဖြစ်áዠမှá€á€ºá€á€»á€€á€ºáŠ á€¤á€žá€­á€¯á€·á€á€½á€„့်ပြုá€á€¼á€„်းသည် ပြင်ပဘရောင်ဇာများ သို့မဟုá€á€º á€á€˜á€ºá€¡á€¬á€¸ ကြည့်ရှုနိုင်သည့် á€á€…်á€á€¼á€¬á€¸á€žá€±á€¬ အပလီကေးရှင်းများအား သက်ရောက်မှုရှိမည် မဟုá€á€ºá€•ါá‹"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"ဘရောင်ဇာáမှá€á€ºá€á€™á€ºá€¸ သို့မဟုá€á€º á€á€®á€—ွီá€á€½á€„်သိမ်းထားသည့် မှá€á€ºá€žá€¬á€¸á€á€»á€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ပြင်ဆင်ရန် အက်ပ်အား á€á€½á€„့်ပြုပါዠဤသို့ပြုá€á€¼á€„်းသည် ဘရောင်ဇာá အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ဖျက်ရန် သို့မဟုá€á€º ပြင်ဆင်ရန် အက်ပ်အား á€á€½á€„့်ပြုထားá€á€¼á€„်းဖြစ်áዠမှá€á€ºá€á€»á€€á€ºáŠ á€¤á€žá€­á€¯á€·á€á€½á€„့်ပြုá€á€¼á€„်းသည် ပြင်ပဘရောင်ဇာများ သို့မဟုá€á€º á€á€˜á€ºá€¡á€¬á€¸ ကြည့်ရှုနိုင်သည့် á€á€…်á€á€¼á€¬á€¸á€žá€±á€¬ အပလီကေးရှင်းများအား သက်ရောက်မှုရှိမည် မဟုá€á€ºá€•ါá‹"</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"အပလီကေးရှင်းအား ဘရောင်ဇာမှ မှá€á€ºá€á€™á€ºá€¸ သို့ မှá€á€ºá€žá€¬á€¸á€™á€¾á€¯ အမှá€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸ ပြင်ဆင်á€á€½á€„့် ပေးá€á€¼á€„်းዠအပလီကေးရှင်းမှ ဘရောင်ဇာ မှá€á€ºá€á€™á€ºá€¸á€™á€»á€¬á€¸á€€á€­á€¯ ဖျက်ပစ်á€á€½á€„့် သို့ ပြင်ဆင်á€á€½á€„့် ရှိပါမည်ዠမှá€á€ºá€á€»á€€á€ºá‹ ဒီá€á€½á€„့်ပြုá€á€»á€€á€ºá€€á€­á€¯ á€á€á€­á€šá€•ါá€á€® ဘရောင်ဇာများአá€á€á€¼á€¬á€¸ အပလီကေးရှင်းများမှ သုံးမည် မဟုá€á€ºá€•ါá‹"</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"နှိုးစက်သá€á€ºá€™á€¾á€á€ºá€›á€”်"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"အက်ပ်အား á€á€•်ဆင်ထားသည့် နှိုးစက်နာရီ အက်ပ်ထဲá€á€½á€„် နှိုးစက်ကို သá€á€ºá€™á€¾á€á€ºá€á€½á€„့် ပြုသည်ዠအá€á€»á€­á€¯á€· နှိုးစက် အက်ပ်များက ထိုအင်္ဂါရပ်ကို ပြီးမြောက်အောင် မလုပ်နိုင်ကြပါá‹"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"အသံစာပို့စနစ်အားထည့်ရန်"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"အက်ပ်အား သင့် အသံမေးလ် á€á€„်စာသို့ စာများကို ထည့်á€á€½á€„့် ပြုသည်á‹"</string>
<string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ဘရောင်ဇာ ဘူမိဇုန်သá€á€ºá€™á€¾á€á€ºá€™á€¾á€¯ á€á€½á€„့်ပြုá€á€»á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ မွမ်းမံá€á€¼á€„်း"</string>
- <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"အက်ပ်အား ဘရောင်ဇာá ဘူမိဇုန်သá€á€ºá€™á€¾á€á€ºá€›á€±á€¸ á€á€½á€„့်ပြုá€á€»á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ မွမ်းမံá€á€½á€„့် ပြုသည်ዠကြံဖန် အက်ပ်များက áŽá€„်းကို အသုံးá€á€»á€•ြီး လိုရာ á€á€€á€ºá€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€žá€­á€¯á€· á€á€Šá€ºá€”ေရာ အá€á€»á€€á€ºá€¡á€œá€€á€º ပို့မှုကို လုပ်နိုင်သည်á‹"</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"အက်ပ်အား ဘရောင်ဇာá ဘူမိဇုန်သá€á€ºá€™á€¾á€á€ºá€›á€±á€¸ á€á€½á€„့်ပြုá€á€»á€€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ မွမ်းမံá€á€½á€„့်ပြုသည်ዠအဖျက်အက်ပ်များက áŽá€„်းကိုအသုံးá€á€»á€•ြီး လိုရာ á€á€˜á€ºá€†á€­á€¯á€€á€ºá€™á€»á€¬á€¸á€žá€­á€¯á€· á€á€Šá€ºá€”ေရာအá€á€»á€€á€ºá€¡á€œá€€á€º ပို့နိုင်သည်á‹"</string>
<string name="save_password_message" msgid="767344687139195790">"ဤလျှို့á€á€¾á€€á€ºá€…ကားá€á€¾á€€á€ºá€¡á€¬á€¸ ဘရောင်ဇာကိုမှá€á€ºá€á€­á€¯á€„်းမည်လား"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"ယá€á€¯á€™á€œá€¯á€•်ပါ"</string>
<string name="save_password_remember" msgid="6491879678996749466">"မှá€á€ºá€‘ားရန်"</string>
- <string name="save_password_never" msgid="8274330296785855105">"ကန့်သá€á€ºá€™á€¾á€¯á€™á€›á€¾á€­"</string>
+ <string name="save_password_never" msgid="8274330296785855105">"ဘယ်á€á€±á€¬á€·á€™á€¾"</string>
<string name="open_permission_deny" msgid="7374036708316629800">"သင့်ဆီမှာ ဒီစာမျက်နှာကို ဖွင့်ရန် á€á€½á€„့်ပြုá€á€»á€€á€º မရှိပါá‹"</string>
<string name="text_copied" msgid="4985729524670131385">"clipboardထံ စာသားအားကူးယူမည်"</string>
<string name="more_item_label" msgid="4650918923083320495">"နောက်ထပ်"</string>
<string name="prepend_shortcut_label" msgid="2572214461676015642">"Menu+"</string>
<string name="menu_space_shortcut_label" msgid="2410328639272162537">"space"</string>
<string name="menu_enter_shortcut_label" msgid="2743362785111309668">"enter"</string>
- <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"ဖျက်"</string>
+ <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"ဖျက်ရန်"</string>
<string name="search_go" msgid="8298016669822141719">"ရှာဖွေá€á€¼á€„်း"</string>
<string name="search_hint" msgid="1733947260773056054">"ရှာဖွေပါ..."</string>
<string name="searchview_description_search" msgid="6749826639098512120">"ရှာဖွေá€á€¼á€„်း"</string>
<string name="searchview_description_query" msgid="5911778593125355124">"ရှာစရာ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€”ေရာ"</string>
<string name="searchview_description_clear" msgid="1330281990951833033">"ရှာစရာ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸ ဖယ်ရှားရန်"</string>
- <string name="searchview_description_submit" msgid="2688450133297983542">"ရှာဖွေစရာ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯ အá€á€Šá€ºá€•ြုရန်"</string>
+ <string name="searchview_description_submit" msgid="2688450133297983542">"ရှာဖွေစရာ အá€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯ ပေးပို့ရန်"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"အသံဖြင့် ရှာဖွေá€á€¼á€„်း"</string>
<string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"ထိá€á€½á€±á€·á€•ြီး ရှာဖွေá€á€¼á€„်း ဖွင့်မည်မလား?"</string>
<string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> က ထိá€á€½á€±á€·á€•ြီး ရှာဖွေá€á€¼á€„်းကို လုပ်á€á€»á€„်ပါသည်ዠထိá€á€½á€±á€·á€›á€¾á€¬á€–ွေá€á€¼á€„်း ဖွင့်ထားလျှင် သင့်လက်ဖျားအောက်မှ အရာကို ကြားနိုင် သို့ ရှင်းလင်းá€á€»á€€á€ºá€€á€­á€¯ မြင်နိုင်á€á€²á€· အပြင် လက် အနေအထားဖြင့် á€á€€á€ºá€˜á€œá€€á€ºá€€á€­á€¯ ဆက်သွယ်ပြုလုပ်စေá€á€­á€¯á€„်းနိုင်ပါသည်"</string>
@@ -940,14 +940,14 @@
<string name="paste" msgid="5629880836805036433">"Paste"</string>
<string name="paste_as_plain_text" msgid="5427792741908010675">"စာသားအá€á€­á€¯á€„်း ကူးထည့်ပါ"</string>
<string name="replace" msgid="5781686059063148930">"အစားထိုá€á€¼á€„်း"</string>
- <string name="delete" msgid="6098684844021697789">"ဖျက်ပစ်ရန်"</string>
+ <string name="delete" msgid="6098684844021697789">"ဖျက်ရန်"</string>
<string name="copyUrl" msgid="2538211579596067402">"URLအား ကူးá€á€¼á€„်း"</string>
<string name="selectTextMode" msgid="1018691815143165326">"စာသား ရွေးရန်"</string>
<string name="undo" msgid="7905788502491742328">"ပြန်ဖျက်ရန်"</string>
<string name="redo" msgid="7759464876566803888">"ထပ်လုပ်ပါ"</string>
<string name="textSelectionCABTitle" msgid="5236850394370820357">"စာá€á€­á€¯á€›á€½á€±á€¸á€á€»á€šá€ºá€™á€¾á€¯"</string>
<string name="addToDictionary" msgid="4352161534510057874">"အဘိဓာန်ထဲ ထည့်ပါ"</string>
- <string name="deleteText" msgid="6979668428458199034">"ဖျက်ပစ်ရန်"</string>
+ <string name="deleteText" msgid="6979668428458199034">"ဖျက်ရန်"</string>
<string name="inputMethod" msgid="1653630062304567879">"ထည့်သွင်းရန်နည်းလမ်း"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"စာá€á€­á€¯ လုပ်ဆောင်á€á€»á€€á€º"</string>
<string name="low_internal_storage_view_title" msgid="5576272496365684834">"သိမ်းဆည်သော နေရာ နည်းနေပါသည်"</string>
@@ -977,7 +977,7 @@
<string name="whichSendApplicationLabel" msgid="4579076294675975354">"မျှá€á€±á€•ါ"</string>
<string name="whichSendToApplication" msgid="8272422260066642057">"ကိုအသုံးပြုá ပို့ပါ"</string>
<string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s ကိုအသုံးပြုá ပို့ပါ"</string>
- <string name="whichSendToApplicationLabel" msgid="8878962419005813500">"ပို့ပါ"</string>
+ <string name="whichSendToApplicationLabel" msgid="8878962419005813500">"ပို့ရန်"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"ပင်မ အက်ပ်ကို ရွေးပါ"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"%1$sကို ပင်မအဖြစ် သုံးပါ"</string>
<string name="whichHomeApplicationLabel" msgid="809529747002918649">"ဓာá€á€ºá€•ုံရိုက်ပါ"</string>
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"သိုလှောင်မှုအား ပြုပြင်á€á€¼á€„်းá‹"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android ကိုအဆင့်မြှင့်á€á€„်နေပါသည်"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"အဆင့်မြှင့်á€á€„်á€á€¼á€„်း မပြီးဆုံးသေးသá အá€á€»á€­á€¯á€·á€¡á€€á€ºá€•်များကို ကောင်းမွန်စွာအသုံးပြုနိုင်ဦးမည် မဟုá€á€ºá€•ါ"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> ထဲက အက်ပ်<xliff:g id="NUMBER_1">%2$d</xliff:g>ကို ဆီလျော်အောင် လုပ်နေ"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> အားပြင်ဆင်နေသည်á‹"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"အက်ပ်များကို စá€á€„်နေ"</string>
@@ -1077,8 +1079,8 @@
<string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"á€á€­á€¯á€„်ဖိုင်ကိုá€á€»á€­á€á€ºá€†á€€á€ºá€™á€›á€•ါ"</string>
<string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" အင်á€á€¬á€”က် ဆက်သွယ်မှု ကောင်းကောင်းမရှိပါ"</string>
<string name="wifi_connect_alert_title" msgid="8455846016001810172">"á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€€á€­á€¯ á€á€½á€„့်ပြုမလား?"</string>
- <string name="wifi_connect_alert_message" msgid="6451273376815958922">"အပ္ပလီကေးရှင်း %1$s သည် á€á€­á€¯á€„်ဖိုင်ကွန်ရက် %2$s ကိုá€á€»á€­á€á€ºá€†á€€á€ºá€œá€­á€¯á€žá€Šá€º"</string>
- <string name="wifi_connect_default_application" msgid="7143109390475484319">"အက်ပ်"</string>
+ <string name="wifi_connect_alert_message" msgid="6451273376815958922">"အပလီကေးရှင်း %1$s သည် á€á€­á€¯á€„်ဖိုင်ကွန်ရက် %2$s ကိုá€á€»á€­á€á€ºá€†á€€á€ºá€œá€­á€¯á€žá€Šá€º"</string>
+ <string name="wifi_connect_default_application" msgid="7143109390475484319">"အပလီကေးရှင်း"</string>
<string name="wifi_p2p_dialog_title" msgid="97611782659324517">"á€á€­á€¯á€€á€ºá€›á€­á€¯á€€á€º Wi-Fi"</string>
<string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"á€á€­á€¯á€€á€ºá€›á€­á€¯á€€á€ºWi-Fi ကို စá€á€„်ပါዠáŽá€„်းသည် Wi-Fi ဟော့စပေါ့ကို ရပ်ဆိုင်းစေမှာ ဖြစ်ပါသည်á‹"</string>
<string name="wifi_p2p_failed_message" msgid="3763669677935623084">"á€á€­á€¯á€€á€ºá€›á€­á€¯á€€á€ºá€á€­á€¯á€„်ဖိုင်ကို စá€á€„်လို့ မရပါ"</string>
@@ -1194,12 +1196,12 @@
<string name="permlab_readInstallSessions" msgid="3713753067455750349">"á€á€•်ဆင်ရေး လုပ်ကိုင်မှုကို ဖá€á€ºá€›á€”်"</string>
<string name="permdesc_readInstallSessions" msgid="2049771699626019849">"အပလီကေးရှင်းအား á€á€•်ဆင်ရေး á€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€™á€»á€¬á€¸á€€á€­á€¯ ဖá€á€ºá€á€½á€„့်ပြုသည်ዠáŽá€„်းသည် ဖွင့်သုံးနေသည့် အထုပ်အား á€á€•်ဆင်မှုဆိုင်ရာ အသေးိစá€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ ကြည့်ရှုá€á€½á€„့် ပြုသည်á‹"</string>
<string name="permlab_requestInstallPackages" msgid="5782013576218172577">"á€á€•်ဆင်ရေး အထုပ်များကို á€á€±á€¬á€„်းဆိုပါ"</string>
- <string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ပက်ကေ့များ သွင်းယူá€á€¼á€„်းအá€á€½á€€á€º á€á€±á€¬á€„်းဆိုရန် အပ္ပလီကေးရှင်းအား á€á€½á€„့်ပြုပါ"</string>
+ <string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ပက်ကေ့များ သွင်းယူá€á€¼á€„်းအá€á€½á€€á€º á€á€±á€¬á€„်းဆိုရန် အပလီကေးရှင်းအား á€á€½á€„့်ပြုပါ"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ဇူးမ်အသုံးပြုရန် နှစ်á€á€»á€€á€ºá€á€­á€¯á€·á€•ါ"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"á€á€’်ဂျက်ထည့်လို့ မရပါ"</string>
<string name="ime_action_go" msgid="8320845651737369027">"သွားပါ"</string>
<string name="ime_action_search" msgid="658110271822807811">"ရှာဖွေá€á€¼á€„်း"</string>
- <string name="ime_action_send" msgid="2316166556349314424">"ပို့á€á€¼á€„်း"</string>
+ <string name="ime_action_send" msgid="2316166556349314424">"ပို့ရန်"</string>
<string name="ime_action_next" msgid="3138843904009813834">"ရှေ့သို့"</string>
<string name="ime_action_done" msgid="8971516117910934605">"ပြီးပါပြီ"</string>
<string name="ime_action_previous" msgid="1443550039250105948">"အနောက်သို့"</string>
@@ -1235,13 +1237,13 @@
<string name="upload_file" msgid="2897957172366730416">"ဖိုင်ရွေးá€á€»á€šá€ºá€›á€”်"</string>
<string name="no_file_chosen" msgid="6363648562170759465">"မည်သည့်ဖိုင်ကိုမှမရွေးပါ"</string>
<string name="reset" msgid="2448168080964209908">"ပြန်လည်သá€á€ºá€™á€¾á€á€ºá€›á€”်"</string>
- <string name="submit" msgid="1602335572089911941">"á€á€„်​ပြရန်​"</string>
+ <string name="submit" msgid="1602335572089911941">"ပေးပို့ရန်"</string>
<string name="car_mode_disable_notification_title" msgid="3164768212003864316">"ကားထဲá€á€½á€„်အသုံးပြုနိုင်သောစနစ် ရရှိနိုင်သည်"</string>
<string name="car_mode_disable_notification_message" msgid="6301524980144350051">"ကားမောင်းနှင်á€á€¼á€„်းမုဒ်မှ ထွက်ရန် á€á€­á€¯á€·á€•ါá‹"</string>
<string name="tethered_notification_title" msgid="3146694234398202601">"á€á€†á€„့်ပြန်လည်လွှင့်á€á€¼á€„်း သို့မဟုá€á€º ဟော့စပေါ့ ဖွင့်ထားသည်"</string>
<string name="tethered_notification_message" msgid="2113628520792055377">"စနစ်ထည့်သွင်းရန် á€á€­á€¯á€·á€•ါá‹"</string>
<string name="back_button_label" msgid="2300470004503343439">"နောက်သို့"</string>
- <string name="next_button_label" msgid="1080555104677992408">"နောက်"</string>
+ <string name="next_button_label" msgid="1080555104677992408">"ရှေ့သို့"</string>
<string name="skip_button_label" msgid="1275362299471631819">"ကျော်"</string>
<string name="no_matches" msgid="8129421908915840737">"ထပ်á€á€°á€™á€á€½á€±á€·á€›á€¾á€­á€•ါ"</string>
<string name="find_on_page" msgid="1946799233822820384">"စာမျက်နှာá€á€½á€„်ရှာဖွေရန်"</string>
@@ -1254,7 +1256,7 @@
<string name="progress_erasing" product="default" msgid="6596988875507043042">"SD ကဒ် အား ဖျက်နေစဉ်…"</string>
<string name="share" msgid="1778686618230011964">"မျှá€á€±á€á€¼á€„်း"</string>
<string name="find" msgid="4808270900322985960">"ရှာဖွေရန်"</string>
- <string name="websearch" msgid="4337157977400211589">"á€á€€á€ºá€˜á€ºá€•ေါ်မှာ ရှာဖွေရန်"</string>
+ <string name="websearch" msgid="4337157977400211589">"á€á€˜á€ºá€á€½á€„် ရှာရန်"</string>
<string name="find_next" msgid="5742124618942193978">"နောက်á€á€…်á€á€¯ ရှာဖွေရန်"</string>
<string name="find_previous" msgid="2196723669388360506">"အရင်á€á€…်á€á€¯ ရှာဖွေရန်"</string>
<string name="gpsNotifTicker" msgid="5622683912616496172">"<xliff:g id="NAME">%s</xliff:g>မှ á€á€Šá€ºá€”ေရာအား á€á€±á€¬á€„်းá€á€¶á€žá€Šá€º"</string>
@@ -1290,7 +1292,7 @@
<string name="date_picker_next_month_button" msgid="5559507736887605055">"လာမည့် လ"</string>
<string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Altá€á€œá€¯á€á€º"</string>
<string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"မလုပ်á€á€±á€¬á€· á€á€œá€¯á€á€º"</string>
- <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ဖျက်ရန်á€á€œá€¯á€á€º"</string>
+ <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ဖျက်ရန်"</string>
<string name="keyboardview_keycode_done" msgid="1992571118466679775">"ပြီးဆုံးသည့်á€á€œá€¯á€á€º"</string>
<string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"စနစ်ပြောင်းá€á€¼á€„်းá€á€œá€¯á€á€º"</string>
<string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shiftá€á€œá€¯á€á€º"</string>
@@ -1427,7 +1429,7 @@
<string name="owner_name" msgid="2716755460376028154">"ပိုင်ရှင်"</string>
<string name="error_message_title" msgid="4510373083082500195">"အမှား"</string>
<string name="error_message_change_not_allowed" msgid="1347282344200417578">"ဒီအပြောင်းအလဲမျိုးကို သင့် စီမံအုပ်á€á€»á€¯á€•်သူမှ á€á€½á€„့်မပြုပါ"</string>
- <string name="app_not_found" msgid="3429141853498927379">"ဤလုပ်ဆောင်á€á€»á€€á€ºá€€á€­á€¯ ပြုလုပ်ပေးမည့် အက်ပ်မရှိပါá‹"</string>
+ <string name="app_not_found" msgid="3429141853498927379">"ဤလုပ်ဆောင်á€á€»á€€á€ºá€€á€­á€¯ ပြုလုပ်ပေးမည့် အပလီကေးရှင်းမရှိပါá‹"</string>
<string name="revoke" msgid="5404479185228271586">"မလုပ်á€á€±á€¬á€·á€•ါ"</string>
<string name="mediasize_iso_a0" msgid="1994474252931294172">"အိုက်အက်စ်အို အေ á€"</string>
<string name="mediasize_iso_a1" msgid="3333060421529791786">"အိုက်အက်စ်အို အေá"</string>
@@ -1553,8 +1555,8 @@
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ပင်မဖြုá€á€ºá€™á€®á€™á€¾á€¬ စကားá€á€¾á€€á€ºá€€á€­á€¯ မေးကြည့်ရန်"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"သင့် အက်ဒမင်မှ သွင်းယူထားá"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"သင့်စီမံá€á€”့်á€á€½á€²á€žá€°á€™á€¾ အဆင့်မြှင့်ထားပါသည်á‹"</string>
- <string name="package_deleted_device_owner" msgid="7650577387493101353">"သင့် အက်ဒမင်အား ဖျက်ပစ်ရန်"</string>
- <string name="battery_saver_description" msgid="1960431123816253034">"ဘက်ထရီသက်á€á€™á€ºá€¸ ကြာရှည်á€á€¶á€›á€”်አဘက်ထရီအားထိန်းသည် သင့်ကိရိယာá ဆောင်ရွက်á€á€»á€€á€ºá€€á€­á€¯ လျှော့ပေးပြီး á€á€¯á€”်á€á€«á€™á€¾á€¯áŠ á€á€Šá€ºá€”ေရာá€á€”်ဆောင်မှုများနှင့်አနောက်á€á€¶á€’ေá€á€¬á€¡á€™á€»á€¬á€¸á€…ုကို ကန့်သá€á€ºá€•ေးáዠစင့်လုပ်ပေးရလေ့ရှိသည့် အီးမေးလ်አစာပို့á€á€¼á€„်းနှင့်አအá€á€¼á€¬á€¸á€¡á€•လီကေးရှင်းများကို áŽá€„်းá€á€­á€¯á€·á€¡á€¬á€¸ သင် ဖွင့်မှသာ အဆင့်မြှင့်မွမ်းမံမည်ဖြစ်áá‹ \n\n ကိရိယာအား အားသွင်းနေစဉ် ဘက်ထရီအားထိန်းအား အလိုအလျောက် ပိá€á€ºá€‘ားသည်á‹"</string>
+ <string name="package_deleted_device_owner" msgid="7650577387493101353">"သင့် အက်ဒမင်အား ဖျက်ရန်"</string>
+ <string name="battery_saver_description" msgid="1960431123816253034">"ဘက်ထရီသက်á€á€™á€ºá€¸ ကြာရှည်á€á€¶á€›á€”်አဘက်ထရီအားထိန်းသည် သင့်ကိရိယာá ဆောင်ရွက်á€á€»á€€á€ºá€€á€­á€¯ လျှော့ပေးပြီး á€á€¯á€”်á€á€«á€™á€¾á€¯áŠ á€á€Šá€ºá€”ေရာá€á€”်ဆောင်မှုများနှင့်አနောက်á€á€¶á€’ေá€á€¬á€¡á€™á€»á€¬á€¸á€…ုကို ကန့်သá€á€ºá€•ေးáዠစင့်လုပ်ပေးရလေ့ရှိသည့် အီးမေးလ်አစာပို့á€á€¼á€„်းနှင့်አအá€á€¼á€¬á€¸á€¡á€•လီကေးရှင်းများကို áŽá€„်းá€á€­á€¯á€·á€¡á€¬á€¸ သင် ဖွင့်မှသာ အပ်ဒိá€á€ºá€œá€¯á€•်မည်ဖြစ်áá‹ \n\n ကိရိယာအား အားသွင်းနေစဉ် ဘက်ထရီအားထိန်းအား အလိုအလျောက် ပိá€á€ºá€‘ားသည်á‹"</string>
<string name="data_saver_description" msgid="6015391409098303235">"ဒေá€á€¬á€¡á€žá€¯á€¶á€¸á€œá€»á€¾á€±á€¬á€·á€á€»á€”ိုင်ရန် အက်ပ်များကို နောက်á€á€¶á€á€½á€„် ဒေá€á€¬á€•ို့á€á€¼á€„်းနှင့် လက်á€á€¶á€á€¼á€„်းမရှိစေရန် ဒေá€á€¬á€á€»á€½á€±á€á€¬á€™á€¾á€¯á€…နစ်က á€á€¬á€¸á€†á€®á€¸á€‘ားပါသည်ዠယá€á€¯á€¡á€€á€ºá€•်ဖြင့် ဒေá€á€¬á€¡á€žá€¯á€¶á€¸á€•ြုနိုင်သော်လည်း အကြိမ်လျှော့áသုံးရပါမည်ዠဥပမာአသင် မá€á€­á€¯á€·á€™á€á€»á€„်း ပုံများပေါ်လာမည် မဟုá€á€ºá€•ါá‹"</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"ဒေá€á€¬á€¡á€žá€¯á€¶á€¸á€•ြုမှု á€á€»á€½á€±á€á€¬á€™á€¾á€¯á€…နစ်ကို ဖွင့်မလားá‹"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"ဖွင့်ပါ"</string>
@@ -1662,5 +1664,5 @@
<string name="audit_safemode_notification" msgid="6416076898350685856">"ဤစက်ပစ္စည်းကို ကန့်သá€á€ºá€á€»á€€á€ºá€™á€»á€¬á€¸á€™á€•ါဘဲ အသုံးပြုရန် စက်ရုံထုá€á€ºá€†á€€á€ºá€á€„်အá€á€­á€¯á€„်း ပြန်လည်သá€á€ºá€™á€¾á€á€ºá€•ါ"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"ပိုမိုလေ့လာရန် á€á€­á€¯á€·á€•ါá‹"</string>
<string name="suspended_widget_accessibility" msgid="6712143096475264190">"ပိá€á€ºá€‘ားသည့် <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="conference_call" msgid="3751093130790472426">"လူအမြောက်အများá€á€•ြိုင်နက် á€á€±á€«á€ºá€†á€­á€¯á€™á€¾á€¯"</string>
+ <string name="conference_call" msgid="3751093130790472426">"လူအမြောက်အမြားá€á€•ြိုင်နက် á€á€±á€«á€ºá€†á€­á€¯á€™á€¾á€¯"</string>
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b53d86c212c3..d2e4d7162da4 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimaliser lagring."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android oppgraderes"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Noen apper fungerer kanskje ikke skikkelig før oppgraderingen er fullført"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimaliserer app <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Forbereder <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Starter apper."</string>
@@ -1201,7 +1203,7 @@
<string name="ime_action_search" msgid="658110271822807811">"Søk"</string>
<string name="ime_action_send" msgid="2316166556349314424">"Send"</string>
<string name="ime_action_next" msgid="3138843904009813834">"Neste"</string>
- <string name="ime_action_done" msgid="8971516117910934605">"Utført"</string>
+ <string name="ime_action_done" msgid="8971516117910934605">"Ferdig"</string>
<string name="ime_action_previous" msgid="1443550039250105948">"Forrige"</string>
<string name="ime_action_default" msgid="2840921885558045721">"Utfør"</string>
<string name="dial_number_using" msgid="5789176425167573586">"Ring nummeret\n<xliff:g id="NUMBER">%s</xliff:g>"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 8f382968adea..b3de0aaec8c4 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1030,6 +1030,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"भणà¥à¤¡à¤¾à¤°à¤£ अनà¥à¤•ूलन गरà¥à¤¦à¥ˆà¥¤"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android को सà¥à¤¤à¤°à¤µà¥ƒà¤¦à¥à¤§à¤¿ हà¥à¤à¤¦à¥ˆà¤›"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"सà¥à¤¤à¤°à¤µà¥ƒà¤¦à¥à¤§à¤¿ समà¥à¤ªà¤¨à¥à¤¨ नभà¤à¤¸à¤®à¥à¤® केही अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—हरू रामà¥à¤°à¤°à¥€ काम नगरà¥à¤¨ सकà¥à¤›à¤¨à¥"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤— अनà¥à¤•à¥à¤² हà¥à¤à¤¦à¥ˆ <xliff:g id="NUMBER_0">%1$d</xliff:g> को <xliff:g id="NUMBER_1">%2$d</xliff:g>।"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> तयारी गरà¥à¤¦à¥ˆà¥¤"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"सà¥à¤°à¥à¤µà¤¾à¤¤ अनà¥à¤ªà¥à¤°à¤¯à¥‹à¤—हरू।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index d43d6c625cfe..f23d046595dc 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Opslagruimte wordt geoptimaliseerd."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android wordt geüpgraded"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Sommige apps werken mogelijk pas correct nadat de upgrade is voltooid"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g> optimaliseren."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> voorbereiden."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Apps starten."</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index bea0682ae385..d96b89eb725e 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"ਸਟੋਰੇਜ ਅਨà©à¨•ੂਲ ਕਰ ਰਿਹਾ ਹੈ।"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android ਅੱਪਗà©à¨°à©‡à¨¡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਕà©à¨ à¨à¨ªà¨¾à¨‚ ਅੱਪਗà©à¨°à©‡à¨¡ ਦੇ ਪੂਰੀ ਹੋਣ ਤੱਕ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰਨ"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> <xliff:g id="NUMBER_1">%2$d</xliff:g> ਦਾ à¨à¨ª ਅਨà©à¨•ੂਲ ਕਰ ਰਿਹਾ ਹੈ।"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> ਤਿਆਰ ਕਰ ਰਿਹਾ ਹੈ।"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"à¨à¨ªà¨¸ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index cff4fe4076c7..dcbf9d042b89 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1070,6 +1070,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optymalizacja pamięci."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android jest uaktualniany"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Niektóre aplikacje mogą nie działać prawidłowo, dopóki nie zakończy się aktualizacja."</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optymalizowanie aplikacji <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"PrzygotowujÄ™ aplikacjÄ™ <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Uruchamianie aplikacji."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index f5b2389cc490..6998871d0d14 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Otimizando o armazenamento."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"O Android está sendo atualizado"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Alguns apps podem não funcionar corretamente até que a atualização seja concluída"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Otimizando app <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando apps."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3079a611589f..1e96a4d28bca 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"A otimizar o armazenamento."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"O Android está a ser atualizado"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Algumas aplicações podem não funcionar corretamente enquanto a atualização não for concluída"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"A otimizar a aplicação <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"A preparar o <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"A iniciar aplicações"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index f5b2389cc490..6998871d0d14 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Otimizando o armazenamento."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"O Android está sendo atualizado"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Alguns apps podem não funcionar corretamente até que a atualização seja concluída"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Otimizando app <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Preparando <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Iniciando apps."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 0cb12af35a66..0058858484b8 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1047,6 +1047,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Se optimizează stocarea."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android face upgrade"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Este posibil ca unele aplicații să nu funcționeze corespunzător până când nu se finalizează upgrade-ul"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Se optimizează aplicația <xliff:g id="NUMBER_0">%1$d</xliff:g> din <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Se pregătește <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Se pornesc aplicațiile."</string>
diff --git a/core/res/res/values-round-watch/dimens_material.xml b/core/res/res/values-round-watch/dimens_material.xml
index a417d1951a7f..db1f1f34638b 100644
--- a/core/res/res/values-round-watch/dimens_material.xml
+++ b/core/res/res/values-round-watch/dimens_material.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<resources>
- <dimen name="dialog_padding_material">32dp</dimen>
- <dimen name="preference_fragment_padding_vertical_material">22dp</dimen>
+ <dimen name="dialog_padding_material">@dimen/screen_percentage_15</dimen>
+ <dimen name="preference_fragment_padding_vertical_material">@dimen/screen_percentage_15</dimen>
- <dimen name="list_item_padding_horizontal_material">32dp</dimen>
- <dimen name="list_item_padding_start_material">40dp</dimen>
- <dimen name="list_item_padding_end_material">24dp</dimen>
+ <dimen name="list_item_padding_horizontal_material">@dimen/screen_percentage_15</dimen>
+ <dimen name="list_item_padding_start_material">@dimen/screen_percentage_15</dimen>
+ <dimen name="list_item_padding_end_material">@dimen/screen_percentage_10</dimen>
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index abd901251c11..e202854e5972 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1020,7 +1020,7 @@
<string name="whichEditApplicationLabel" msgid="7183524181625290300">"Изменить"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"ПоделитьÑÑ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ:"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"ПоделитьÑÑ Ñ‡ÐµÑ€ÐµÐ· %1$s"</string>
- <string name="whichSendApplicationLabel" msgid="4579076294675975354">"Открыть доÑтуп"</string>
+ <string name="whichSendApplicationLabel" msgid="4579076294675975354">"ПоделитьÑÑ"</string>
<string name="whichSendToApplication" msgid="8272422260066642057">"Выберите приложение"</string>
<string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Отправка Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ %1$s"</string>
<string name="whichSendToApplicationLabel" msgid="8878962419005813500">"Отправить"</string>
@@ -1070,6 +1070,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"ÐžÐ¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð°â€¦"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Обновление Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ‹ неполадки в работе приложений."</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"ÐžÐ¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ <xliff:g id="NUMBER_0">%1$d</xliff:g> из <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Подготовка Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ \"<xliff:g id="APPNAME">%1$s</xliff:g>\"..."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"ЗапуÑк приложений."</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index c64d1edf7820..9240212eadcc 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1026,6 +1026,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"ආචයනය à¶´à·Šâ€à¶»à·à·ƒà·Šà¶­à·’කරණය කිරීම."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android à¶‹à¶­à·Šà·à·Šâ€à¶»à·šà¶«à·’ කරමින්"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"à¶‹à¶­à·Šà·à·Šâ€à¶»à·šà¶«à·’ කිරීම අවසන් වන තෙක් සමහර යෙදුම් නිසි ලෙස à¶šà·Šâ€à¶»à·’ය෠නොකළ à·„à·à¶šà·’ය"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g> කින් <xliff:g id="NUMBER_0">%1$d</xliff:g> à·€à·à¶±à·’ යෙදුම à¶´à·Šâ€à¶»à·à·ƒà·Šà¶­ කරමින්."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> සූදà·à¶±à¶¸à·Š කරමින්."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"යෙදුම් ආරම්භ කරමින්."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 97180db4b525..e077075b0258 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1070,6 +1070,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimalizuje sa úložisko"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Prebieha inovácia systému Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Niektoré aplikácie môžu správne fungovaÅ¥ až po dokonÄení inovácie"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Prebieha optimalizácia aplikácie <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Pripravuje sa aplikácia <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Prebieha spúšťanie aplikácií."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 9653ff851e26..e1eea815a692 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1070,6 +1070,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Optimiziranje shrambe."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Poteka nadgradnja Androida."</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Nekatere aplikacije morda ne bodo delovale pravilno, dokler ne bo dokonÄana nadgradnja."</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimiranje aplikacije <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Pripravljanje aplikacije <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Zagon aplikacij."</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index d9b14dc36c87..5ad7ba4e6561 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Po përshtat ruajtjen."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android po përmirësohet"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Disa aplikacione mund të mos funksionojnë si duhet deri sa të përfundojë përmirësimi"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Po përshtat aplikacionin <xliff:g id="NUMBER_0">%1$d</xliff:g> nga gjithsej <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Po përgatit <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Aplikacionet e fillimit."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b3fc8caaf80c..7bfc3ddaf3cb 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1047,6 +1047,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Меморија Ñе оптимизује."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android Ñе надограђује…"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Ðеке апликације можда неће иÑправно функциониÑати док Ñе надоградња не доврши"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Оптимизовање апликације <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Припрема Ñе <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Покретање апликација."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 8557f28da30d..86733605a083 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Lagringsutrymmet optimeras."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android uppgraderas"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"En del appar kanske inte fungerar som de ska innan uppgraderingen har slutförts"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Optimerar app <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> förbereds."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Appar startas."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 30f22ffa4618..71d9bf75e707 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1022,6 +1022,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Inaboresha hifadhi."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Tunasasisha Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Huenda baadhi ya programu zisifanye kazi vizuri hadi itakapomaliza kusasisha"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Inaboresha programu <xliff:g id="NUMBER_0">%1$d</xliff:g> kutoka <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Inaandaa <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Programu zinaanza"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index f6060009d4d0..823286cab455 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"சேமிபà¯à®ªà®•தà¯à®¤à¯ˆ உகநà¯à®¤à®¤à®¾à®•à¯à®•à¯à®•ிறதà¯."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•ிறதà¯"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"மேமà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯à®µà®¤à¯ à®®à¯à®Ÿà®¿à®¯à¯à®®à¯ வரை, சில பயனà¯à®ªà®¾à®Ÿà¯à®•ள௠சரியாக வேலைசெயà¯à®¯à®¾à®®à®²à¯ போககà¯à®•ூடà¯à®®à¯"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> பயனà¯à®ªà®¾à®Ÿà¯à®Ÿà¯ˆ à®’à®°à¯à®™à¯à®•ிணைகà¯à®•ிறதà¯."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>à®à®¤à¯ தயாரà¯à®šà¯†à®¯à¯à®•ிறதà¯."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"பயனà¯à®ªà®¾à®Ÿà¯à®•ள௠தொடஙà¯à®•பà¯à®ªà®Ÿà¯à®•ினà¯à®±à®©."</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 56c2eace7ebd..6218cdfeef0a 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"నిలà±à°µà°¨à± à°…à°¨à±à°•ూలపరà±à°¸à±à°¤à±‹à°‚ది."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android à°…à°ªà±â€Œà°—à±à°°à±‡à°¡à± à°…à°µà±à°¤à±‹à°‚ది"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"à°…à°ªà±â€Œà°—à±à°°à±‡à°¡à± పూరà±à°¤à°¯à±à°¯à±‡ వరకౠకొనà±à°¨à°¿ à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°²à± సరిగà±à°—à°¾ పని చేయకపోవచà±à°šà±"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_1">%2$d</xliff:g>లో <xliff:g id="NUMBER_0">%1$d</xliff:g> à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°¨à±à°¨à°¿ à°…à°¨à±à°•ూలీకరిసà±à°¤à±‹à°‚ది."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g>ని సిదà±à°§à°‚ చేసà±à°¤à±‹à°‚ది."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"à°…à°¨à±à°µà°°à±à°¤à°¨à°¾à°²à°¨à± à°ªà±à°°à°¾à°°à°‚à°­à°¿à°¸à±à°¤à±‹à°‚ది."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b64eb8f91d45..2dfd2e7b1e59 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"à¸à¸³à¸¥à¸±à¸‡à¹€à¸žà¸´à¹ˆà¸¡à¸›à¸£à¸°à¸ªà¸´à¸—ธิภาพพื้นที่จัดเà¸à¹‡à¸šà¸‚้อมูล"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android à¸à¸³à¸¥à¸±à¸‡à¸­à¸±à¸›à¹€à¸à¸£à¸”"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"à¹à¸­à¸›à¸šà¸²à¸‡à¹à¸­à¸›à¸­à¸²à¸ˆà¸—ำงานไม่ถูà¸à¸•้องจนà¸à¸§à¹ˆà¸²à¸ˆà¸°à¸­à¸±à¸›à¹€à¸à¸£à¸”เสร็จ"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"à¸à¸³à¸¥à¸±à¸‡à¹€à¸žà¸´à¹ˆà¸¡à¸›à¸£à¸°à¸ªà¸´à¸—ธิภาพà¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชัน <xliff:g id="NUMBER_0">%1$d</xliff:g> จาภ<xliff:g id="NUMBER_1">%2$d</xliff:g> รายà¸à¸²à¸£"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"à¸à¸³à¸¥à¸±à¸‡à¹€à¸•รียม <xliff:g id="APPNAME">%1$s</xliff:g>"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"à¸à¸³à¸¥à¸±à¸‡à¹€à¸£à¸´à¹ˆà¸¡à¸•้นà¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชัน"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 7c91c681d457..855399280406 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Ino-optimize ang storage."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Nag-a-upgrade ang Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Maaaring hindi gumana nang maayos ang ilang app hangga\'t hindi pa natatapos ang pag-upgrade"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Ino-optimize ang app <xliff:g id="NUMBER_0">%1$d</xliff:g> ng <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Ihinahanda ang <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Sinisimulan ang apps."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 805f1d203fd3..1033e11d4610 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Depolama optimize ediliyor."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android yeni sürüme geçiriliyor"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Yeni sürüme geçiş işlemi tamamlanana kadar bazı uygulamalar düzgün çalışmayabilir"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> uygulama optimize ediliyor."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> hazırlanıyor."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Uygulamalar başlatılıyor"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 66949814b9f4..21c1e3f0f1ca 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1070,6 +1070,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"ÐžÐ¿Ñ‚Ð¸Ð¼Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð¿Ð°Ð¼â€™Ñті."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android оновлюєтьÑÑ"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"ДеÑкі додатки можуть не працювати належним чином, доки не завершитьÑÑ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"ÐžÐ¿Ñ‚Ð¸Ð¼Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸ <xliff:g id="NUMBER_0">%1$d</xliff:g> з <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Підготовка додатка <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"ЗапуÑк програм."</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 651d9ea228e2..ff99fb00c491 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"اسٹوریج Ú©Ùˆ Ø¨ÛØªØ±ÛŒÙ† بنایا جا Ø±ÛØ§ ÛÛ’Û”"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"â€Android اپ گریڈ ÛÙˆ Ø±ÛØ§ ÛÛ’"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"اپ گریڈ ختم Ûونے تک شاید Ú©Ú†Ú¾ ایپس ٹھیک طرح سے کام Ù†Û Ú©Ø±ÛŒÚº"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"ایپ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g> Ú©Ùˆ Ø¨ÛØªØ± بنایا جا Ø±ÛØ§ ÛÛ’Û”"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> تیار ÛÙˆ رÛÛŒ ÛÛ’Û”"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"ایپس شروع ÛÙˆ رÛÛŒ Ûیں۔"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 03d16b757e7e..194b506ace46 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Xotira optimallashtirilmoqda."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android yangilanmoqda"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Yangilanish vaqtida ba’zi ilovalar to‘g‘ri ishlamasligi mumkin"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Ilovalar optimallashtirilmoqda (<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>)."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> tayyorlanmoqda."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Ilovalar ishga tushirilmoqda."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index a302ae445e6a..4ce86cf5c15b 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Tối ưu hóa lưu trữ."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android đang nâng cấp"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Má»™t số ứng dụng có thể không hoạt động bình thưá»ng cho đến khi nâng cấp xong"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Äang tối ưu hóa ứng dụng <xliff:g id="NUMBER_0">%1$d</xliff:g> trong tổng số <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Äang chuẩn bị <xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Khởi động ứng dụng."</string>
diff --git a/packages/SystemUI/res/layout/night_mode_settings.xml b/core/res/res/values-w194dp/dimens_material.xml
index 3725e78cc481..220c4b00232c 100644
--- a/packages/SystemUI/res/layout/night_mode_settings.xml
+++ b/core/res/res/values-w194dp/dimens_material.xml
@@ -13,12 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <include layout="@layout/switch_bar" />
-
-</LinearLayout>
+<resources>
+ <dimen name="screen_percentage_05">9.7dp</dimen>
+ <dimen name="screen_percentage_10">19.4dp</dimen>
+ <dimen name="screen_percentage_15">29.1dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/xml/color_and_appearance.xml b/core/res/res/values-w205dp/dimens_material.xml
index 21f890eb058d..94907ee51dcc 100644
--- a/packages/SystemUI/res/xml/color_and_appearance.xml
+++ b/core/res/res/values-w205dp/dimens_material.xml
@@ -13,18 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:sysui="http://schemas.android.com/apk/res-auto"
- android:title="@string/color_and_appearance">
-
- <Preference
- android:key="night_mode"
- android:title="@string/night_mode"
- android:fragment="com.android.systemui.tuner.NightModeFragment" />
-
- <com.android.systemui.tuner.CalibratePreference
- android:key="calibrate"
- android:title="@string/calibrate_display" />
-
-</PreferenceScreen>
+<resources>
+ <dimen name="screen_percentage_05">10.25dp</dimen>
+ <dimen name="screen_percentage_10">20.5dp</dimen>
+ <dimen name="screen_percentage_15">30.75dp</dimen>
+</resources>
diff --git a/core/res/res/values-w213dp/dimens_material.xml b/core/res/res/values-w213dp/dimens_material.xml
new file mode 100644
index 000000000000..8a4e3a08ea13
--- /dev/null
+++ b/core/res/res/values-w213dp/dimens_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <dimen name="screen_percentage_05">10.65dp</dimen>
+ <dimen name="screen_percentage_10">21.3dp</dimen>
+ <dimen name="screen_percentage_15">31.95dp</dimen>
+</resources>
diff --git a/core/res/res/values-w228dp/dimens_material.xml b/core/res/res/values-w228dp/dimens_material.xml
new file mode 100644
index 000000000000..a2009754d95b
--- /dev/null
+++ b/core/res/res/values-w228dp/dimens_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <dimen name="screen_percentage_05">11.4dp</dimen>
+ <dimen name="screen_percentage_10">22.8dp</dimen>
+ <dimen name="screen_percentage_15">34.2dp</dimen>
+</resources>
diff --git a/core/res/res/values-w240dp/dimens_material.xml b/core/res/res/values-w240dp/dimens_material.xml
new file mode 100644
index 000000000000..a4b58fa95c50
--- /dev/null
+++ b/core/res/res/values-w240dp/dimens_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <dimen name="screen_percentage_05">12dp</dimen>
+ <dimen name="screen_percentage_10">24dp</dimen>
+ <dimen name="screen_percentage_15">36dp</dimen>
+</resources>
diff --git a/core/res/res/values-watch/colors_material.xml b/core/res/res/values-watch/colors_material.xml
index 91eee7d0039f..45eb9812f137 100644
--- a/core/res/res/values-watch/colors_material.xml
+++ b/core/res/res/values-watch/colors_material.xml
@@ -20,5 +20,7 @@
<color name="accent_material_dark">#ff5e97f6</color>
<color name="accent_material_light">#ff4285f4</color>
+ <color name="primary_material_dark">#4D4D4D</color>
+
<color name="button_material_dark">#ff999999</color>
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index b5b87c7748d6..3b2abe78a544 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"正在优化存储空间。"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"Android 正在å‡çº§"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"在å‡çº§å®Œæˆä¹‹å‰ï¼Œéƒ¨åˆ†åº”用å¯èƒ½æ— æ³•正常è¿è¡Œ"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"正在优化第<xliff:g id="NUMBER_0">%1$d</xliff:g>个应用(共<xliff:g id="NUMBER_1">%2$d</xliff:g>个)。"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"正在准备å‡çº§<xliff:g id="APPNAME">%1$s</xliff:g>。"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在å¯åŠ¨åº”ç”¨ã€‚"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index d912ce511807..5aa4648bd048 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"正在優化儲存空間。"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"正在å‡ç´š Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"部分應用程å¼éœ€è¦å®Œæˆå‡ç´šæ–¹å¯æ­£å¸¸é‹ä½œ"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"正在優化第 <xliff:g id="NUMBER_0">%1$d</xliff:g> å€‹æ‡‰ç”¨ç¨‹å¼ (å…± <xliff:g id="NUMBER_1">%2$d</xliff:g> 個)。"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"正在準備 <xliff:g id="APPNAME">%1$s</xliff:g>。"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在啟動應用程å¼ã€‚"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 3c6c2b3a384e..cd3ee3ab23e5 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"正在å°å„²å­˜ç©ºé–“進行最佳化處ç†ã€‚"</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"正在å‡ç´š Android"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"å‡ç´šå®Œæˆå‰ï¼Œéƒ¨åˆ†æ‡‰ç”¨ç¨‹å¼å¯èƒ½ç„¡æ³•正常é‹ä½œ"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"正在最佳化第 <xliff:g id="NUMBER_0">%1$d</xliff:g> å€‹æ‡‰ç”¨ç¨‹å¼ (å…± <xliff:g id="NUMBER_1">%2$d</xliff:g> 個)。"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"正在準備å‡ç´šã€Œ<xliff:g id="APPNAME">%1$s</xliff:g>ã€ã€‚"</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"正在啟動應用程å¼ã€‚"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e29b05f05cfd..b00b74584737 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1024,6 +1024,8 @@
<string name="android_upgrading_fstrim" msgid="8036718871534640010">"Ikhulisa isitoreji."</string>
<string name="android_upgrading_notification_title" msgid="1619393112444671028">"I-Android iyathuthukiswa"</string>
<string name="android_upgrading_notification_body" msgid="5761201379457064286">"Ezinye izinhlelo zokusebenza kungenzeka zingasebenzi kahle kuze kuqedwe ukuthuthukiswa"</string>
+ <!-- no translation found for app_upgrading_toast (3008139776215597053) -->
+ <skip />
<string name="android_upgrading_apk" msgid="7904042682111526169">"Ukubeka ezingeni eliphezulu <xliff:g id="NUMBER_0">%1$d</xliff:g> uhlelo lokusebenza <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
<string name="android_preparing_apk" msgid="8162599310274079154">"Ukulungisela i-<xliff:g id="APPNAME">%1$s</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Qalisa izinhlelo zokusebenza."</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7d8d8114f000..674a0d7f61eb 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -754,6 +754,26 @@
-->
<integer name="config_defaultNightMode">1</integer>
+ <!-- Control whether Night display is available. This should only be enabled on devices
+ with HWC 2.0 or higher. -->
+ <bool name="config_nightDisplayAvailable">false</bool>
+
+ <!-- Default mode to control how Night display is automatically activated.
+ One of the following values (see NightDisplayController.java):
+ 0 - AUTO_MODE_DISABLED
+ 1 - AUTO_MODE_CUSTOM
+ 2 - AUTO_MODE_TWILIGHT
+ -->
+ <integer name="config_defaultNightDisplayAutoMode">0</integer>
+
+ <!-- Default time when Night display is automatically activated.
+ Represented as milliseconds from midnight (e.g. 79200000 == 10pm). -->
+ <integer name="config_defaultNightDisplayCustomStartTime">79200000</integer>
+
+ <!-- Default time when Night display is automatically deactivated.
+ Represented as milliseconds from midnight (e.g. 21600000 == 6am). -->
+ <integer name="config_defaultNightDisplayCustomEndTime">21600000</integer>
+
<!-- Indicate whether to allow the device to suspend when the screen is off
due to the proximity sensor. This resource should only be set to true
if the sensor HAL correctly handles the proximity sensor as a wake-up source.
@@ -2507,4 +2527,12 @@
<!-- Package name for the device provisioning package. -->
<string name="config_deviceProvisioningPackage"></string>
+
+ <!-- Colon separated list of package names that should be granted DND access -->
+ <string name="config_defaultDndAccessPackages" translatable="false">com.android.camera2</string>
+
+ <!-- User restrictions set when the first user is created.
+ Note: Also update appropriate overlay files. -->
+ <string-array translatable="false" name="config_defaultFirstUserRestrictions">
+ </string-array>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f0cfd2b01a20..473796a6b650 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2794,6 +2794,9 @@
<!-- [CHAR LIMIT=200] Body of notification that is shown when performing a system upgrade. -->
<string name="android_upgrading_notification_body">Some apps may not work properly until the upgrade finishes</string>
+ <!-- [CHAR LIMIT=40] Toast that is shown when an app is still upgrading. -->
+ <string name="app_upgrading_toast"><xliff:g id="application">%1$s</xliff:g> is upgrading\u2026</string>
+
<!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog for each .apk that is optimized. -->
<string name="android_upgrading_apk">Optimizing app
<xliff:g id="number" example="123">%1$d</xliff:g> of
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a0ce2afd10e1..3590ac86afd0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2643,6 +2643,9 @@
<!-- Package name for the device provisioning package -->
<java-symbol type="string" name="config_deviceProvisioningPackage" />
+ <!-- Colon separated list of package names that should be granted DND access -->
+ <java-symbol type="string" name="config_defaultDndAccessPackages" />
+
<!-- Used for MimeIconUtils. -->
<java-symbol type="drawable" name="ic_doc_apk" />
<java-symbol type="drawable" name="ic_doc_audio" />
@@ -2668,4 +2671,11 @@
<java-symbol type="drawable" name="ic_doc_video" />
<java-symbol type="drawable" name="ic_doc_generic" />
+ <java-symbol type="bool" name="config_nightDisplayAvailable" />
+ <java-symbol type="integer" name="config_defaultNightDisplayAutoMode" />
+ <java-symbol type="integer" name="config_defaultNightDisplayCustomStartTime" />
+ <java-symbol type="integer" name="config_defaultNightDisplayCustomEndTime" />
+
+ <!-- Default first user restrictions -->
+ <java-symbol type="array" name="config_defaultFirstUserRestrictions" />
</resources>
diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java
index a9fa4dd0d3a9..fd686b9b6330 100644
--- a/core/tests/coretests/src/android/text/method/BackspaceTest.java
+++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java
@@ -170,10 +170,27 @@ public class BackspaceTest extends KeyListenerTestCase {
backspace(state, 0);
state.assertEquals("|");
+ state.setByString("U+1F469 U+200D U+1F373 |");
+ backspace(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("U+1F487 U+200D U+2640 |");
+ backspace(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("U+1F487 U+200D U+2640 U+FE0F |");
+ backspace(state, 0);
+ state.assertEquals("|");
+
state.setByString("U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468 |");
backspace(state, 0);
state.assertEquals("|");
+ // Emoji modifier can be appended to the first emoji.
+ state.setByString("U+1F469 U+1F3FB U+200D U+1F4BC |");
+ backspace(state, 0);
+ state.assertEquals("|");
+
// End with ZERO WIDTH JOINER
state.setByString("U+1F441 U+200D |");
backspace(state, 0);
@@ -445,13 +462,6 @@ public class BackspaceTest extends KeyListenerTestCase {
backspace(state, 0);
state.assertEquals("|");
- // Emoji modifier + ZERO WIDTH JOINER
- state.setByString("U+1F466 U+1F3FB U+200D U+1F469 |");
- backspace(state, 0);
- state.assertEquals("U+1F466 |");
- backspace(state, 0);
- state.assertEquals("|");
-
// Regional indicator symbol + Emoji modifier
state.setByString("U+1F1FA U+1F3FB |");
backspace(state, 0);
diff --git a/docs/html-intl/intl/ja/training/basics/data-storage/files.jd b/docs/html-intl/intl/ja/training/basics/data-storage/files.jd
index dddfe371c428..b920c1af47b3 100644
--- a/docs/html-intl/intl/ja/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/ja/training/basics/data-storage/files.jd
@@ -183,7 +183,7 @@ public File getTempFile(Context context, String url) {
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,7 +250,7 @@ public boolean isExternalStorageReadable() {
-
+
<p>ãŸã¨ãˆã°ã€è‡ªåˆ†ã®ã‚¢ãƒ—リã§ãƒ€ã‚¦ãƒ³ãƒ­ãƒ¼ãƒ‰ã—ãŸè¿½åŠ ã®ãƒªã‚½ãƒ¼ã‚¹ã‚„一時的ãªãƒ¡ãƒ‡ã‚£ã‚¢ ファイルã§ã™ã€‚</p>
</dd>
</dl>
@@ -265,7 +265,7 @@ android.os.Environment#DIRECTORY_PICTURES} ãªã©ã®ä¿å­˜ã™ã‚‹ãƒ•ァイルã®ç
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@ android.content.Context#getExternalFilesDir getExternalFilesDir()} を呼ã³å‡ºã
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -366,7 +366,7 @@ myContext.deleteFile(fileName);
<div class="note">
<p><strong>注:</strong> ユーザーãŒã‚¢ãƒ—リをアンインストールã™ã‚‹ã¨ã€Android ã‚·ã‚¹ãƒ†ãƒ ã¯æ¬¡ã‚’削除ã—ã¾ã™ã€‚
-</p>
+</p>
<ul>
<li>内部ストレージã«ä¿å­˜ã—ãŸã™ã¹ã¦ã®ãƒ•ァイル</li>
<li>{@link
diff --git a/docs/html-intl/intl/ko/training/basics/data-storage/files.jd b/docs/html-intl/intl/ko/training/basics/data-storage/files.jd
index 71652b5774fe..0b717a892a4f 100644
--- a/docs/html-intl/intl/ko/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/ko/training/basics/data-storage/files.jd
@@ -183,7 +183,7 @@ public File getTempFile(Context context, String url) {
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,7 +250,7 @@ public boolean isExternalStorageReadable() {
ì•±ì„ ì œê±°í•˜ë©´ ê°™ì´ ì‚­ì œë©ë‹ˆë‹¤. ì´ëŸ¬í•œ 파ì¼ì€
엄밀히 ë§í•´ 외부 ì €ìž¥ì†Œì— ì €ìž¥ëœ íŒŒì¼ì´ê¸° ë•Œë¬¸ì— ì‚¬ìš©ìž ë° ë‹¤ë¥¸ ì•±ì˜ ì•¡ì„¸ìŠ¤ê°€ 가능하긴 하지만, 앱 외부ì—서
사용ìžì—게 ê°’ì„ ì‹¤ì œë¡œ 제공하지는 않습니다. 사용ìžê°€ ì•±ì„ ì œê±°í•˜ë©´ ì•±ì˜ ì™¸ë¶€ ê°œì¸ ë””ë ‰í„°ë¦¬ ë‚´ 모든 파ì¼ì„ 시스템ì—서
-삭제합니다.
+삭제합니다.
<p>예를 들어 앱ì—서 다운로드한 추가 리소스 ë˜ëŠ” 임시 미디어 파ì¼ì´ ì´ì— 해당합니다.</p>
</dd>
</dl>
@@ -265,7 +265,7 @@ android.os.Environment#DIRECTORY_PICTURES}와 ê°™ì€ ë‹¤ë¥¸ 공개
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@ android.content.Context#getExternalFilesDir getExternalFilesDir()}ì„ í˜¸ì¶œí•˜ê
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -357,7 +357,7 @@ JPEG로 변환하여 íŒŒì¼ ì¸ì½”딩ì„
myFile.delete();
</pre>
-<p>파ì¼ì´ ë‚´ë¶€ ì €ìž¥ì†Œì— ì €ìž¥ë˜ì–´ 있는 경우, {@link android.content.Context}ì— ìœ„ì¹˜ë¥¼ 요청하고 {@link android.content.Context#deleteFile deleteFile()}ì„ í˜¸ì¶œí•˜ì—¬ 파ì¼ì„
+<p>파ì¼ì´ ë‚´ë¶€ ì €ìž¥ì†Œì— ì €ìž¥ë˜ì–´ 있는 경우, {@link android.content.Context}ì— ìœ„ì¹˜ë¥¼ 요청하고 {@link android.content.Context#deleteFile deleteFile()}ì„ í˜¸ì¶œí•˜ì—¬ 파ì¼ì„
삭제할 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤.</p>
<pre>
@@ -366,7 +366,7 @@ myContext.deleteFile(fileName);
<div class="note">
<p><strong>참고:</strong> 사용ìžê°€ ì•±ì„ ì œê±°í•˜ë©´ Android 시스템ì´
-ë‹¤ìŒ í•­ëª©ì„ ì‚­ì œí•©ë‹ˆë‹¤.</p>
+ë‹¤ìŒ í•­ëª©ì„ ì‚­ì œí•©ë‹ˆë‹¤.</p>
<ul>
<li>ë‚´ë¶€ ì €ìž¥ì†Œì— ì €ìž¥í•œ 모든 파ì¼</li>
<li>{@link
diff --git a/docs/html-intl/intl/pt-br/training/basics/data-storage/files.jd b/docs/html-intl/intl/pt-br/training/basics/data-storage/files.jd
index d071d398d491..0e00645600e2 100644
--- a/docs/html-intl/intl/pt-br/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/pt-br/training/basics/data-storage/files.jd
@@ -183,7 +183,7 @@ public File getTempFile(Context context, String url) {
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,12 +250,12 @@ o usuário deve continuar a ter acesso a esses arquivos.
. Embora esses arquivos estejam teoricamente à disposição do usuário e de outros aplicativo por estarem
no armazenamento externo, na verdade são arquivos que não têm valor para o usuário
fora do aplicativo. Ao desinstalar o aplicativo, o sistema exclui
-todos os arquivos no diretório privado externo do aplicativo.
+todos os arquivos no diretório privado externo do aplicativo.
<p>Por exemplo, recursos adicionais baixados através do aplicativo ou arquivos de mídia temporários.</p>
</dd>
</dl>
-<p>Para salvar arquivos públicos no armazenamento externo, use o método
+<p>Para salvar arquivos públicos no armazenamento externo, use o método
{@link android.os.Environment#getExternalStoragePublicDirectory
getExternalStoragePublicDirectory()} para obter um {@link java.io.File} que representa
o diretório correto no armazenamento externo. O método exige um argumento que especifica
@@ -265,7 +265,7 @@ android.os.Environment#DIRECTORY_PICTURES}. Por exemplo:</p>
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@ usuário faz a desinstalação.</p>
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -366,7 +366,7 @@ myContext.deleteFile(fileName);
<div class="note">
<p><strong>Observação:</strong> quando o usuário desinstala o aplicativo, o sistema Android também
-exclui:</p>
+exclui:</p>
<ul>
<li>Todos os arquivos salvos no armazenamento interno</li>
<li>Todos os arquivos salvos no armazenamento externo usando {@link
diff --git a/docs/html-intl/intl/ru/training/basics/data-storage/files.jd b/docs/html-intl/intl/ru/training/basics/data-storage/files.jd
index 2afecea81a89..2b8f880aacaf 100644
--- a/docs/html-intl/intl/ru/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/ru/training/basics/data-storage/files.jd
@@ -183,7 +183,7 @@ public File getTempFile(Context context, String url) {
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,7 +250,7 @@ public boolean isExternalStorageReadable() {
вашего Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¼. Ð¥Ð¾Ñ‚Ñ Ñ‚ÐµÑ…Ð½Ð¸Ñ‡ÐµÑки Ñти файлы доÑтупны Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¸ других приложений, поÑкольку находÑÑ‚ÑÑ
во внешнем хранилище, они не имеют никакой ценноÑти Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹
вне вашего приложениÑ. Когда пользователь удалÑет ваше приложение, ÑиÑтема удалÑет
-вÑе файлы из каталога закрытых файлов вашего Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð²Ð¾ внешнем хранилище.
+вÑе файлы из каталога закрытых файлов вашего Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð²Ð¾ внешнем хранилище.
<p>Ðапример, к Ñтой категории отноÑÑÑ‚ÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ñ‹Ðµ реÑурÑÑ‹, загруженные приложением, и временные мультимедийные файлы.</p>
</dd>
</dl>
@@ -265,7 +265,7 @@ android.os.Environment#DIRECTORY_PICTURES}. Ðапример:</p>
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@ android.content.Context#getExternalFilesDir getExternalFilesDir()} и предо
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -332,7 +332,7 @@ java.io.File#getTotalSpace}. Эти методы позволÑÑŽÑ‚ узнать
общее проÑтранÑтво в хранилище. Эта Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‚Ð°ÐºÐ¶Ðµ позволÑть
избежать Ð¿ÐµÑ€ÐµÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐ¼Ð° хранилища Ñверх определенного уровнÑ.</p>
-<p>Однако ÑиÑтема не гарантирует возможноÑть запиÑи такого же количеÑтва байт, как указано
+<p>Однако ÑиÑтема не гарантирует возможноÑть запиÑи такого же количеÑтва байт, как указано
в {@link java.io.File#getFreeSpace}. ЕÑли выводимое чиÑло на
неÑколько мегабайт превышает размер данных, которые вы хотите Ñохранить, или еÑли Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема заполнена
менее, чем на 90%, дальше можно дейÑтвовать Ñпокойно.
@@ -366,13 +366,13 @@ myContext.deleteFile(fileName);
<div class="note">
<p><strong>Примечание.</strong> При удалении пользователем вашего Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ ÑиÑтема Android удалÑет
-Ñледующие Ñлементы:</p>
+Ñледующие Ñлементы:</p>
<ul>
<li>Ð’Ñе файлы, Ñохраненные во внутреннем хранилище</li>
<li>Ð’Ñе файлы, Ñохраненные во внешнем хранилище Ñ Ð¸Ñпользованием {@link
android.content.Context#getExternalFilesDir getExternalFilesDir()}.</li>
</ul>
-<p>Однако вам Ñледует регулÑрно вручную очищать кÑш-памÑть, чтобы удалить файлы, Ñозданные Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ
+<p>Однако вам Ñледует регулÑрно вручную очищать кÑш-памÑть, чтобы удалить файлы, Ñозданные Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ
{@link android.content.Context#getCacheDir()}, а также удалÑть любые
другие ненужные файлы.</p>
</div>
diff --git a/docs/html-intl/intl/zh-cn/training/basics/data-storage/files.jd b/docs/html-intl/intl/zh-cn/training/basics/data-storage/files.jd
index 14422757397c..4ec1d68f714d 100644
--- a/docs/html-intl/intl/zh-cn/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/zh-cn/training/basics/data-storage/files.jd
@@ -183,7 +183,7 @@ public File getTempFile(Context context, String url) {
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,7 +250,7 @@ public boolean isExternalStorageReadable() {
-
+
<p>ä¾‹å¦‚ï¼Œæ‚¨çš„åº”ç”¨ä¸‹è½½çš„å…¶ä»–èµ„æºæˆ–临时介质文件。</p>
</dd>
</dl>
@@ -265,7 +265,7 @@ android.os.Environment#DIRECTORY_PICTURES}。
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@ android.content.Context#getExternalFilesDir getExternalFilesDir()} 获å–相应ç
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -311,7 +311,7 @@ getExternalStoragePublicDirectory()}。
<p>无论您对于共享的文件使用 {@link
android.os.Environment#getExternalStoragePublicDirectory
-getExternalStoragePublicDirectory()} 还是对您的应用专用文件使用
+getExternalStoragePublicDirectory()} 还是对您的应用专用文件使用
{@link android.content.Context#getExternalFilesDir
getExternalFilesDir()} ,您使用诸如
{@link android.os.Environment#DIRECTORY_PICTURES} çš„ API 常数æä¾›çš„目录åç§°éžå¸¸é‡è¦ã€‚
@@ -332,7 +332,7 @@ java.io.IOException} 。
此信æ¯ä¹Ÿå¯ç”¨æ¥é¿å…填充存储å·ä»¥è‡´è¶…出特定阈值。
</p>
-<p>但是,系统并ä¸ä¿è¯æ‚¨å¯ä»¥å†™å…¥ä¸Ž {@link java.io.File#getFreeSpace}
+<p>但是,系统并ä¸ä¿è¯æ‚¨å¯ä»¥å†™å…¥ä¸Ž {@link java.io.File#getFreeSpace}
指示的一样多的字节。如果返回的数字比您è¦ä¿å­˜çš„æ•°æ®å¤§å°å¤§å‡ºå‡  MB,或如果文件系统所å ç©ºé—´ä¸åˆ° 90%,则å¯å®‰å…¨ç»§ç»­æ“作。å¦åˆ™ï¼Œæ‚¨å¯èƒ½ä¸åº”写入存储。
@@ -366,7 +366,7 @@ myContext.deleteFile(fileName);
<div class="note">
<p><strong>注æ„:</strong>当用户å¸è½½æ‚¨çš„应用时,Android 系统会删除以下å„项:
-</p>
+</p>
<ul>
<li>您ä¿å­˜åœ¨å†…部存储中的所有文件</li>
<li>您使用 {@link
diff --git a/docs/html-intl/intl/zh-tw/training/basics/data-storage/files.jd b/docs/html-intl/intl/zh-tw/training/basics/data-storage/files.jd
index 8b8d0a77f0dd..cda58641c3bc 100644
--- a/docs/html-intl/intl/zh-tw/training/basics/data-storage/files.jd
+++ b/docs/html-intl/intl/zh-tw/training/basics/data-storage/files.jd
@@ -40,7 +40,7 @@ API 讀å–並寫入檔案。
該物件的用途很廣,例如éžå¸¸é©ç”¨æ–¼å½±åƒæª”案或é€éŽç¶²è·¯äº¤æ›çš„項目。
</p>
-<p>本課程將顯示如何在您的應用程å¼ä¸­åŸ·è¡Œèˆ‡æª”案相關的基本任務。本課程å‡è¨­æ‚¨å·²ç†Ÿæ‚‰ Linux 檔案系統的基本概念,以åŠ
+<p>本課程將顯示如何在您的應用程å¼ä¸­åŸ·è¡Œèˆ‡æª”案相關的基本任務。本課程å‡è¨­æ‚¨å·²ç†Ÿæ‚‰ Linux 檔案系統的基本概念,以åŠ
{@link java.io} 中的標準檔案輸入/輸出 API。
</p>
@@ -183,7 +183,7 @@ public File getTempFile(Context context, String url) {
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -250,12 +250,12 @@ public boolean isExternalStorageReadable() {
-
+
<p>例如,您的應用程å¼ä¸‹è¼‰çš„附加資æºï¼Œæˆ–暫存媒體檔案都是ç§ç”¨æª”案。</p>
</dd>
</dl>
-<p>若您希望將公用檔案儲存在外部儲存空間,請使用
+<p>若您希望將公用檔案儲存在外部儲存空間,請使用
{@link android.os.Environment#getExternalStoragePublicDirectory
getExternalStoragePublicDirectory()} 方法å–得代表外部儲存空間內相應目錄的 {@link java.io.File}。
該方法採用å°è¦å„²å­˜çš„æª”案類型進行指定 (以便能åˆç†å€åˆ†é€™äº›æª”案與其他公用檔案) 的引數,諸如 {@link android.os.Environment#DIRECTORY_MUSIC} 或 {@link
@@ -265,7 +265,7 @@ android.os.Environment#DIRECTORY_PICTURES}。
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -287,7 +287,7 @@ android.content.Context#getExternalFilesDir getExternalFilesDir()},然後å‘å…
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -366,7 +366,7 @@ myContext.deleteFile(fileName);
<div class="note">
<p><strong>注æ„:</strong>ä½¿ç”¨è€…è§£é™¤å®‰è£æ‚¨çš„æ‡‰ç”¨ç¨‹å¼æ™‚,Android 系統會刪除以下檔案:
-</p>
+</p>
<ul>
<li>您在內部儲存空間儲存的所有檔案</li>
<li>您使用 {@link
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index 11e06f110bec..4a9cab6d239f 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -361,6 +361,8 @@ redirects:
to: /about/dashboards/index.html
- from: /resources/community-groups.html
to: /support.html
+- from: /community/index.html
+ to: /support.html
- from: /guide/tutorials/
to: /resources/tutorials/
- from: /resources/tutorials/views/hello-linearlayout.html
@@ -801,8 +803,8 @@ redirects:
to: http://android-developers.blogspot.com/2016/03/first-preview-of-android-n-developer.html
- from: /reference/org/apache/http/...
to: /about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client
-- from: /shareables/
- to: https://commondatastorage.googleapis.com/androiddevelopers/shareables/
+- from: /shareables/...
+ to: https://commondatastorage.googleapis.com/androiddevelopers/shareables/...
- from: /downloads/
to: https://commondatastorage.googleapis.com/androiddevelopers/
- from: /training/performance/battery/network/action-any-traffic.html
@@ -1193,3 +1195,5 @@ redirects:
to: http://tools.android.com/tech-docs/new-build-system/gradle-experimental/experimental-to-stable-gradle
- from: /r/studio-ui/sdk-manager.html
to: https://developer.android.com/studio/intro/update.html#sdk-manager
+- from: /r/studio-ui/newjclass.html
+ to: /studio/write/index.html
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 911e25603d6e..a9f1985da9ce 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 June 6, 2016.
+<p style="clear:both"><em>Data collected during a 7-day period ending on July 11, 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 June 6, 2016.
+<p style="clear:both"><em>Data collected during a 7-day period ending on July 11, 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%3A48.6%2C41.8%2C9.6&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%3A47.5%2C41.9%2C10.6&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>48.6%</td>
+<td>47.5%</td>
</tr>
<tr>
<td>3.0</td>
-<td>41.8%</td>
+<td>41.9%</td>
</tr>
<tr>
<td>3.1</td>
-<td>9.6%</td>
+<td>10.6%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on June 6, 2016</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on July 11, 2016</em></p>
@@ -147,28 +147,28 @@ var SCREEN_DATA =
"Large": {
"hdpi": "0.5",
"ldpi": "0.2",
- "mdpi": "4.5",
- "tvdpi": "2.2",
+ "mdpi": "4.4",
+ "tvdpi": "2.1",
"xhdpi": "0.5"
},
"Normal": {
- "hdpi": "41.1",
- "mdpi": "4.2",
+ "hdpi": "40.9",
+ "mdpi": "4.1",
"tvdpi": "0.1",
- "xhdpi": "25.6",
- "xxhdpi": "15.0"
+ "xhdpi": "26.3",
+ "xxhdpi": "15.1"
},
"Small": {
- "ldpi": "2.0"
+ "ldpi": "1.9"
},
"Xlarge": {
"hdpi": "0.3",
- "mdpi": "3.1",
+ "mdpi": "2.9",
"xhdpi": "0.7"
}
},
- "densitychart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A2.2%2C11.8%2C2.3%2C41.9%2C26.8%2C15.0&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi",
- "layoutchart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A4.1%2C7.9%2C86.0%2C2.0&chl=Xlarge%7CLarge%7CNormal%7CSmall"
+ "densitychart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&chd=t%3A2.1%2C11.4%2C2.2%2C41.7%2C27.5%2C15.1&chf=bg%2Cs%2C00000000&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chs=400x250&cht=p",
+ "layoutchart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&chd=t%3A3.9%2C7.7%2C86.5%2C1.9&chf=bg%2Cs%2C00000000&chl=Xlarge%7CLarge%7CNormal%7CSmall&chs=400x250&cht=p"
}
];
@@ -176,7 +176,7 @@ var SCREEN_DATA =
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?chs=500x250&cht=p&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A0.1%2C2.0%2C1.9%2C18.9%2C31.6%2C35.4%2C10.1&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat%7CLollipop%7CMarshmallow",
+ "chart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&chd=t%3A0.1%2C1.9%2C1.7%2C17.8%2C30.2%2C35.1%2C13.3&chf=bg%2Cs%2C00000000&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat%7CLollipop%7CMarshmallow&chs=500x250&cht=p",
"data": [
{
"api": 8,
@@ -186,47 +186,47 @@ var VERSION_DATA =
{
"api": 10,
"name": "Gingerbread",
- "perc": "2.0"
+ "perc": "1.9"
},
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "1.9"
+ "perc": "1.7"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "6.8"
+ "perc": "6.4"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "9.4"
+ "perc": "8.8"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "2.7"
+ "perc": "2.6"
},
{
"api": 19,
"name": "KitKat",
- "perc": "31.6"
+ "perc": "30.1"
},
{
"api": 21,
"name": "Lollipop",
- "perc": "15.4"
+ "perc": "14.3"
},
{
"api": 22,
"name": "Lollipop",
- "perc": "20.0"
+ "perc": "20.8"
},
{
"api": 23,
"name": "Marshmallow",
- "perc": "10.1"
+ "perc": "13.3"
}
]
}
diff --git a/docs/html/auto/images/logos/auto/lincoln.png b/docs/html/auto/images/logos/auto/lincoln.png
new file mode 100644
index 000000000000..0ade9fed5537
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/lincoln.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/mbenz.png b/docs/html/auto/images/logos/auto/mbenz.png
new file mode 100644
index 000000000000..84deacd3f83a
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/mbenz.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/opel.png b/docs/html/auto/images/logos/auto/opel.png
index 7e25ed574ecb..fcb70402b30c 100644
--- a/docs/html/auto/images/logos/auto/opel.png
+++ b/docs/html/auto/images/logos/auto/opel.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/renault.png b/docs/html/auto/images/logos/auto/renault.png
index d252aa32b59c..297043068e03 100644
--- a/docs/html/auto/images/logos/auto/renault.png
+++ b/docs/html/auto/images/logos/auto/renault.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/rsm.png b/docs/html/auto/images/logos/auto/rsm.png
new file mode 100644
index 000000000000..fa0e56afae44
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/rsm.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/tata.png b/docs/html/auto/images/logos/auto/tata.png
new file mode 100644
index 000000000000..dfc4a5f8eed8
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/tata.png
Binary files differ
diff --git a/docs/html/auto/index.jd b/docs/html/auto/index.jd
index 843aabf94f64..5b67641c8a83 100644
--- a/docs/html/auto/index.jd
+++ b/docs/html/auto/index.jd
@@ -507,7 +507,12 @@ nonavpage=true
width="120" height="120" class="img-logo" />
</a>
</div>
-
+ <div class="col-5">
+ <a href=" http://www.lincoln.com/">
+ <img src="{@docRoot}auto/images/logos/auto/lincoln.png"
+ width="120" height="120" class="img-logo" />
+ </a>
+ </div>
<div class="col-5">
<a href="http://www.mahindra.com/">
<img src="{@docRoot}auto/images/logos/auto/mahindra.png"
@@ -520,16 +525,22 @@ nonavpage=true
width="120" height="120" class="img-logo" />
</a>
</div>
+ </div>
+ <div class="cols cols-leftp">
<div class="col-5">
<a href="http://www.mazda.com/">
<img src="{@docRoot}auto/images/logos/auto/mazda.png"
width="120" height="120" class="img-logo" />
</a>
</div>
- </div>
- <div class="cols cols-leftp">
- <div class="col-5">
+ <div class="col-5">
+ <a href="http://www.mercedes-benz.com/">
+ <img src="{@docRoot}auto/images/logos/auto/mbenz.png"
+ width="120" height="120" class="img-logo" />
+ </a>
+ </div>
+ <div class="col-5">
<a href="http://www.mitsubishi-motors.com/">
<img src="{@docRoot}auto/images/logos/auto/mitsubishi.png"
width="120" height="120" class="img-logo" />
@@ -542,20 +553,22 @@ nonavpage=true
width="120" height="120" class="img-logo" />
</a>
</div>
+ </div>
+ <div class="cols cols-leftp">
<div class="col-5">
<a href="http://www.opel.com/">
<img src="{@docRoot}auto/images/logos/auto/opel.png"
width="120" height="120" class="img-logo" />
</a>
</div>
+
<div class="col-5">
<a href="http://www.peugeot.com/">
<img src="{@docRoot}auto/images/logos/auto/peugeot.png"
width="120" height="120" class="img-logo" />
</a>
</div>
- </div>
- <div class="cols cols-leftp">
+
<div class="col-5">
<a href="http://www.ramtrucks.com/">
<img src="{@docRoot}auto/images/logos/auto/ram.png"
@@ -569,27 +582,37 @@ nonavpage=true
width="120" height="120" class="img-logo" />
</a>
</div>
+ </div>
+ <div class="cols cols-leftp">
+ <div class="col-5">
+ <a href="http://www.renaultsamsungm.com/ ">
+ <img src="{@docRoot}auto/images/logos/auto/rsm.png"
+ width="120" height="120" class="img-logo" />
+ </a>
+ </div>
+
<div class="col-5">
<a href="http://www.seat.com/">
<img src="{@docRoot}auto/images/logos/auto/seat.png"
width="120" height="120" class="img-logo" />
</a>
</div>
+
<div class="col-5">
<a href="http://www.skoda-auto.com/">
<img src="{@docRoot}auto/images/logos/auto/skoda.png"
width="120" height="120" class="img-logo" />
</a>
</div>
- </div>
- <div class="cols cols-leftp">
+
<div class="col-5">
<a href="http://www.smotor.com/">
<img src="{@docRoot}auto/images/logos/auto/ssangyong.png"
width="120" height="120" class="img-logo" />
</a>
</div>
-
+ </div>
+ <div class="cols cols-leftp">
<div class="col-5">
<a href="http://www.subaru-global.com/">
<img src="{@docRoot}auto/images/logos/auto/subaru.png"
@@ -597,13 +620,20 @@ nonavpage=true
</a>
</div>
-
<div class="col-5">
<a href="http://www.globalsuzuki.com/automobile/">
<img src="{@docRoot}auto/images/logos/auto/suzuki.png"
width="120" height="120" class="img-logo" />
</a>
</div>
+
+ <div class="col-5">
+ <a href="http://www.tatamotors.com/">
+ <img src="{@docRoot}auto/images/logos/auto/tata.png"
+ width="120" height="120" class="img-logo" />
+ </a>
+ </div>
+
<div class="col-5">
<a href="http://www.vauxhall.co.uk/">
<img src="{@docRoot}auto/images/logos/auto/vauxhall.png"
@@ -618,7 +648,8 @@ nonavpage=true
width="120" height="120" class="img-logo" />
</a>
</div>
-
+
+
<div class="col-5">
<a href="http://www.volvocars.com/intl">
<img src="{@docRoot}auto/images/logos/auto/volvo.png"
diff --git a/docs/html/community/index.html b/docs/html/community/index.html
deleted file mode 100644
index e3834ba15cd0..000000000000
--- a/docs/html/community/index.html
+++ /dev/null
@@ -1,320 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<meta name="google-site-verification" content="sa-bIAI6GKvct3f61-WpRguHq-aNjtF7xJjMTSi79as" />
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Android Developers Community</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var devsite = false;
-</script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-
-<style>
-#header {
- padding: 2.2em 0 0.2em 0;
-}
-#header-wrap h1 {
- margin:0;
- padding:0;
- line-height:16px;
-}
-#body-content {
- margin-top:20px;
-}
-#nav-x.wrap {
- overflow:auto;
-}
-h2 {
- border-bottom:1px solid #CCC;
-}
-</style>
-</head>
-
-
-
-
-
-
-<body>
-
-
-<!-- Header -->
-<div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo">
- <a href="/index.html">
- <img src="http://developer.android.com/assets/images/dac_logo.png" width="123" height="25" alt="Android Developers" />
- </a>
- </div>
- <div class="col-8">
- <h1>Community Outreach</h1>
- </div>
-
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul style="margin-bottom:0">
- <li><a href="https://www.youtube.com/user/androiddevelopers">Android Developers Live</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="http://developer.android.com/training/">Android Developer Training</a></li>
- <li><a href="http://developer.android.com/samples/">Samples</a></li>
- </ul>
- <br class="clear-fix">
- </div>
- <div class="bottom"></div>
- </div><!-- end morehover -->
- </div><!-- end menu-container -->
- </div><!-- end header-wrap -->
-</div>
-<!-- /Header -->
-
-<div id="nav-x" class="wrap">
- <ul class="nav-x col-9 develop">
- <li><a href="#News">News</a></li>
- <li><a href="#Community">Community</a></li>
- <li><a href="#Content">Content</a></li>
- <li><a href="#Social">Social</a></li>
- </ul>
-</div>
-
-
-<!-- MAIN CONTENT -->
-
-
-<div class="wrap" id="body-content">
-
-<img src="/images/community/aco1small.png" alt="" style="float:right;margin:20px 0 0 40px">
-
-<p style="clear:left">
- Android is working with communities to
-<ul>
-<li>Create a cooperative relationship between highly impactful communities and high performing developers</li>
-<li>Strengthen relationships between Android and coding communities so that developers have a motivation to interact with those communities</li>
-<li>Reward communities for attracting developers by providing them with resources and direct access to the Android team</li></ul>
-<p>Our IMPACT is measured by <strong>good apps</strong> and a <strong>thriving community</strong></p>
-
-<h2 id="News" style="clear:left">News</h2>
-<p>Our current theme is on the <b><em>Android 4.4 KitKat and Updated Developer Tools</em></b> release, with new ways to create beautiful apps, printing and storage frameworks, low-power sensors, new media capabilities and RenderScript in the NDK.</p>
-
-<div class="col-8" style="margin-left:0">
-<img src="/images/community/kk-hero2.jpg" alt="" height="277">
-</div>
-
-<div class="col-8" style="margin-right:0">
-<h3 style="margin-top:0"><a href="http://developer.android.com/about/versions/kitkat.html">Android 4.4 Platform Highlights</a></h3>
-<p>Android KitKat brings all of Android's most innovative, most beautiful, and most useful features to more devices everywhere.</p>
-
-<h3><a href="http://developer.android.com/about/versions/android-4.4.html">Android 4.4 APIs</a></h3>
-<p>Android 4.4 (KITKAT) is a new release for the Android platform that offers new features for users and app developers. This document provides an introduction to the most notable new APIs.</p>
-
-<h3><a href="https://play.google.com/store/devices/details?id=nexus_5_white_32gb">New Nexus 5</a></h3>
-<p>Nexus 5 helps you capture the everyday and the epic in fresh new ways. It's the slimmest and fastest Nexus phone ever made, powered by Android 4.4, KitKat.</p>
-</div>
-<p></p>
-
-<h2 id="Community" style="clear:left">Community Spotlight</h2>
-
-<div class="col-8" style="margin-left:0">
-<h3>Android Community Groups</h3>
-<h4>July 2013</h4>
-<p><a href="mailto:gtugam@gmail.com">GDG Armenia</a> held <a href="http://eca.hackathon.am/">ecaHack Yerevan</a>, an Android hackathon featuring &quot;Angry Designers vs Android Developers&quot;, where the designers had a look into developers apps and gave them some advices regarding to design. The hackathon was sponsored by Alcatel One Touch and each member of the winner team got one Alcatel One Touch Idol. Check out the <a href="https://plus.google.com/u/0/events/gallery/cgj9d39gphiephlq0e2899dv6j4?cfem=1">photos.</a></p>
-<h4>September 2013</h4>
-<p><a href="mailto:soham.mondal@gmail.com">GDG Blrdroid</a> held a <a href="http://www.meetup.com/blrdroid/events/140665852/">meetup</a> on performance optimisation.</p>
-<p><a href="mailto:baileye@gmail.com">GDG Dublin</a> held their meetup with a talk on AdMob for Android and iOS, entitled &ldquo;Admob for Android and iOS developers&rdquo;. </p>
-<p>GDG Mbale&rsquo;s <a href="mailto:nsubugahassan@gmail.com">Hassan Nsubuga</a> has been managing a university <a href="https://plus.google.com/103735976334615631393/posts/gQMWCGUhMBn">course session</a> since September. They are now through with the basics and have a firm foundation, so this month they will be doing a lot of advanced stuff including exploring the latest API enhancements with KitKat. </p>
-<p><a href="mailto:wojtek.kalicinski@gmail.com">GDG Warsaw</a> held an Android Barcamp focused on App Quality. The discussion was moderated by GDG organisers, but the talks were given by the community members, including some top Android companies and developers in Poland.</p>
-<h4>October 2013</h4>
-<p><a href="mailto:benjamin.r.m.weiss@gmail.com">GDG Berlin Android</a> held their <a href="https://berlin.ticketbud.com/devfest-berlin-2013">DevFest</a>.</p>
-<p><a href="mailto:soham.mondal@gmail.com">GDG Blrdroid</a> held their <a href="http://www.meetup.com/blrdroid/events/144457162/">meetup</a> in collaboration with GDG Bangalore, where they talked about a wider range of things from incorporating user feedback to effectively using the cell radio. David McLaughlin from the Developer Relations team also visited during the meetup and delivered the keynote. They also hit a milestone with its 4th anniversary on the 9th of October and crossed 4300 members in the past few days so its been a memorable couple of months for them.</p>
-<p><a href="mailto:hir3npatel@gmail.com">GDG Cape Town</a> held an <a href="https://plus.google.com/108309780217630451504/posts/9BTCEqnBHoQ">Android Workshop</a> where they gave away lots of branded KitKats.</p>
-<p><a href="mailto:baileye@gmail.com">GDG Dublin</a> held its DevFest, which featured a codeLab on Android titled &ldquo;Codelab: Intro to Android Development.&rdquo;</p>
-<p><a href="mailto:hugo@dutchaug.org">GDG Dutch Android User Group</a> held their <a href="http://www.devfest.nl/program">DevFest</a>. They had a bunch of Android sessions, mostly by local speakers. In addition to the Android sessions, they also ran a workshop on writing custom views.</p>
-<p><a href="mailto:hugo@dutchaug.org">Hugo Visser</a> from the Dutch Android User Group spoke at <a href="https://bitbucket.org/qbusict/cupboard">DroidCon UK barcamp</a>, where he delivered a talk on Cupboard, a simple and lightweight persistence framework, specifically for Android.</p>
-<p><a href="mailto:prajyotmainkar@gmail.com">GDG GAUG</a> held the <a href="https://plus.google.com/110448195989468248957/posts/8doJuCpySWS">Google Devfest 2013</a>, where they had two tracks and more than 200 delegates attending. They also had a <a href="https://plus.google.com/110448195989468248957/posts/6rxLzj2Rpde">Hackathon</a> and they hit the <a href="https://plus.google.com/110448195989468248957">1000 member</a> mark this month, which makes them the second largest android community in India after GDG Blrdroid. </p>
-<p><a href="mailto:cyrilleguipie@gmail.com">GDG Miage</a> held their DevFest where they gave a talk about Intents and Services. The also held a startup Weekend Bootcamp where they talked about Activites and Layouts. They will also hold an Android Workshop in December.</p>
-<p><a href="mailto:gabriel.kb@gmail.com">GDG Uruguay</a> had their <a href="http://gdg.uy/devfest2013">DevFest</a>, where they held an Android workshop for beginners as an Android vs iOS comparison, a session on best practices using YouTube APIs in Android, and &nbsp;What's new in Google for developers (with a special section about Android). You can see pictures on <a href="https://plus.google.com/114520966453242230657/posts/dqZAuMqc12Z">the G+ page</a>. </p>
-
-<h4>November 2013</h4>
-<p><a href="mailto:yorogoule@gmail.com">Abidjandroid/GDG Côte d'Ivoire</a> held an Android Launch Party featuring the KitKat release.</p>
-<p>The <a href="mailto:hugo@dutchaug.org">Dutch Android User Group</a> had a very interactive presentation on Android Code Puzzlers and Tips &amp; tricks, where they rewarded participation by giving out books, tshirts, jelly beans and kitkats. The presentation was at the <a href="http://www.nljug.org/jfall">Dutch JFall conference</a>, organized by the NLJUG. It's a large yearly Java conference and the DAUG had the only Android session there.</p>
-<p>The <a href="mailto:benjamin.r.m.weiss@gmail.com">GDG Berlin Android</a> meetup this month featured the KitKat release.</p>
-<p><a href="mailto:soham.mondal@gmail.com">The GDG Blrdroid</a> <a href="http://www.meetup.com/blrdroid/events/148210762/%20">meetup</a> was another focused on KitKat.</p>
-<p>At the <a href="mailto:amahdy7@gmail.com">GDG Cairo</a> <a href="https://plus.google.com/events/co59j0870in5a4kh8n5navifnm8">DevFest</a> there was a &quot;What's new in Android SDK&quot; session on day 1, and an Android workshop on day 2. Kitkat also provided interest in the sessions and the snacks bar. The KitKat <a href="http://buff.ly/HNE7yq">presentation</a>, the track organization, and everything related to it were all organized by women.</p>
-<p><a href="mailto:hir3npatel@gmail.com">GDG Cape Town</a> held an Android Workshop.</p>
-<p><a href="mailto:alessandro.gbridge@gmail.com">GDG Udine</a> organized a talk after the release of KitKat for a school in Pordenone.</p>
-<p><a href="mailto:hugo@dutchaug.org">Hugo Visser</a> from Droidcon Netherlands organized an Android hackathon themed &quot;Location, Location, Location&quot;. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
-<p><a href="mailto:eyal.lezmy@gmail.com">Paris Android User Group</a> welcomed <a href="https://plus.google.com/+RomainGuy">Romain Guy</a> and <a href="https://plus.google.com/+ChetHaase">Chet Haase</a> to their meetup this month. They&rsquo;ll be meeting up with other GDG leads and UG managers meet at <a href="https://plus.google.com/events/cupo201fjreo9g9t2e596gv8nd4">Devoxx</a> next Thursday.</p>
-<p><a href="mailto:wojtek.kalicinski@gmail.com">GDG Warsaw</a> had over 250 attendees at their DevFest, which featured session tracks on Android and Web and a whole day of Code Labs in Android, AngularJS and Arduino.</p>
-<h4>December 2013</h4>
-<p><a href="mailto:prajyotmainkar@gmail.com">GDG GAUG</a> are planning a codelab and hackathon.</p>
-<p><a href="mailto:psvensson@gmail.com">Peter Svensson</a> spoke at <a href="http://swdc.se/droidcon/events/stockholm-2013/">DroidCon Stockholm</a></p>
-The unstoppable <a href="mailto:bonbhel@gmail.com">Max Bonbhel</a> from the African GDG Android is hosting AAC 2014 and Android GDG Barcamp events in December. Also, in order to encourage African Java developers to move to the Android platform, he created the <a href="https://docs.google.com/spreadsheet/ccc?key=0AtFPan-z2ps-dHBtX1luY2pRQjdtRjliUGcxMVBNeVE&usp=sharing#gid=0">Africa Android Training (AAT) program</a>. The training material targets developers with different levels of experience in Java development. More than 60 developers have been taking part in the weekly sessions. The next 10 sessions will start Saturday, November 9, 2013. 260 GDG and Java User Group members have already registered from 12 Countries.
-<p>&nbsp;</p>
-</div>
-
-<div class="col-8" style="margin-right:0">
-<h3>Android Community Experts</h3>
-
-<h4>October 2013</h4>
-<p><a href="mailto:eyal.lezmy@gmail.com">Eyal Lezmy</a> presented two sessions. &ldquo;<a href="http://bit.ly/andbigfail">Play Store bashing, learn from the biggest fails</a>&rdquo; looked at several applications, mainly developed by huge companies, and analyzed why they failed to satisfy the users or the Android guidelines. &ldquo;<a href="http://bit.ly/lifeofapp">Android, the life of your app</a>&rdquo; tells a story, living the life of a user, identify the frustrations he can encounter and present ways to avoid it, as a developer.</p>
-<p><a href="mailto:mariux01@gmail.com">Mario Viviani</a> presented and recorded the next <a href="http://www.youtube.com/watch?v=jaT0bYhhaGY">Android App Clinic - Italia</a>. This episode was regarding the Cards UI and SMS app support in Android 4.4. They experimented with a short form of the video (10 minutes instead of 20) and in less than day it got almost 400+ views -- which is great considering it's in Italian! The previous episode reached 1300 views all-time and was the most successful video of GDL Italia in Q2.</p>
-<p><a href="mailto:m.kaeppler@gmail.com">Matthias Käppler</a> contributed the <a href="https://github.com/Netflix/RxJava/tree/master/rxjava-contrib/rxjava-android">first Android specific component</a> to the RxJava project, and spoke about <a href="http://uk.droidcon.com/2013/sessions/conquering-concurrency-bringing-the-reactive-extensions-to-the-android-platform/">RxJava and reactive programming on Android</a> at DroidCon UK. He has also open sourced <a href="https://github.com/mttkay/memento">Memento</a>, an Android annotation processor to replace the deprecated onRetainNonConfigurationInstance.</p>
-<p><a href="mailto:wojtek.kalicinski@gmail.com">Wojtek Kaliciński</a>&rsquo;s talk, &quot;Android - is it time for a break yet?&quot; highlights not only what's new in Android 4.4 KitKat, but also how to take your app to the next level by making sure you provide the best app experience possible to all 4.0+ users.</p>
-<a href="https://plus.sandbox.google.com/110448195989468248957/posts"><img src="/images/community/hackathon-gdgaug.jpg" alt="" align="right"></a>
-
-</div>
-
-<h2 id="Content" style="clear:left">New Content</h2>
-<div class="col-8" style="margin-left:0">
-<p><h4>Android 4.4 What's New</h4>
-KitKat has been optimized to run on a much broader range of devices, with special focus on the millions of entry-level devices that have as little as 512MB RAM. To help, we've created new APIs, better tools, and better documentation to let you create apps that perform well on all devices.<br>
-Check out this video summary of some of the most significant developer features in the latest Android release, including new ways to make your apps beautiful, NFC Host Card Emulation, a printing framework, the storage access framework, low-power step detector and step counter sensors, and more!<br>
-<h5><a href="http://www.youtube.com/watch?v=sONcojECWXs&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5>
-<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5>
-<i>Be sure to get the <a href="http://developer.android.com/about/versions/android-4.4.html">full Android 4.4 API Overview</a>, and take a look at our <a href="https://www.youtube.com/playlist?list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">related DevBytes videos</a></i></p>
-
-<p><h4>WebView in Android 4.4</h4>
-Android 4.4 (API level 19) introduces a new version of WebView that is based on Chromium. This change upgrades WebView performance and standards support for HTML5, CSS3, and JavaScript to match the latest web browsers. Any apps using WebView will inherit these upgrades when running on Android 4.4 and higher.
-<h5><a href="http://developer.android.com/guide/webapps/migrating.html">API Guide</a></h5>
-</p>
-
-<p><h4>Android 4.4 Immersive Mode</h4>
-With Android 4.4 KitKat, your apps can now truly go full-screen with a new Immersive Mode. Immersive Mode lets your apps hide the system's status and navigation bars while capturing all touch events—ideal for rich interactive content such as books and games. This video demonstrates how to use the new API, in addition to recapping earlier full-screen APIs on Android.
-<h5><a href="http://www.youtube.com/watch?v=cBi8fjv90E4&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5>
-<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5>
-<h5><a href="http://developer.android.com/samples/ImmersiveMode/index.html">Sample</a></h5>
-</p>
-
-<p>
-<h4>Android 4.4 Storage Access Framework - Provider</h4>
-Get up to speed on the new document storage API in Android 4.4 KitKat. This video gets you up and running with your own DocumentProvider by stepping you through the making of a simple cloud storage app.
-<h5><a href="http://www.youtube.com/watch?v=zxHVeXbK1P4&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5>
-<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5>
-<h5><a href="http://developer.android.com/guide/topics/providers/document-provider.html">Training</a></h5>
-<h5><a href="http://developer.android.com/samples/StorageProvider/index.html">Sample</a>, <a href="https://play.google.com/store/apps/details?id=com.box.android">Box Application</a></h5>
-</blockquote>
-
-</p>
-
-
-<p><h4>Android 4.4 Storage Access Framework - Client</h4>
-Get up to speed on the new storage access framework in Android 4.4 KitKat. This video teaches you how to quickly create, edit, save and delete documents provided by other apps as a client of the storage access framework.
-<h5><a href="http://www.youtube.com/watch?v=UFj9AEz0DHQ&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5>
-<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5>
-<h5><a href="http://developer.android.com/samples/StorageClient/index.html">Sample</a></h5>
-</p>
-
-<p><h4>Android 4.4 Closed Captioning</h4>
-Displaying closed captions in your app's videos can be quick and simple in Android 4.4 KitKat,. Learn how to attach timed text tracks to VideoView and allow users to customize how captions are displayed.
-<h5><a href="http://www.youtube.com/watch?v=hCRGc2PcmB8&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5>
-<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a>
-</p>
-</h5>
-</div>
-
-<div class="col-8" style="margin-right:0">
-
-<p>
-<h4>Android 4.4 Transitions</h4>
-In this episode, we introduce the new Transitions API in Android 4.4 Kitkat. This API provides a simple way for developers to provide animated segues to different scenes of their application, helping users to understand the application flow with very little code. The general approach is to tell the system that you'd like to run a transition animation, then make the necessary changes to your UI. The system figures out the differences and animates the changes.
-<h5><a href="http://www.youtube.com/watch?v=S3H7nJ4QaD8&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K&index=3">Video</a></h5>
-<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></p>
-</h5>
-<p><h4>Android 4.4: SMS APIs</h4>
-Android 4.4 KitKat introduces the new SMS APIs as well as the new concept of a default SMS app. This video discusses these new APIs and how your app should use them to send and receive SMS and MMS messages.<br>
-<h5><a href="http://www.youtube.com/watch?v=mdq0R2WQssQ&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5>
-<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5>
-<i>See also -<br>
-<a href="http://goo.gl/sw5NdH">Android Developer Blog post on Android 4.4 KitKat SMS APIs</a><br>
-<a href="http://goo.gl/7vTx3s">Android Protip on using booleans in your AndroidManifest.xml</a></i></p>
-
-
-<p><h4>Android 4.4 Printing API</h4>
-In this video, we introduce the new Printing API in Android 4.4 KitKat. This API provides a simple way for developers to print to cloud-connected printers using Google Cloud Print. It's really easy to print bitmaps, and HTML (that you generate on the device, or just web content).<br>
-<h5><a href="http://www.youtube.com/watch?v=Iub67ic87KI&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5>
-<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a></h5>
-<h5><a href="http://developer.android.com/training/printing/index.html">Training</a></h5>
-<i>Some pro-tips:</i>
-<ul>
- <li>For Webview/HTML printing, printing from javascript is not supported yet (window.print() for example). Also we are planning to address the limitations around WebView/HTML printing in future releases (eg: headers/footers, and specifying print ranges).</li>
-<li>We encourage developers to open Android Open Source bugs for features that they feel important as a feedback.</li>
-</ul>
-
-<p><h4>App Indexing</h4>
-In this episode we discuss the new App Indexing feature that we recently announced for Google Search for Android.<br>
-Currently, when you do a google search on the web, you get results that are links to websites. With App Indexing, you will be able to point Google Search users on Android directly to content within your app!
-If you’re an Android app developer who has a web presence and you want more control over how your content is accessed from search, via your website or Android app, App Indexing is a great feature for you to explore.
-Also, enabling your website and app for indexing is a way to increase engagement with your app by making the content more discoverable, and more accessible to users directly from the search results page.
-For information on App Indexing, please visit <a href="http://g.co/appindexing">http://g.co/appindexing</a>
-<h5><a href="http://www.youtube.com/watch?v=Xh_W82JgOms&list=PLWz5rJ2EKKc-2quE-o0enpILZF3nBZg_K">Video</a></h5>
-<h5><a href="https://drive.google.com/a/google.com/folderview?id=0BwhAiXVwzMoFc28wWEpyeE9qYTQ&usp=sharing">Presentation</a>
-</p>
-</h5>
-</div>
-
-<h2 id="Social" style="clear:left">Social</h2>
-<div class="col-8" style="margin-left:0">
-
-<h3 >G+</h3>
-
-<ul>
-<li><a href="https://plus.google.com/u/1/108967384991768947849/posts/1iVvwyfTM8y">What's New in Android 4.4</a>
- <ul>
- <li><a href="http://www.youtube.com/watch?v=HrFRY32i_sE">What's New in Android 4.4 [JAPANESE!]</a></li>
- <li><a href="https://www.youtube.com/watch?v=U9jAcwaETD4">What's New in Android 4.4 [KOREAN!]</a></li>
- <li><a href="https://plus.google.com/u/1/108967384991768947849/posts/WfqdvDG2Cyr">Quer saber das novidades do Android 4.4? [PORTUGUESE!]</a></li>
- </ul>
-</li>
-<li><a href="https://plus.google.com/u/1/+AndroidDevelopers/posts/femjRbay18f">Android 4.4 and Updated Developer Tools
-</a></li>
-<li><a href="https://plus.google.com/u/1/108967384991768947849/posts/P2q82aYN7do">Google Play Services 4.0
-</a></li>
-</ul>
-</div>
-
-<div class="col-8" style="margin-right:0">
-<h3>Blog</h3>
-
-<ul>
- <li><a href="http://android-developers.blogspot.hk/2013/10/android-44-kitkat-and-updated-developer.html">Android 4.4 KitKat and Updated Developer Tools</a></li>
- <li><a href="http://android-developers.blogspot.hk/2013/10/google-play-services-40.html">Google Play Services 4.0</a></li>
- <li><a href="http://android-developers.blogspot.hk/2013/10/making-your-app-content-more-accessible.html">Making your App Content more Accessible from Googl...</a></li>
- <li><a href="http://android-developers.blogspot.hk/2013/10/getting-your-sms-apps-ready-for-kitkat.html">Getting Your SMS Apps Ready for KitKat</a></li>
-</ul>
-</div>
-
-</div><!-- /MAIN CONTENT 'wrap' -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/distribute/stories/apps.jd b/docs/html/distribute/stories/apps.jd
index 9a642dcab4d7..76e9f5ac368b 100644
--- a/docs/html/distribute/stories/apps.jd
+++ b/docs/html/distribute/stories/apps.jd
@@ -1,5 +1,4 @@
page.title=Developer Stories: Apps
-meta.tags="apps, developer story"
page.timestamp=1381449601
page.image=images/cards/distribute/stories/intuit-mint.png
page.metaDescription=How app developers are making use of localization, tablet features.
@@ -30,5 +29,5 @@ page.metaDescription=How app developers are making use of localization, tablet f
data-sortOrder="-timestamp"
data-cardSizes="6x6"
data-items-per-page="15"
- data-initial-results="3"></div>
+ data-initial-results="6"></div>
</div></section> \ No newline at end of file
diff --git a/docs/html/distribute/stories/apps/aftenposten.jd b/docs/html/distribute/stories/apps/aftenposten.jd
new file mode 100644
index 000000000000..f1f388e2b6bd
--- /dev/null
+++ b/docs/html/distribute/stories/apps/aftenposten.jd
@@ -0,0 +1,80 @@
+page.title=Aftenposten Improves Retention by Allowing Readers to Customize Notifications
+page.metaDescription=Aftenposten upgraded their app and improved user retention.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/aftenposten.png
+page.timestamp=1468270114
+
+@jd:body
+
+<div class="figure" style="width:113px">
+ <img src="{@docRoot}images/distribute/stories/aftenposten-icon.png" height=
+ "106">
+</div>
+
+<h3>
+ Background
+</h3>
+
+<p>
+ Aftenposten is one of the largest newspapers in Norway. Their <a class=
+ "external-link" href=
+ "https://play.google.com/store/apps/details?id=no.cita&amp;e=-EnableAppDetailsPageRedesign">
+ news app</a> was released on Android in 2013.
+</p>
+
+<p>
+ Aftenposten found that sending too many notifications, with no user control
+ over the default <em>on</em> setting or differentiation between general and
+ breaking news, caused many people to uninstall their app. They changed the
+ user controls for notifications and used the native Android share button in
+ the app, <strong>which reduced user uninstalls</strong>.
+</p>
+
+<h3>
+ What they did
+</h3>
+
+<p>
+ Aftenposten created a new onboarding flow that explained what notifications
+ were available, allowing readers to manage their preferences and customize up
+ to three topics. They also changed their custom share icon for the native
+ Android app.
+</p>
+
+<h3>
+ Results
+</h3>
+
+<p>
+ The results showed that with the new notifications management onboarding
+ screen, <strong>uninstalls decreased by 9.2% over 60 days</strong>. And with
+ the option to customize notifications, 51% of readers decided to keep two out
+ of three topics turned on. This led to a <strong>28% decrease over 60 days in
+ the number of users muting notifications completely</strong>. It also
+ provided insight into users’ content preferences, with <em>Sport</em> being
+ the least-favored notification.
+</p>
+
+<p>
+ Aftenposten also increased share interactions by 17% just by replacing their
+ custom share icon with the native Android share icon.
+</p>
+
+<p>
+ Aftenposten commented that: <em>Many of our users who see the onboarding
+ screen interact with it by turning off at least one notification topic. This
+ means that users are accepting push from one or more topics, instead of
+ turning it off completely. Moreover, readers are sharing more articles since
+ we added the standard share Android icon.</em>
+</p>
+
+<h3>
+ Get started
+</h3>
+
+<p>
+ Find out more about best practices for <a href=
+ "{@docRoot}design/patterns/notifications.html">Notifications</a> and <a href=
+ "{@docRoot}training/building-content-sharing.html">Building Apps with Content
+ Sharing</a>.
+</p>
diff --git a/docs/html/distribute/stories/apps/el-mundo.jd b/docs/html/distribute/stories/apps/el-mundo.jd
new file mode 100644
index 000000000000..2ee813d55d11
--- /dev/null
+++ b/docs/html/distribute/stories/apps/el-mundo.jd
@@ -0,0 +1,73 @@
+page.title=El Mundo Improves User Ratings and Engagement with Material Design
+page.metaDescription=El Mundo uses Material Design principles to enhance their app's user experience.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/el-mundo.png
+page.timestamp=1468270112
+
+@jd:body
+
+<div class="figure" style="width:113px">
+ <img src="{@docRoot}images/distribute/stories/el-mundo-icon.png" height=
+ "113">
+</div>
+
+<h3>
+ Background
+</h3>
+
+<p>
+ <a class="external-link" href=
+ "https://play.google.com/store/apps/details?id=com.gi.elmundo.main">El
+ Mundo</a>, one of Spain’s largest newspapers, integrated material design
+ principles into their app, which helped increase their Google Play Store
+ rating and improve user engagement.
+</p>
+
+<h3>
+ What they did
+</h3>
+
+<p>
+ El Mundo decided to completely redesign their app to provide a higher quality
+ user experience, making it easier for their readers to engage with news
+ content. By implementing material design guidelines, they created a
+ consistent look and feel throughout their app.
+</p>
+
+<p>
+ After analyzing user comments, El Mundo discovered that readers considered
+ their app to be complicated and out-of-date. Therefore, they decided to
+ simplify the app’s functionality by removing features that were redundant.
+ They also removed sections of their app that were less relevant to their
+ readers, such as weather updates and movie trailers. Finally, they applied a
+ brand new internal development framework that they now use consistently
+ across all of their apps.
+</p>
+
+<h3>
+ Results
+</h3>
+
+<p>
+ Following the re-launch of their material design app, El Mundo saw a
+ <strong>45% increase in the weekly install rate</strong>. Readers now spend
+ more time in the app, with the average time spent in-app increasing from one
+ to three minutes.
+</p>
+
+<p>
+ Additionally, this redesign resulted in more readers providing positive
+ feedback around the new experience, increasing the app rating in the Google
+ Play store by 25.8%, from 3.1 to 3.9.
+</p>
+
+<h3>
+ Get started
+</h3>
+
+<p>
+ Learn how to integrate <a class="external-link" href=
+ "https://material.google.com">Material Design</a> guidelines and follow
+ <a class="external-link" href="https://design.google.com">design
+ principles</a> for your app.
+</p>
diff --git a/docs/html/distribute/stories/apps/segundamano.jd b/docs/html/distribute/stories/apps/segundamano.jd
new file mode 100644
index 000000000000..4cbf817c6d43
--- /dev/null
+++ b/docs/html/distribute/stories/apps/segundamano.jd
@@ -0,0 +1,63 @@
+page.title=Segundamano Develops Android-First as Its Fastest Channel for Growth
+page.metaDescription=Segundamano developed Android app to increase potential for growth.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/segundamano.png
+page.timestamp=1468270110
+
+@jd:body
+
+<div class="figure" style="width:113px">
+ <img src="{@docRoot}images/distribute/stories/segundamano-icon.png" height=
+ "113">
+</div>
+
+<h3>
+ Background
+</h3>
+
+<p>
+ <a class="external-link" href=
+ "https://play.google.com/store/apps/details?id=mx.segundamano.android">Segundamano</a>
+ is a leading shopping application in Mexico for second-hand products. They
+ started by placing classified ads in newspapers, progressed to desktop, and
+ over the past year have seen significant growth in mobile, which now accounts
+ for 70% of their business. They have also seen <strong>270% year-over-year
+ growth on the Android platform alone</strong>.
+</p>
+
+<h3>
+ What they did
+</h3>
+
+<p>
+ Segundamano shifted focus to mobile with their Android app because of the
+ high potential for growth. From July 2015 to January 2016, they saw an
+ increase of 55% in the number of classified ads on Android, higher than any
+ other platform. To leverage this momentum, Segundamano implemented two new
+ features on Android: premium offers and push notifications. Segundamano also
+ decided to implement material design in order to improve the in-app
+ experience and streamline the sales process for users.
+</p>
+
+<h3>
+ Results
+</h3>
+
+<p>
+ Following Segundamano’s enhancements to the user experience, they've seen an
+ increase in their star rating, a 4.7% lift in monthly active users, and a 7%
+ increase in sales of premium listings. Additionally, year-to-date, their
+ <strong>installs are over seven times higher on Android than on other
+ platforms</strong>.
+</p>
+
+<h3>
+ Get started
+</h3>
+
+<p>
+ Learn more about simplifying your in-app experience with <a href=
+ "{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a>
+ and the <a href="{@docRoot}design/material/index.html">material design
+ guidelines</a>.
+</p> \ No newline at end of file
diff --git a/docs/html/distribute/stories/apps/tapps.jd b/docs/html/distribute/stories/apps/tapps.jd
new file mode 100644
index 000000000000..129213946630
--- /dev/null
+++ b/docs/html/distribute/stories/apps/tapps.jd
@@ -0,0 +1,366 @@
+page.title=Tapps Games Increases Installs by More Than 20% with Store Listing Experiments
+page.metaDescription=Tapps Games increased their use of store listing experiments in the Developer Console, with impressive results.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/tapps.png
+page.timestamp=1468270108
+
+@jd:body
+
+<style type="text/css">
+ span.positive{
+ color:green;
+ font-size: 125%;
+ font-weight:bold;">
+ }
+ span.negative{
+ color:red;
+ font-size: 125%;
+ font-weight:bold;">
+ }
+</style>
+
+<div class="figure" style="width:215px">
+ <img src="{@docRoot}images/distribute/stories/tapps-logo.png" height="65">
+</div>
+
+<h3>
+ Background
+</h3>
+
+<p>
+ <a class="external-link" href=
+ "https://play.google.com/store/apps/dev?id=6615809648420562690">Tapps</a> is
+ a mobile game publisher in São Paulo, Brazil. With a mission of <em>creating
+ fun for everyone</em>, Tapps has a portfolio of over 200 titles on the Google
+ Play Store, with roughly 70% of their installs coming from Android. Store
+ listing experiments have provided invaluable metrics to help their growing
+ team understand what makes the most effective product listings.
+</p>
+
+<h3>
+ What they did
+</h3>
+
+<p>
+ Tapps has increased their use of store listing experiments in the Developer
+ Console. They recently expanded their marketing team to allocate greater time
+ and designated resources to the Developer Console tools. <strong>"We can’t
+ stress enough how much value the store listing experiments have brought us
+ over the past months. Right now, our marketing team has a substantial time
+ allocated to these tests every week,"</strong> said Felipe Watanabe, head of
+ marketing at Tapps. With icons and screenshots, Tapps tested variations in
+ color, character positioning, and the overall amount of graphic detail. In
+ the description tests, they found that shorter messages with clear calls to
+ action and appropriate language localizations were most successful.
+</p>
+
+<h3>
+ Results
+</h3>
+
+<p>
+ By frequently conducting store listing experiments, Tapps gained valuable
+ insights that they have applied across their greater portfolio of games.
+ Results showed that shortening messaging, using contrasting colors,
+ reordering screenshots, and simplifying graphics often led to variant results
+ representing an average increase in performance between 5% and 50%. After
+ making changes based on the test results, Tapps saw <strong>install rates
+ increase beyond 20-30%</strong>.
+</p>
+
+<h4>
+ Screen tests
+</h4>
+
+<p>
+ The following table compares the install rates for three apps based on
+ changes to each app's screenshot.
+</p>
+
+<p class="table-caption">
+ <strong>Table 1</strong>. Screen test results
+</p>
+
+<table>
+ <tr>
+ <th>
+ Original
+ </th>
+ <th>
+ Variant
+ </th>
+ <th>
+ Variant results
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-orig-3.png"
+ width="240">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-var-3.png"
+ width="240">
+ </td>
+ <td>
+ <span class="positive">+25%</span>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-orig-1.png"
+ width="240">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-var-1.png"
+ width="240">
+ </td>
+ <td>
+ <span class="positive">+17.1%</span>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-orig-2.png"
+ width="240">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-screen-var-2.png"
+ width="240">
+ </td>
+ <td>
+ <span class="positive">+7.4%</span>
+ </td>
+ </tr>
+
+</table>
+
+<h4>
+ Icon tests
+</h4>
+
+<p>
+ The following tables compare install rates for three apps based on changes
+ to each app's icon.
+</p>
+
+<p class="table-caption">
+ <strong>Table 2</strong>. Icon 1 test results
+</p>
+
+<table>
+ <tr>
+ <th>
+ Original
+ </th>
+ <th>
+ Variant 1
+ </th>
+ <th>
+ Variant 2
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-orig-1.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-1.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-1-2.png">
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ ---
+ </td>
+ <td>
+ <span class="negative">-29.6%</span>
+ </td>
+ <td>
+ <span class="positive">+20.8%</span>
+ </td>
+ </tr>
+</table>
+
+<p class="table-caption">
+ <strong>Table 3</strong>. Icon 2 test results
+</p>
+
+<table>
+ <tr>
+ <th>
+ Original
+ </th>
+ <th>
+ Variant 1
+ </th>
+ <th>
+ Variant 2
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-orig-2.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-2.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-2-2.png">
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ ---
+ </td>
+ <td>
+ <span class="positive">+5.1%</span>
+ </td>
+ <td>
+ <span class="positive">+19.7%</span>
+ </td>
+ </tr>
+</table>
+
+<p class="table-caption">
+ <strong>Table 4</strong>. Icon 3 test results
+</p>
+
+<table>
+ <tr>
+ <th>
+ Original
+ </th>
+ <th>
+ Variant 1
+ </th>
+ <th>
+ Variant 2
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-orig-3.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-3.png">
+ </td>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-icon-var-3-2.png">
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ ---
+ </td>
+ <td>
+ <span class="negative">-17.7%</span>
+ </td>
+ <td>
+ <span class="positive">+50.7%</span>
+ </td>
+ </tr>
+</table>
+
+<h4>
+ Description tests
+</h4>
+
+<p>
+ The following table compares install rates for three apps based on changes to
+ each app's description text.
+</p>
+
+<p class="table-caption">
+ <strong>Table 5</strong>. Description test results
+</p>
+
+<table>
+ <tr>
+ <th>
+ Game
+ </th>
+ <th>
+ Original
+ </th>
+ <th>
+ Variant
+ </th>
+ <th>
+ Variant results
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-logic-pic.png">
+ <strong>Logic Pic</strong>
+ </td>
+ <td>
+ <em>"Use logic to solve fun puzzles and discover hidden pictures! Logic
+ Pic is free!"</em>
+ </td>
+ <td>
+ <strong><em>"Discover all the hidden pictures in this challenging classic
+ japanese puzzle!"</em></strong>
+ </td>
+ <td>
+ <span class="positive">+10.7%</span>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-candy-hills.png"
+ width="96"> <strong>Candy Hills</strong>
+ </td>
+ <td>
+ <em>"What will your candy park look like? Build it now in Candy
+ Hills!"</em>
+ </td>
+ <td>
+ <strong><em>"Build your own sweet candy park in Candy
+ Hills!"</em></strong>
+ </td>
+ <td>
+ <span class="positive">+8.2%</span>
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ <img src="{@docRoot}images/distribute/stories/tapps-villains-corp.png"
+ width="96"> <strong>Villains Corp.</strong>
+ </td>
+ <td>
+ <em>"Be a real villain and CONQUER THE WORLD!"</em>
+ </td>
+ <td>
+ <strong><em>"Mwahahaha! Be a real villain and CONQUER THE
+ WORLD!"</em></strong>
+ </td>
+ <td>
+ <span class="positive">+6.8%</span>
+ </td>
+ </tr>
+</table>
+
+<h3>
+ Get started
+</h3>
+
+<p>
+ Find out more about <a href=
+ "{@docRoot}distribute/users/experiments.html">store listing experiments</a>.
+</p>
diff --git a/docs/html/distribute/stories/apps/upbeat-games.jd b/docs/html/distribute/stories/apps/upbeat-games.jd
new file mode 100644
index 000000000000..02222d39e686
--- /dev/null
+++ b/docs/html/distribute/stories/apps/upbeat-games.jd
@@ -0,0 +1,69 @@
+page.title=Witch Puzzle Achieves 98% of International Installs on Android
+page.metaDescription=Witch Puzzle localized their app into 12 languages.
+page.tags="developerstory", "apps", "googleplay"
+page.image=images/cards/distribute/stories/witch-puzzle.png
+page.timestamp=1468270106
+
+@jd:body
+
+
+<div class="figure">
+ <img src="{@docRoot}images/distribute/stories/witch-puzzle-icon.png"
+ width="113">
+</div>
+
+<h3>
+ Background
+</h3>
+
+<p>
+ Located in São Paulo, Brazil, <a class="external-link" href=
+ "https://play.google.com/store/apps/dev?id=8995071809141037139">Upbeat
+ Games</a> is an indie game developer with a mission to build fun and easy
+ games that anyone can play. As a small team, the Upbeat crew reacted quickly
+ to their game’s growing installs in Asian countries, and is now seeing strong
+ international growth with their game <a class="external-link" href=
+ "https://play.google.com/store/apps/details?id=com.upbeatgames.witchpuzzle">Witch
+ Puzzle</a>.
+</p>
+
+<h3>
+ What they did
+</h3>
+
+<p>
+ After noticing that Witch Puzzle was gaining traction throughout Asia, Upbeat
+ localized their game into 12 languages, prioritizing countries with an
+ existing user base and high gross national income (GNI). This led to a direct
+ increase in installs.
+</p>
+
+<div class="figure">
+ <img src="{@docRoot}images/distribute/stories/japanese-witch-puzzle.png"
+ width="214">
+ <p class="img-caption">
+ Japanese version of Witch Puzzle
+ </p>
+</div>
+
+<h3>
+ Results
+</h3>
+
+<p>
+ “In the last three months, 98% of our international installs for Witch Puzzle
+ came from Android,†said Vinicius Sormani Heimbeck, Upbeat’s founder. Upbeat
+ applied these learnings across their portfolio of games. Now, <strong>75% of
+ their portfolio’s revenue is driven by Android</strong>.
+</p>
+
+<h3>
+ Get started
+</h3>
+
+<p>
+ Use the <a href=
+ "{@docRoot}distribute/tools/localization-checklist.html">Localization
+ Checklist</a> to learn more about tailoring your app for different markets to
+ drive installs and revenue, and to create a better overall user experience.
+</p>
diff --git a/docs/html/distribute/stories/games.jd b/docs/html/distribute/stories/games.jd
index fe059ebae4a3..daaac0d2acc8 100644
--- a/docs/html/distribute/stories/games.jd
+++ b/docs/html/distribute/stories/games.jd
@@ -1,5 +1,4 @@
page.title=Developer Stories: Games
-meta.tags="google play, games, global, developer story"
page.timestamp=1381449601
page.image=/images/distribute/glu-ew-gpgames.jpg
page.metaDescription=How game studios are using Google Play game services to deliver new gaming experiences for their users.
diff --git a/docs/html/guide/topics/resources/layout-resource.jd b/docs/html/guide/topics/resources/layout-resource.jd
index 8c5708a4b122..ab381c33fb84 100644
--- a/docs/html/guide/topics/resources/layout-resource.jd
+++ b/docs/html/guide/topics/resources/layout-resource.jd
@@ -33,16 +33,17 @@ In XML: <code>@[<em>package</em>:]layout/<em>filename</em></code>
<dt>syntax:</dt>
<dd>
<pre class="stx">
-&lt;?xml version="1.0" encoding="utf-8"?>
-&lt;<a href="#viewgroup-element"><em>ViewGroup</em></a> xmlns:android="http://schemas.android.com/apk/res/android"
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;<a href="#viewgroup-element"><em>ViewGroup</em></a>
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@[+][<em>package</em>:]id/<em>resource_name</em>"
- android:layout_height=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
- android:layout_width=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
+ android:layout_height=["<em>dimension</em>" | "match_parent" | "wrap_content"]
+ android:layout_width=["<em>dimension</em>" | "match_parent" | "wrap_content"]
[<em>ViewGroup-specific attributes</em>] &gt;
&lt;<a href="#view-element"><em>View</em></a>
android:id="@[+][<em>package</em>:]id/<em>resource_name</em>"
- android:layout_height=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
- android:layout_width=["<em>dimension</em>" | "fill_parent" | "wrap_content"]
+ android:layout_height=["<em>dimension</em>" | "match_parent" | "wrap_content"]
+ android:layout_width=["<em>dimension</em>" | "match_parent" | "wrap_content"]
[<em>View-specific attributes</em>] &gt;
&lt;<a href="#requestfocus-element">requestFocus</a>/&gt;
&lt;/<em>View</em>&gt;
@@ -82,15 +83,17 @@ about the <a href="#idvalue">value for {@code android:id}</a> below.
</dd>
<dt><code>android:layout_height</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The height for the group, as a
-dimension value (or <a
-href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
-or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
+dimension value (or
+<a href="more-resources.html#Dimension">dimension resource</a>) or a keyword
+({@code "match_parent"} or {@code "wrap_content"}). See the <a href=
+"#layoutvalues">valid values</a> below.
</dd>
<dt><code>android:layout_width</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The width for the group, as a
-dimension value (or <a
-href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
-or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
+dimension value (or
+<a href="more-resources.html#Dimension">dimension resource</a>) or a keyword
+({@code "match_parent"} or {@code "wrap_content"}). See the <a href=
+"#layoutvalues">valid values</a> below.
</dd>
</dl>
<p>More attributes are supported by the {@link android.view.ViewGroup}
@@ -114,15 +117,17 @@ the <a href="#idvalue">value for {@code android:id}</a> below.
</dd>
<dt><code>android:layout_height</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The height for the element, as
-a dimension value (or <a
-href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
-or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
+a dimension value (or
+<a href="more-resources.html#Dimension">dimension resource</a>) or a keyword
+({@code "match_parent"} or {@code "wrap_content"}). See the <a href=
+"#layoutvalues">valid values</a> below.
</dd>
<dt><code>android:layout_width</code></dt>
<dd><em>Dimension or keyword</em>. <strong>Required</strong>. The width for the element, as
-a dimension value (or <a
-href="more-resources.html#Dimension">dimension resource</a>) or a keyword ({@code "fill_parent"}
-or {@code "wrap_content"}). See the <a href="#layoutvalues">valid values</a> below.
+a dimension value (or
+<a href="more-resources.html#Dimension">dimension resource</a>) or a keyword
+({@code "match_parent"} or {@code "wrap_content"}). See the <a href=
+"#layoutvalues">valid values</a> below.
</dd>
</dl>
<p>More attributes are supported by the {@link android.view.View}
@@ -221,9 +226,6 @@ plus symbol in the <code>android:id</code> value.</p>
deprecate <code>fill_parent</code>.</td>
</tr>
<tr>
- <td><code>fill_parent</code></td>
- <td>Sets the dimension to match that of the parent element.</td>
- </tr><tr>
<td><code>wrap_content</code></td>
<td>Sets the dimension only to the size required to fit the content of this element.</td>
</tr>
@@ -245,8 +247,8 @@ guide.
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:orientation="vertical" >
&lt;TextView android:id="@+id/text"
android:layout_width="wrap_content"
@@ -279,4 +281,4 @@ public void onCreate(Bundle savedInstanceState) {
</ul>
</dd>
-</dl>
+</dl> \ No newline at end of file
diff --git a/docs/html/guide/topics/security/permissions.jd b/docs/html/guide/topics/security/permissions.jd
index e7bf760bb84a..39a1f814e49a 100644
--- a/docs/html/guide/topics/security/permissions.jd
+++ b/docs/html/guide/topics/security/permissions.jd
@@ -675,7 +675,7 @@ Services that cost you money: send SMS messages, directly call phone numbers
<a name="manifest"></a>
<h3>Enforcing Permissions in AndroidManifest.xml</h3>
-<p>TYou can apply high-level permissions restricting access to entire components
+<p>You can apply high-level permissions restricting access to entire components
of the system or application through your
<code>AndroidManifest.xml</code>. To do this, include an {@link
android.R.attr#permission android:permission} attribute on the desired
diff --git a/docs/html/images/cards/distribute/stories/aftenposten.png b/docs/html/images/cards/distribute/stories/aftenposten.png
new file mode 100644
index 000000000000..60cb85104f8c
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/aftenposten.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/el-mundo.png b/docs/html/images/cards/distribute/stories/el-mundo.png
new file mode 100644
index 000000000000..23db783d47dd
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/el-mundo.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/segundamano.png b/docs/html/images/cards/distribute/stories/segundamano.png
new file mode 100644
index 000000000000..60e873c0c8cb
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/segundamano.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/tapps.png b/docs/html/images/cards/distribute/stories/tapps.png
new file mode 100644
index 000000000000..e01e3adf596d
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/tapps.png
Binary files differ
diff --git a/docs/html/images/cards/distribute/stories/witch-puzzle.png b/docs/html/images/cards/distribute/stories/witch-puzzle.png
new file mode 100644
index 000000000000..c336f1bf16ef
--- /dev/null
+++ b/docs/html/images/cards/distribute/stories/witch-puzzle.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/aftenposten-icon.png b/docs/html/images/distribute/stories/aftenposten-icon.png
new file mode 100644
index 000000000000..60cb85104f8c
--- /dev/null
+++ b/docs/html/images/distribute/stories/aftenposten-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/el-mundo-icon.png b/docs/html/images/distribute/stories/el-mundo-icon.png
new file mode 100644
index 000000000000..23db783d47dd
--- /dev/null
+++ b/docs/html/images/distribute/stories/el-mundo-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/japanese-witch-puzzle.png b/docs/html/images/distribute/stories/japanese-witch-puzzle.png
new file mode 100644
index 000000000000..6a7ef13dd9f9
--- /dev/null
+++ b/docs/html/images/distribute/stories/japanese-witch-puzzle.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/segundamano-icon.png b/docs/html/images/distribute/stories/segundamano-icon.png
new file mode 100644
index 000000000000..60e873c0c8cb
--- /dev/null
+++ b/docs/html/images/distribute/stories/segundamano-icon.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-candy-hills.png b/docs/html/images/distribute/stories/tapps-candy-hills.png
new file mode 100644
index 000000000000..14dcb9447ba6
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-candy-hills.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-orig-1.png b/docs/html/images/distribute/stories/tapps-icon-orig-1.png
new file mode 100644
index 000000000000..44af423f3795
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-orig-1.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-orig-2.png b/docs/html/images/distribute/stories/tapps-icon-orig-2.png
new file mode 100644
index 000000000000..1b362557b2b0
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-orig-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-orig-3.png b/docs/html/images/distribute/stories/tapps-icon-orig-3.png
new file mode 100644
index 000000000000..2f393f8ba965
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-orig-3.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-1-2.png b/docs/html/images/distribute/stories/tapps-icon-var-1-2.png
new file mode 100644
index 000000000000..fecab6e06f90
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-1-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-1.png b/docs/html/images/distribute/stories/tapps-icon-var-1.png
new file mode 100644
index 000000000000..77bd02a17f63
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-1.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-2-2.png b/docs/html/images/distribute/stories/tapps-icon-var-2-2.png
new file mode 100644
index 000000000000..84166c43c9f1
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-2-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-2.png b/docs/html/images/distribute/stories/tapps-icon-var-2.png
new file mode 100644
index 000000000000..939c2fdf1b34
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-3-2.png b/docs/html/images/distribute/stories/tapps-icon-var-3-2.png
new file mode 100644
index 000000000000..4aa782d0b9f9
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-3-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-icon-var-3.png b/docs/html/images/distribute/stories/tapps-icon-var-3.png
new file mode 100644
index 000000000000..1e44fdf7cfbc
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-icon-var-3.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-logic-pic.png b/docs/html/images/distribute/stories/tapps-logic-pic.png
new file mode 100644
index 000000000000..5029f79ca610
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-logic-pic.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-logo.png b/docs/html/images/distribute/stories/tapps-logo.png
new file mode 100644
index 000000000000..e01e3adf596d
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-logo.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-orig-1.png b/docs/html/images/distribute/stories/tapps-screen-orig-1.png
new file mode 100644
index 000000000000..d54e75c8dd80
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-orig-1.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-orig-2.png b/docs/html/images/distribute/stories/tapps-screen-orig-2.png
new file mode 100644
index 000000000000..a2d18e3cd0da
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-orig-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-orig-3.png b/docs/html/images/distribute/stories/tapps-screen-orig-3.png
new file mode 100644
index 000000000000..e01fe20fb6b2
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-orig-3.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-var-1.png b/docs/html/images/distribute/stories/tapps-screen-var-1.png
new file mode 100644
index 000000000000..b93035093d3f
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-var-1.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-var-2.png b/docs/html/images/distribute/stories/tapps-screen-var-2.png
new file mode 100644
index 000000000000..9ccb8a647e44
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-var-2.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-screen-var-3.png b/docs/html/images/distribute/stories/tapps-screen-var-3.png
new file mode 100644
index 000000000000..8eb58e1cb6d1
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-screen-var-3.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/tapps-villains-corp.png b/docs/html/images/distribute/stories/tapps-villains-corp.png
new file mode 100644
index 000000000000..6e037dad4f23
--- /dev/null
+++ b/docs/html/images/distribute/stories/tapps-villains-corp.png
Binary files differ
diff --git a/docs/html/images/distribute/stories/witch-puzzle-icon.png b/docs/html/images/distribute/stories/witch-puzzle-icon.png
new file mode 100644
index 000000000000..c336f1bf16ef
--- /dev/null
+++ b/docs/html/images/distribute/stories/witch-puzzle-icon.png
Binary files differ
diff --git a/docs/html/images/training/tv/tif/app-link-2x.png b/docs/html/images/training/tv/tif/app-link-2x.png
new file mode 100644
index 000000000000..d9d058231b14
--- /dev/null
+++ b/docs/html/images/training/tv/tif/app-link-2x.png
Binary files differ
diff --git a/docs/html/images/training/tv/tif/app-link-diagram.png b/docs/html/images/training/tv/tif/app-link-diagram.png
new file mode 100644
index 000000000000..92328adfcd7c
--- /dev/null
+++ b/docs/html/images/training/tv/tif/app-link-diagram.png
Binary files differ
diff --git a/docs/html/images/training/tv/tif/app-link.png b/docs/html/images/training/tv/tif/app-link.png
new file mode 100644
index 000000000000..7573a188b03e
--- /dev/null
+++ b/docs/html/images/training/tv/tif/app-link.png
Binary files differ
diff --git a/docs/html/preview/setup-sdk.jd b/docs/html/preview/setup-sdk.jd
index 3e95f3e864c0..ff11e8e93c3f 100644
--- a/docs/html/preview/setup-sdk.jd
+++ b/docs/html/preview/setup-sdk.jd
@@ -77,32 +77,10 @@ Android N Preview SDK in Android Studio as follows:</p>
<h3 id="docs-dl">Get the N Preview reference documentation</h3>
<p>Beginning with the Preview 4 release, the API reference for the
-N platform (API level 24) is now available online at <a href=
- "{@docRoot}reference/">developer.android.com/reference/</a>.
-</p>
-
-<p>If you'd like an offline copy of the API reference, you can download it
-from the following table. The download also includes an incremental diff report
-for API changes between the Preview 3 and Preview 4 release, which is not
-available online.</p>
-
-<table>
- <tr>
- <th scope="col">Documentation</th>
- <th scope="col">Checksums</th>
- </tr>
- <tr>
- <td style="white-space: nowrap">
- <a href="{@docRoot}shareables/preview/n-preview-4-docs.zip"
- >n-preview-4-docs.zip</a></td>
- <td width="100%">
- MD5: f853e3ba0707083336dfa780b8fed9a7<br>
- SHA-1: 36fcbc497cc2e63b1bc1d629c304b0ba43a88946
- </td>
- </tr>
-</table>
-
-
+ N platform (API level 24) is now available online at <a href=
+ "{@docRoot}reference/">developer.android.com/reference/</a>. There is also
+ an incremental diff report for <a href="{@docRoot}sdk/api_diff/24/changes.html"
+ >API changes between API levels 23 and 24</a>.</p>
<h2 id="java8">Get the Java 8 JDK</h2>
diff --git a/docs/html/topic/libraries/support-library/features.jd b/docs/html/topic/libraries/support-library/features.jd
index 584bef8a7981..d648384399da 100755
--- a/docs/html/topic/libraries/support-library/features.jd
+++ b/docs/html/topic/libraries/support-library/features.jd
@@ -142,7 +142,7 @@ page.title=Support Library Features
</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/v4/} directory. The library does not contain user
+<code>&lt;sdk&gt;/extras/android/support/v4/</code> directory. The library does not contain user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
resources</a>.</p>
@@ -169,7 +169,7 @@ com.android.support:support-v4:23.3.0
<p>
After you download the Android Support Libraries, this library is located in the
- {@code &lt;sdk&gt;/extras/android/support/multidex/} directory. The library does not contain
+ <code>&lt;sdk&gt;/extras/android/support/multidex/</code> directory. The library does not contain
user interface resources. To include it in your application project, follow the instructions
for
<a href= "{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
@@ -229,7 +229,7 @@ com.android.support:multidex:1.0.0
</ul>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/v7/appcompat/} directory. The library contains user
+<code>&lt;sdk&gt;/extras/android/support/v7/appcompat/</code> directory. The library contains user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries with
resources</a>.</p>
@@ -250,7 +250,7 @@ on any app. These cards are useful for material design
implementations, and are used extensively in layouts for TV apps.</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/v7/cardview/} directory. The library contains user interface
+<code>&lt;sdk&gt;/extras/android/support/v7/cardview/</code> directory. The library contains user interface
resources. To include it in your application project, follow the instructions
for <a href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding
libraries with resources</a>.</p>
@@ -271,7 +271,7 @@ allows you to arrange user interface elements using a grid of rectangular cells.
For detailed information about the v7 gridlayout library APIs, see the
{@link android.support.v7.widget android.support.v7.widget} package in the API reference.</p>
-<p>This library is located in the {@code &lt;sdk&gt;/extras/android/support/v7/gridlayout/}
+<p>This library is located in the <code>&lt;sdk&gt;/extras/android/support/v7/gridlayout/</code>
directory . The library contains user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries with
@@ -332,7 +332,7 @@ from an album cover, and use those colors to build a color-coordinated song
title card.</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/v7/palette/} directory. The library does not contain
+<code>&lt;sdk&gt;/extras/android/support/v7/palette/</code> directory. The library does not contain
user interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
resources</a>.</p>
@@ -354,7 +354,7 @@ widget, a view for efficiently displaying large data sets by providing a
limited window of data items.</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/v7/recyclerview/} directory. The library contains
+<code>&lt;sdk&gt;/extras/android/support/v7/recyclerview/</code> directory. The library contains
user interface resources. To include it in your application project, follow the instructions
for <a href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding
libraries with resources</a>.</p>
@@ -383,7 +383,7 @@ such as {@link android.support.v7.preference.CheckBoxPreference} and
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/v7/preference} directory. For more information
+<code>&lt;sdk&gt;/extras/android/support/v7/preference</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -447,7 +447,7 @@ defaultConfig {
</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/v13/} directory. The library does not contain user
+<code>&lt;sdk&gt;/extras/android/support/v13/</code> directory. The library does not contain user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
resources</a>.</p>
@@ -479,7 +479,7 @@ for preference interfaces such as
</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/v14/} directory. The library does not contain user
+<code>&lt;sdk&gt;/extras/android/support/v14/</code> directory. The library does not contain user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
resources</a>.</p>
@@ -508,7 +508,7 @@ interface and classes, such as
</p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/v17/} directory. The library does not contain user
+<code>&lt;sdk&gt;/extras/android/support/v17/</code> directory. The library does not contain user
interface resources. To include it in your application project, follow the instructions for
<a href="{@docRoot}tools/support-library/setup.html#libs-without-res">Adding libraries without
resources</a>.</p>
@@ -550,7 +550,7 @@ com.android.support:preference-leanback-v17:23.3.0
</ul>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/v17/leanback} directory. For more information
+<code>&lt;sdk&gt;/extras/android/support/v17/leanback</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -571,7 +571,7 @@ package provides APIs to support adding annotation metadata to your apps. </p>
<p></p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/annotations} directory. For more information
+<code>&lt;sdk&gt;/extras/android/support/annotations</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -596,7 +596,7 @@ snackbars, and <a href="{@docRoot}design/building-blocks/tabs.html">tabs</a>. <
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/design} directory. For more information
+<code>&lt;sdk&gt;/extras/android/support/design</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -624,7 +624,7 @@ Callback</a>. </p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/customtabs} directory. For more information
+<code>&lt;sdk&gt;/extras/android/support/customtabs</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -655,7 +655,7 @@ PercentRelativeLayout</a>. </p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/percent} directory. For more information
+<code>&lt;sdk&gt;/extras/android/support/percent</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
@@ -685,7 +685,7 @@ RecommendationExtender</a>. </p>
<p>After you download the Android Support Libraries, this library is located in the
-{@code &lt;sdk&gt;/extras/android/support/recommendation} directory. For more information
+<code>&lt;sdk&gt;/extras/android/support/recommendation</code> directory. For more information
on how to set up your project, follow the instructions in <a
href="{@docRoot}tools/support-library/setup.html#libs-with-res">Adding libraries
with resources</a>. </p>
diff --git a/docs/html/topic/performance/index.jd b/docs/html/topic/performance/index.jd
index 08c610f291dc..e08db15baa08 100644
--- a/docs/html/topic/performance/index.jd
+++ b/docs/html/topic/performance/index.jd
@@ -1,6 +1,6 @@
page.title=Performance
page.article=true
-page.metaDescription=Android Performance does nice things. Details to come.
+page.metaDescription=Improve your app's performance by learning how to optimize power consumption, launch times, and other important areas of performance.
meta.tags="performance"
page.tags="performance"
diff --git a/docs/html/topic/performance/launch-time.jd b/docs/html/topic/performance/launch-time.jd
index c9ce1d56185f..84d5fab12a6b 100644
--- a/docs/html/topic/performance/launch-time.jd
+++ b/docs/html/topic/performance/launch-time.jd
@@ -112,7 +112,7 @@ other.
</p>
<br/>
- <img src="{@docRoot}performance/images/cold-launch.png">
+ <img src="{@docRoot}topic/performance/images/cold-launch.png">
<p class="img-caption">
<strong>Figure 1.</strong> A visual representation of the important parts of
a cold application launch.
@@ -262,7 +262,7 @@ the {@code Displayed} time.
</p>
<br/>
- <img src="{@docRoot}performance/images/displayed-logcat.png">
+ <img src="{@docRoot}topic/performance/images/displayed-logcat.png">
<p class="img-caption">
<strong>Figure 2.</strong> Disabling filters, and
finding the {@code Displayed} value in logcat.
diff --git a/docs/html/training/articles/perf-tips.jd b/docs/html/training/articles/perf-tips.jd
index 4a3184c76fe8..82de69a55249 100644
--- a/docs/html/training/articles/perf-tips.jd
+++ b/docs/html/training/articles/perf-tips.jd
@@ -43,7 +43,7 @@ processors running at different speeds. It's not even generally the case
that you can simply say "device X is a factor F faster/slower than device Y",
and scale your results from one device to others. In particular, measurement
on the emulator tells you very little about performance on any device. There
-are also huge differences between devices with and without a
+are also huge differences between devices with and without a
<acronym title="Just In Time compiler">JIT</acronym>: the best
code for a device with a JIT is not always the best code for a device
without.</p>
@@ -88,7 +88,7 @@ parallel single one-dimension arrays:</p>
but this also generalizes to the fact that two parallel arrays of ints
are also a <strong>lot</strong> more efficient than an array of {@code (int,int)}
objects. The same goes for any combination of primitive types.</li>
-
+
<li>If you need to implement a container that stores tuples of {@code (Foo,Bar)}
objects, try to remember that two parallel {@code Foo[]} and {@code Bar[]} arrays are
generally much better than a single array of custom {@code (Foo,Bar)} objects.
@@ -401,19 +401,6 @@ final fields too.)
need to solve. Make sure you can accurately measure your existing performance,
or you won't be able to measure the benefit of the alternatives you try.</p>
-<p>Every claim made in this document is backed up by a benchmark. The source
-to these benchmarks can be found in the <a
-href="http://code.google.com/p/dalvik/source/browse/#svn/trunk/benchmarks">code.google.com
-"dalvik" project</a>.</p>
-
-<p>The benchmarks are built with the
-<a href="http://code.google.com/p/caliper/">Caliper</a> microbenchmarking
-framework for Java. Microbenchmarks are hard to get right, so Caliper goes out
-of its way to do the hard work for you, and even detect some cases where you're
-not measuring what you think you're measuring (because, say, the VM has
-managed to optimize all your code away). We highly recommend you use Caliper
-to run your own microbenchmarks.</p>
-
<p>You may also find
<a href="{@docRoot}tools/debugging/debugging-tracing.html">Traceview</a> useful
for profiling, but it's important to realize that it currently disables the JIT,
diff --git a/docs/html/training/basics/data-storage/files.jd b/docs/html/training/basics/data-storage/files.jd
index 58a1d5ff2b0e..349af78338b9 100644
--- a/docs/html/training/basics/data-storage/files.jd
+++ b/docs/html/training/basics/data-storage/files.jd
@@ -192,7 +192,7 @@ public File getTempFile(Context context, String url) {
try {
String fileName = Uri.parse(url).getLastPathSegment();
file = File.createTempFile(fileName, null, context.getCacheDir());
- catch (IOException e) {
+ } catch (IOException e) {
// Error while creating file
}
return file;
@@ -259,7 +259,7 @@ these files should remain available to the user.
your app. Although these files are technically accessible by the user and other apps because they
are on the external storage, they are files that realistically don't provide value to the user
outside your app. When the user uninstalls your app, the system deletes
- all files in your app's external private directory.
+ all files in your app's external private directory.
<p>For example, additional resources downloaded by your app or temporary media files.</p>
</dd>
</dl>
@@ -274,7 +274,7 @@ android.os.Environment#DIRECTORY_PICTURES}. For example:</p>
<pre>
public File getAlbumStorageDir(String albumName) {
- // Get the directory for the user's public pictures directory.
+ // Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -296,7 +296,7 @@ user uninstalls your app.</p>
<pre>
public File getAlbumStorageDir(Context context, String albumName) {
- // Get the directory for the app's private pictures directory.
+ // Get the directory for the app's private pictures directory.
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
@@ -375,7 +375,7 @@ myContext.deleteFile(fileName);
<div class="note">
<p><strong>Note:</strong> When the user uninstalls your app, the Android system deletes
-the following:</p>
+the following:</p>
<ul>
<li>All files you saved on internal storage</li>
<li>All files you saved on external storage using {@link
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index e66237a2fdfe..4c2155b36314 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -93,13 +93,19 @@ lesson.</p>
Activities</a> for more information.</p>
</div>
</div>
- <li>Under <strong>Add an activity to &lt;<em>template</em>&gt;</strong>, select <strong>Blank
- Activity</strong> and click <strong>Next</strong>.</li>
+ <li>Under <strong>Add an activity to &lt;<em>template</em>&gt;</strong>,
+ select <strong>Basic Activity</strong> and click <strong>Next</strong>.
+ </li>
+
<li>Under <strong>Customize the Activity</strong>, change the
- <strong>Activity Name</strong> to <em>MyActivity</em>. The <strong>Layout Name</strong> changes
- to <em>activity_my</em>, and the <strong>Title</strong> to <em>MyActivity</em>. The
- <strong>Menu Resource Name</strong> is <em>menu_my</em>.
- <li>Click the <strong>Finish</strong> button to create the project.</li>
+ <strong>Activity Name</strong> to <em>MyActivity</em>. The <strong>Layout
+ Name</strong> changes to <em>activity_my</em>, and the <strong>Title</strong>
+ to <em>MyActivity</em>. The <strong>Menu Resource Name</strong> is
+ <em>menu_my</em>.
+ </li>
+
+ <li>Click the <strong>Finish</strong> button to create the project.
+ </li>
</ol>
<p>Your Android project is now a basic "Hello World" app that contains some default files. Take a
@@ -180,4 +186,6 @@ moment to review the most important of these:</p>
string and color definitions.</dd>
</dl>
-<p>To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
+<p>
+ To run the app, continue to the <a href="running-app.html">next lesson</a>.
+</p> \ No newline at end of file
diff --git a/docs/html/training/displaying-bitmaps/load-bitmap.jd b/docs/html/training/displaying-bitmaps/load-bitmap.jd
index f963baac3a0d..81eb1ab58ef5 100644
--- a/docs/html/training/displaying-bitmaps/load-bitmap.jd
+++ b/docs/html/training/displaying-bitmaps/load-bitmap.jd
@@ -115,8 +115,8 @@ public static int calculateInSampleSize(
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
- while ((halfHeight / inSampleSize) &gt; reqHeight
- && (halfWidth / inSampleSize) &gt; reqWidth) {
+ while ((halfHeight / inSampleSize) &gt;= reqHeight
+ && (halfWidth / inSampleSize) &gt;= reqWidth) {
inSampleSize *= 2;
}
}
diff --git a/docs/html/training/testing/ui-testing/uiautomator-testing.jd b/docs/html/training/testing/ui-testing/uiautomator-testing.jd
index 05ddc348efdb..5d42107f88ec 100644
--- a/docs/html/training/testing/ui-testing/uiautomator-testing.jd
+++ b/docs/html/training/testing/ui-testing/uiautomator-testing.jd
@@ -26,7 +26,7 @@ trainingnavtop=true
<h2>You should also read</h2>
<ul>
- <li><a href="{@docRoot}reference/android/support/test/package-summary.html">
+ <li><a href="{@docRoot}reference/android/support/test/uiautomator/package-summary.html">
UI Automator API Reference</a></li>
</ul>
diff --git a/docs/html/training/tv/tif/channel.jd b/docs/html/training/tv/tif/channel.jd
index 999f1ca9c5c5..59e357a316ac 100644
--- a/docs/html/training/tv/tif/channel.jd
+++ b/docs/html/training/tv/tif/channel.jd
@@ -13,6 +13,7 @@ trainingnavtop=true
<li><a href="#permission">Get Permission</a></li>
<li><a href="#register">Register Channels in the Database</a></li>
<li><a href="#update">Update Channel Data</a></li>
+ <li><a href="#applink">Add App Link Information</a></li>
</ol>
<h2>Try It Out</h2>
<ul>
@@ -22,10 +23,13 @@ trainingnavtop=true
</div>
</div>
-<p>Your TV input must provide Electronic Program Guide (EPG) data for at least one channel in its
-setup activity. You should also periodically update that data, with consideration for the size of
-the update and the processing thread that handles it. This lesson discusses creating and updating
-channel and program data on the system database with these considerations in mind.</p>
+<p>Your TV input must provide Electronic Program Guide (EPG) data for at least
+one channel in its setup activity. You should also periodically update that
+data, with consideration for the size of the update and the processing thread
+that handles it. Additionally, you can provide app links for channels
+that guide the user to related content and activities.
+This lesson discusses creating and updating channel and program data on the
+system database with these considerations in mind.</p>
<p>&nbsp;</p>
@@ -70,6 +74,10 @@ addition to those above to better identify traditional broadcast channels:</p>
ID</li>
</ul>
+<p>If you want to provide app link details for your channels, you need to
+update some additional fields. For more information on app link fields, see
+<a href="#applink">Add App Link Information</a>.
+
<p>For internet streaming based TV inputs, assign your own values to the above accordingly so that
each channel can be identified uniquely.</p>
@@ -236,4 +244,112 @@ Android TV live TV sample app</a> for an example.</p>
<p>Other techniques to separate the data update tasks from the UI thread include using the
{@link android.os.HandlerThread} class, or you may implement your own using {@link android.os.Looper}
and {@link android.os.Handler} classes. See <a href="{@docRoot}guide/components/processes-and-threads.html">
-Processes and Threads</a> for more information.</p> \ No newline at end of file
+Processes and Threads</a> for more information.</p>
+
+<h2 id="applink">Add App Link Information</h2>
+
+<p>Channels can use <em>app links</em> to let users easily launch a related
+activity while they are watching channel content. Channel apps use
+app links to extend user engagement by launching activities that show
+related information or additional content. For example, you can use app links
+to do the following:</p>
+
+<ul>
+<li>Guide the user to discover and purchase related content.</li>
+<li>Provide additional information about currently playing content.</li>
+<li>While viewing episodic content, start viewing the next episode in a
+series.</li>
+<li>Let the user interact with content&mdash;for example, rate or review
+content&mdash;without interrupting content playback.</li>
+</ul>
+
+<p>App links are displayed when the user presses <b>Select</b> to show the
+TV menu while watching channel content.</p>
+
+<img alt="" src="{@docRoot}images/training/tv/tif/app-link.png"
+srcset="{@docRoot}images/training/tv/tif/app-link.png 1x,
+{@docRoot}images/training/tv/tif/app-link-2x.png 2x" id="figure1"/>
+<p class="img-caption"><strong>Figure 1.</strong> An example app link
+displayed on the <b>Channels</b> row while channel content is shown.</p>
+
+<p>When the user selects the app link, the system starts an activity using
+an intent URI specified by the channel app. Channel content continues to play
+while the app link activity is active. The user can return to the channel
+content by pressing <b>Back</b>.</p>
+
+<h3 id="card">Provide App Link Channel Data</h4>
+
+<p>Android TV automatically creates an app link for each channel,
+using information from the channel data. To provide app link information,
+specify the following details in your
+{@link android.media.tv.TvContract.Channels} fields:
+</p>
+
+<ul>
+<li>{@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_COLOR} - The
+accent color of the app link for this channel. For an example accent color,
+see figure 2, callout 3.
+</li>
+<li>{@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_ICON_URI} -
+The URI for the app badge icon of the app link for this channel. For an
+example app badge icon, see figure 2, callout 2.
+</li>
+<li>{@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_INTENT_URI} -
+The intent URI of the app link for this channel. You can create the URI
+using {@link android.content.Intent#toUri(int) toUri(int)} with
+{@link android.content.Intent#URI_INTENT_SCHEME URI_INTENT_SCHEME} and
+convert the URI back to the original intent with
+{@link android.content.Intent#parseUri parseUri()}.
+</li>
+<li>{@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_POSTER_ART_URI}
+- The URI for the poster art used as the background of the app link
+for this channel. For an example poster image, see figure 2, callout 1.</li>
+<li>{@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_TEXT} -
+The descriptive link text of the app link for this channel. For an example
+app link description, see the text in figure 2, callout 3.</li>
+</ul>
+
+<img alt="" src="{@docRoot}images/training/tv/tif/app-link-diagram.png"/>
+<p class="img-caption"><strong>Figure 2.</strong> App link details.</p>
+
+<p>If the channel data doesn't specify app link information, the system
+creates a default app link. The system chooses default details as follows:</p>
+
+<ul>
+<li>For the intent URI
+({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_INTENT_URI}),
+the system uses the {@link android.content.Intent#ACTION_MAIN ACTION_MAIN}
+activity for the {@link android.content.Intent#CATEGORY_LEANBACK_LAUNCHER
+CATEGORY_LEANBACK_LAUNCHER} category, typically defined in the app manifest.
+If this activity is not defined, a non-functioning app link appears&mdash;if
+the user clicks it, nothing happens.</li>
+<li>For the descriptive text
+({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_TEXT}), the system
+uses "Open <var>app-name</var>". If no viable app link intent URI is defined,
+the system uses "No link available".</li>
+<li>For the accent color
+({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_COLOR}),
+the system uses the default app color.</li>
+<li>For the poster image
+({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_POSTER_ART_URI}),
+the system uses the app's home screen banner. If the app doesn't provide a
+banner, the system uses a default TV app image.</li>
+<li>For the badge icon
+({@link android.media.tv.TvContract.Channels#COLUMN_APP_LINK_ICON_URI}), the
+system uses a badge that shows the app name. If the system is also using the
+app banner or default app image for the poster image, no app badge is shown.
+</li>
+</ul>
+
+<p>You specify app link details for your channels in your app's
+setup activity. You can update these app link details at any point, so
+if an app link needs to match channel changes, update app
+link details and call
+{@link android.content.ContentResolver#update(android.net.Uri,
+android.content.ContentValues, java.lang.String, java.lang.String[])
+ContentResolver.update()} as needed. For more details on updating
+channel data, see <a href="#update">Update Channel Data</a>.
+</p>
+
+
+
diff --git a/docs/html/wear/preview/_book.yaml b/docs/html/wear/preview/_book.yaml
index a4acad04afcc..3bea2fde22d1 100644
--- a/docs/html/wear/preview/_book.yaml
+++ b/docs/html/wear/preview/_book.yaml
@@ -18,6 +18,8 @@ toc:
path: /wear/preview/features/ui-nav-actions.html
- title: Bridging for Notifications
path: /wear/preview/features/bridger.html
+ - title: Wrist Gestures
+ path: /wear/preview/features/gestures.html
- title: Get Started
path: /wear/preview/start.html
diff --git a/docs/html/wear/preview/api-overview.jd b/docs/html/wear/preview/api-overview.jd
index 11331a777d62..42336244e4e6 100644
--- a/docs/html/wear/preview/api-overview.jd
+++ b/docs/html/wear/preview/api-overview.jd
@@ -25,6 +25,7 @@ page.image=images/cards/card-n-apis_2x.png
<li><a href="#remote-input">Remote Input</a></li>
<li><a href="#bridging">Bridging Mode</a></li>
<li><a href="#imf">Input Method Framework</a></li>
+ <li><a href="#wrist-gestures">Wrist Gestures</a></li>
</ol>
</li>
@@ -79,12 +80,11 @@ The navigation and action drawers provide users with new ways to interact with a
watch face using the API.
</p>
-<p>For examples of how to use this feature,
+<p>For information about this API,
see <a href="{@docRoot}wear/preview/features/complications.html">
Watch Face Complications</a>.
</p>
-
<h3 id="drawers">Navigation and Action drawers</h3>
<p>Wear 2.0 introduces two new widgets, navigation drawer and action drawer. These
@@ -233,6 +233,24 @@ This allows users to enter text on Wear using the system default IME or third pa
Input Method Framework</a>.
</p>
+<h3 id="wrist-gestures">Wrist Gestures</h3>
+
+<p>
+ Wrist gestures can enable quick, one-handed interactions with your app
+ when use of a touch screen is inconvenient. The following
+ <a href="https://support.google.com/androidwear/answer/6312406">wrist gestures</a>
+ are available for use by apps:
+</p>
+
+<ul>
+ <li>Flick wrist out</li>
+ <li>Flick wrist in</li>
+</ul>
+
+<p>For more information, see
+<a href="{@docRoot}wear/preview/features/gestures.html">
+ Wrist Gestures</a>.
+</p>
<h2 id="stand-alone">Standalone Devices</h2>
diff --git a/docs/html/wear/preview/downloads.jd b/docs/html/wear/preview/downloads.jd
index 86895047d7d2..4bc401bae072 100644
--- a/docs/html/wear/preview/downloads.jd
+++ b/docs/html/wear/preview/downloads.jd
@@ -223,8 +223,8 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement
</p>
<p class="warning">
- <strong>Warning:</strong> Installing a system image on a watch removes all data from the
- watch, so you should back up your data first.
+ <strong>Warning:</strong> Installing a system image on a watch removes all
+ data from the watch, so you should back up your data first.
</p>
<h3 id="preview_system_images">
@@ -233,8 +233,13 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement
<p>
The preview includes system images for testing your app. Based on your
- device, you can download a preview system image from the following tables
- and flash it to the corresponding device.
+ device, you can download a preview system image from one of the
+ following tables and flash it to the corresponding device.
+ </p>
+
+ <p>
+ To restore your device to its original state during the preview,
+ you can flash the appropriate retail system image, below, to the device.
</p>
<h4 id="preview_image_for_lge_watch_urbane_2nd_edition">
@@ -261,9 +266,9 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement
<td>
Preview image for testing
</td>
- <td><a href="#top" onclick="onDownload(this)">nemo-nvd36i-factory-9cdd2ac0.tgz</a><br>
- MD5: b33ba8e59780fbe5c83d8936b108640f<br>
- SHA-1: 9cdd2ac01f2976cafe5a21958298dac159b7a325
+ <td><a href="#top" onclick="onDownload(this)">nemo-nvd83h-factory-48ac950c.tgz</a><br>
+ MD5: dd351884cce9fb5bf1bdec0a8e5f56e3<br>
+ SHA-1: 48ac950c48faef96a7770e3c1acb56d23a28d859
</td>
</tr>
@@ -302,9 +307,9 @@ This is the Android Wear SDK Preview License Agreement (the “License Agreement
<td>
Preview image for testing
</td>
- <td><a href="#top" onclick="onDownload(this)">sturgeon-nvd36i-factory-2cbe5080.tgz</a><br>
- MD5: ccc972cdc33cba778a2f624066ef5713<br>
- SHA-1: 2cbe5080ded060ce43ba65ff27e2290b28981634
+ <td><a href="#top" onclick="onDownload(this)">sturgeon-nvd83h-factory-cb5a11ab.tgz</a><br>
+ MD5: 38c1047992b1d28f6833d9f6c8470cdc<br>
+ SHA-1: cb5a11ab0260ea3ca7da5894e73e41f70357da6b
</td>
</tr>
<tr id="sturgeon-non-preview">
diff --git a/docs/html/wear/preview/features/gestures.jd b/docs/html/wear/preview/features/gestures.jd
new file mode 100644
index 000000000000..7806c4e99836
--- /dev/null
+++ b/docs/html/wear/preview/features/gestures.jd
@@ -0,0 +1,323 @@
+page.title=Wrist Gestures
+meta.keywords="wear-preview"
+page.tags="wear-preview"
+page.image=images/cards/card-n-sdk_2x.png
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+
+ <ul>
+ <li><a href="#using_wlv">Using a WearableListView</a></li>
+ <li><a href="#using_key_events">Using Key Events Directly</a></li>
+ <li><a href="#best_practices">Best Practices</a></li>
+ </ul>
+
+</div>
+</div>
+
+ <p>
+ Wrist gestures can enable quick, one-handed interactions with your app
+ when use of a touch screen is inconvenient. For example, a user can scroll
+ through notifications with one hand while holding a cup of water with the
+ other. Other examples of using wrist gestures when a touch screen would
+ be inconvenient include:
+ </p>
+
+ <ul>
+ <li>In an app for jogging, navigating through vertical screens that show
+ the steps taken, time elapsed, and current pace
+ </li>
+
+ <li>At the airport with luggage, scrolling through flight and gate
+ information
+ </li>
+
+ <li>Scrolling through news articles
+ </li>
+ </ul>
+
+ <p>
+ To review the wrist gestures on your watch, first confirm gestures are
+ turned on by selecting <strong>Settings &gt; Gestures &gt; Wrist Gestures
+ On</strong>. (Wrist gestures are on by default.) Then complete the
+ Gestures tutorial on the watch (<strong>Settings &gt; Gestures &gt;
+ Launch Tutorial</strong>).
+ </p>
+
+ <p>
+ The following gestures from the <a href=
+ "https://support.google.com/androidwear/answer/6312406">Android Wear
+ Help</a> are unavailable to apps:
+ </p>
+
+ <ul>
+ <li>Push wrist down
+ </li>
+
+ <li>Raise wrist up
+ </li>
+
+ <li>Shaking the wrist
+ </li>
+ </ul>
+
+ <p>
+ Wrist gestures can be used in these ways:
+ </p>
+
+ <ul>
+ <li>
+ <a href="#using_wlv">Using a WearableListView</a>, which
+ has predefined gesture actions
+ </li>
+
+ <li>
+ <a href="#using_key_events">Using key events directly</a> to
+ define new user actions
+ </li>
+ </ul>
+
+ <p>
+ Each wrist gesture is mapped to an <code>int</code> constant from the
+ <code><a href=
+ "{@docRoot}reference/android/view/KeyEvent.html">KeyEvent</a></code>
+ class, as shown in the following table:
+ </p>
+
+ <table>
+ <tr>
+ <th>
+ Gesture
+ </th>
+ <th>
+ KeyEvent
+ </th>
+ <th>
+ Description
+ </th>
+ </tr>
+
+ <tr>
+ <td>
+ Flick wrist out
+ </td>
+ <td>
+ <a href=
+ "{@docRoot}reference/android/view/KeyEvent.html#KEYCODE_NAVIGATE_NEXT">
+ KEYCODE_NAVIGATE_NEXT</a>
+ </td>
+ <td>
+ This key code goes to the next item.
+ </td>
+ </tr>
+
+ <tr>
+ <td>
+ Flick wrist in
+ </td>
+ <td>
+ <a href=
+ "{@docRoot}reference/android/view/KeyEvent.html#KEYCODE_NAVIGATE_PREVIOUS">
+ KEYCODE_NAVIGATE_PREVIOUS</a>
+ </td>
+ <td>
+ This key code goes to the previous item.
+ </td>
+ </tr>
+ </table>
+
+ <h2 id="using_wlv">
+ Using a WearableListView
+ </h2>
+
+ <p>
+ A <code><a href=
+ "{@docRoot}reference/android/support/wearable/view/WearableListView.html">
+ WearableListView</a></code> has predefined actions for occurrences of
+ wrist gestures when the View has the focus. For more information, see
+ <a href="#best_practices">Best Practices</a>. For information about using
+ <code>WearableListView</code>, see <a href=
+ "{@docRoot}training/wearables/ui/lists.html">Creating
+ Lists</a>.
+ </p>
+
+ <p>
+ Even if you use a <code>WearableListView</code>, you may want to use
+ constants from the <code><a href=
+ "{@docRoot}reference/android/view/KeyEvent.html">KeyEvent</a></code>
+ class. The predefined actions can be overridden by subclassing the
+ <code>WearableListView</code> and re-implementing the
+ <code>onKeyDown()</code> callback. The behavior can be disabled entirely
+ by using <code>setEnableGestureNavigation(false)</code>. Also see
+ <a href="{@docRoot}training/keyboard-input/commands.html">
+ Handling Keyboard Actions</a>.
+ </p>
+
+ <h2 id="using_key_events">
+ Using Key Events Directly
+ </h2>
+
+ <p>
+ You can use key events outside of a <code><a href=
+ "{@docRoot}reference/android/support/wearable/view/WearableListView.html">
+ WearableListView</a></code> to trigger new actions in response to gesture
+ events. Importantly, these gesture events:
+ </p>
+
+ <ul>
+ <li>Are recognized when a device is in Active mode
+ </li>
+
+ <li>Are delivered in the same way as all key events
+ </li>
+ </ul>
+
+ <p>
+ Specifically, these events are delivered to the top Activity, to the View
+ with keyboard focus. Just as any other key event, a class that relates to
+ user interaction (such as a View or an Activity) that implements
+ <code><a href=
+ "{@docRoot}reference/android/view/KeyEvent.Callback.html">
+ KeyEvent.Callback</a></code> can listen to key events that relate to
+ wrist gestures. The Android framework calls the View or Activity that has
+ the focus with the key events; for gestures, the <code>onKeyDown()</code>
+ method callback is called when gestures occur.
+ </p>
+
+ <p>
+ As an example, an app may override predefined actions in a View or
+ Activity (both implementing <code>KeyEvent.Callback</code>) as follows:
+ </p>
+
+ <pre>
+public final class GesturesActivity extends Activity {
+
+ &#64;Override /* KeyEvent.Callback */
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_NAVIGATE_NEXT:
+ // Do something that advances a user View to the next item in an ordered list.
+ return moveToNextItem();
+ case KeyEvent.KEYCODE_NAVIGATE_PREVIOUS:
+ // Do something that advances a user View to the previous item in an ordered list.
+ return moveToPreviousItem();
+ }
+ // If you did not handle it, let it be handled by the next possible element as deemed by the Activity.
+ return super.onKeyDown(keyCode, event);
+ }
+
+ /** Shows the next item in the custom list. */
+ private boolean moveToNextItem() {
+ boolean handled = false;
+ …
+ // Return true if handled successfully, otherwise return false.
+ return handled;
+ }
+
+ /** Shows the previous item in the custom list. */
+ private boolean moveToPreviousItem() {
+ boolean handled = false;
+ …
+ // Return true if handled successfully, otherwise return false.
+ return handled;
+ }
+}
+</pre>
+
+ <h2 id="best_practices">
+ Best Practices
+ </h2>
+
+ <ul>
+ <li>Review the <code><a href=
+ "{@docRoot}reference/android/view/KeyEvent.html">KeyEvent</a></code>
+ and <code><a href=
+ "{@docRoot}reference/android/view/KeyEvent.Callback.html">
+ KeyEvent.Callback</a></code> pages for the delivery of key events to
+ your View and Activity.
+ </li>
+
+ <li>Keep a consistent directional affordance:
+ <ul>
+ <li>Use "Flick wrist out" for next, "Flick wrist in" for previous
+ </li>
+ </ul>
+ </li>
+
+ <li>Have a touch parallel for a gesture.
+ </li>
+
+ <li>Provide visual feedback.
+ </li>
+
+ <li>Don't use a keycode to implement functionality that would be
+ counter-intuitive to the rest of the system. For example, do not use
+ <code>KEYCODE_NAVIGATE_NEXT</code> to cancel an action or to navigate the
+ left-right axis with flicks.
+ </li>
+
+ <li>Don't intercept the key events on elements that are not part of the
+ user interface, for example the Views that are offscreen or partially
+ covered. This is the same as any other key event.
+ </li>
+
+ <li>Don't reinterpret repeated flick gestures into your own, new gesture.
+ It may conflict with the system's "Shaking the wrist" gesture.
+ </li>
+
+ <li>For a View to receive gesture key events, it must have <a href=
+ "{@docRoot}reference/android/view/View.html#attr_android:focusable">
+ focus</a>; see <a href=
+ "{@docRoot}reference/android/view/View.html#setFocusable(boolean)">
+ View::setFocusable()</a>. Because gestures are treated as key events,
+ they trigger a transition out of "Touch mode" that may do unexpected
+ things. Therefore, since users may alternate between using touch and
+ gestures, the <a href=
+ "{@docRoot}reference/android/view/View.html#setFocusableInTouchMode(boolean)">
+ View::setFocusableInTouchmode()</a> method may be necessary. In some
+ cases, it also may be necessary to use
+ <code>setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS)</code> so
+ that when focus changes after a change to or from "Touch mode," your
+ intended View gets the focus.
+ </li>
+
+ <li>Use <code>requestFocus()</code> and <code>clearFocus()</code>
+ carefully:
+ <ul>
+ <li>When calling <code><a href=
+ "{@docRoot}reference/android/view/View.html#requestFocus()">
+ requestFocus()</a></code>, be sure that the View really should have
+ focus. If the View is offscreen, or is covered by another View,
+ surprises can occur when gestures trigger callbacks.
+ </li>
+
+ <li>The <code><a href=
+ "{@docRoot}reference/android/view/View.html#clearFocus()">
+ clearFocus()</a></code> initiates a focus search to find another
+ suitable View. Depending on the View hierarchy, this search might
+ require non-trivial computation. It can also end up assigning focus
+ to a View you don’t expect to receive focus.
+ </li>
+ </ul>
+ </li>
+
+ <li>Key events are delivered first to the View with focus in the View
+ hierarchy. If the focused View does not handle the event (i.e., returns
+ <code>false</code>), the event is not delivered to the parent View, even
+ if it can receive focus and has a <a href=
+ "{@docRoot}reference/android/text/method/KeyListener.html">
+ KeyListener</a>. Rather, the event is delivered to the current Activity
+ holding the View hierarchy with focus. Thus, it may be necessary to
+ catch all events at the higher level and then pass relevant codes down.
+ Alternatively, you might subclass the Activity and override the
+ <code><a href=
+ "{@docRoot}reference/android/app/Activity.html#dispatchKeyEvent(android.view.KeyEvent)">
+ dispatchKeyEvent(KeyEvent event)</a></code> method to ensure that keys
+ are intercepted when necessary, or are handled when not handled at
+ lower layers.
+ </li>
+ </ul>
diff --git a/docs/html/wear/preview/features/ui-nav-actions.jd b/docs/html/wear/preview/features/ui-nav-actions.jd
index 1ba275fa97c1..fb1426401695 100644
--- a/docs/html/wear/preview/features/ui-nav-actions.jd
+++ b/docs/html/wear/preview/features/ui-nav-actions.jd
@@ -12,7 +12,7 @@ page.image=/wear/preview/images/card_drawer.png
<ol>
<li><a href="#create a drawer">Create a Drawer Layout</a></li>
<li><a href="#initialize">Initialize the Drawer List</a></li>
- <li><a href="#creating">Create a Custom View Drawer</a></li>
+ <li><a href="#creating">Create a Custom Drawer View</a></li>
<li><a href="#listen to events">Listen for Drawer Events</a></li>
<li><a href=#peeking">Peeking Drawers</a></li>
</ol>
@@ -37,8 +37,8 @@ page.image=/wear/preview/images/card_drawer.png
</div>
</div>
<p>As part of the <a href="http://www.google.com/design/spec-wear">Material Design</a>
- for Android Wear, Wear 2.0 adds interactive navigation and action drawers.
- The navigation drawer appears at the top of the screen and lets users jump to
+ for Android Wear, Wear 2.0 adds interactive navigation and action drawers.
+ The navigation drawer appears at the top of the screen and lets users jump to
different views within
the app, similar to the navigation drawer on a phone. The action drawer appears
at the bottom of the screen and provides context-specific actions for the user,
@@ -59,7 +59,8 @@ the opposite direction. </p>
<div class="cols">
<p>This lesson describes how to implement action and navigation drawers in your
-app using the {@code WearableDrawerLayout} APIs.
+app using the {@code WearableDrawerLayout} APIs. For more information, see the
+downloadable <a href="{@docRoot}preview/setup-sdk.html#docs-dl">API reference</a>.
</p>
<h2 id="create a drawer">Create a Drawer Layout</h2>
@@ -99,41 +100,44 @@ To add an action or a navigation drawer, declare your user interface with a
&lt;/android.support.wearable.view.drawer.WearableDrawerLayout>
</pre>
+
<h2 id="initialize">Initialize the Drawer List</h2>
<p>One of the first things you need to do in your activity is to initialize the
drawers list of items. You should implement {@code WearableNavigationDrawerAdapter}
to populate the navigation drawer contents. To populate the action drawer with
-a list of actions, inflate an XML file into the Menu (via MenuInflater).</p>
+a list of actions, inflate an XML file into the Menu (via {@code MenuInflater}).
+</p>
<p>The following code snippet shows how to initialize the contents of your drawers:
</p>
+
<pre>
public class MainActivity extends WearableActivity implements
WearableActionDrawer.OnMenuItemClickListener{
private WearableDrawerLayout mwearableDrawerLayout;
private WearableNavigationDrawer mWearableNavigationDrawer;
private WearableActionDrawer mWearableActionDrawer;
-
+
...
-
+
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
-
+
......
-
-
+
+
// Main Wearable Drawer Layout that wraps all content
mWearableDrawerLayout = (WearableDrawerLayout) findViewById(R.id.drawer_layout);
-
+
// Top Navigation Drawer
mWearableNavigationDrawer = (WearableNavigationDrawer) findViewById(R.id.top_navigation_drawer);
mWearableNavigationDrawer.setAdapter(new YourImplementationNavigationAdapter(this));
// Peeks Navigation drawer on the top.
mWearableDrawerLayout.peekDrawer(Gravity.TOP);
-
+
// Bottom Action Drawer
mWearableActionDrawer = (WearableActionDrawer) findViewById(R.id.bottom_action_drawer);
@@ -149,44 +153,58 @@ WearableActionDrawer.OnMenuItemClickListener{
}
</pre>
-<h2 id="creating">Create a Custom View Drawer</h2>
-
-<p>To use custom views in drawers, add <code>WearableDrawerView</code> to the
-<code>WearableDrawerLayout</code>. To set the contents of the drawer, call <code>
-<a href="https://x20web.corp.google.com/~psoulos/docs/reference/android/support/wearable/view/drawer/WearableDrawerView.html#setDrawerContent(android.view.View)">setDrawerContent(View)</a></code>
- instead of manually adding the view to the hierarchy. You must also specify the
- drawer position with the <code>android:layout_gravity</code> attribute. </p>
-<p> The following example specifies a top drawer:</p>
+
+<h2 id="creating">Create a Custom Drawer View</h2>
+
+<p>To use custom views in drawers, add <code>WearableDrawerView</code> to the
+<code>WearableDrawerLayout</code>. To set the peek view and drawer contents, add
+ them as children of the {@code WearableDrawerView} and specify their IDs in the
+ {@code peek_view} and {@code drawer_content} attributes respectively. You must
+ also specify the drawer position with the {@code android:layout_gravity}
+ attribute. </p>
+
+<p> The following example specifies a top drawer with peek view and drawer
+contents:</p>
+
<pre>
-&lt;android.support.wearable.view.drawer.WearableDrawerLayout&gt;
- &lt;FrameLayout
- android:id=â€@+id/content†/&gt;
-
- &lt;WearableDrawerView
- android:layout_width=â€match_parentâ€
- andndroid:layout_height=â€match_parentâ€
- android:layout_gravity=â€topâ€&gt;
- &lt;FrameLayout
- android:id=â€@+id/top_drawer_content†/&gt;
- &lt;/WearableDrawerView&gt;
-&lt;/android.support.wearable.view.drawer.WearableDrawerView&gt;
+ &lt;android.support.wearable.view.drawer.WearableDrawerView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="top"
+ android:background="@color/red"
+ app:drawer_content="@+id/drawer_content"
+ app:peek_view="@+id/peek_view">
+ &lt;FrameLayout
+ android:id="@id/drawer_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ &lt;!-- Drawer content goes here. -->
+ &lt;/FrameLayout>
+ &lt;LinearLayout
+ android:id="@id/peek_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:orientation="horizontal">
+ &lt;!-- Peek view content goes here. -->
+ &lt;LinearLayout>
+ &lt;/android.support.wearable.view.drawer.WearableDrawerView>
</pre>
<h2 id="listen to events">Listen for Drawer Events</h2>
-<p>To listen for drawer events, call {@code setDrawerStateCallback()}on your
+<p>To listen for drawer events, call {@code setDrawerStateCallback()} on your
{@code WearableDrawerLayout} and pass it an implementation of
{@code WearableDrawerLayout.DrawerStateCallback}. This interface provides callbacks
for drawer events such as <code>onDrawerOpened()</code>,
<code>onDrawerClosed(),</code> and <code>onDrawerStatechanged()</code>.</p>
<h2 id="peeking">Peeking Drawers</h2>
-<p>To set the drawers to temporarily appear, call <code>peekDrawer()</code> on
+<p>To set the drawers to temporarily appear, call <code>peekDrawer()</code> on
your {@code WearableDrawerLayout} and pass it the {@code Gravity} of the drawer.
This feature is especially useful because it allows immediate access to the
- alternate drawer views or actions associated with it. </p>
+ alternate drawer views or actions associated with it: </p>
+
+<pre>{@code mWearableDrawerLayout.peekDrawer(Gravity.BOTTOM);}</pre>
-<pre>{@code mWearableDrawerLayout.peekDrawer</code>(<code>Gravity.BOTTOM);}</pre>
-<p>You can also call {@code setPeekContent()} on your drawer to display a custom
- view when the drawer is peeking.</p>
diff --git a/docs/html/wear/preview/program.jd b/docs/html/wear/preview/program.jd
index a130663f6f91..e2bf92f80c6c 100644
--- a/docs/html/wear/preview/program.jd
+++ b/docs/html/wear/preview/program.jd
@@ -79,6 +79,11 @@ page.image=images/cards/card-n-sdk_2x.png
</div>
<div class="col-4of12">
+ <h5>
+ </h5>
+
+ <p>
+ </p>
</div>
</div>
</div>
@@ -90,7 +95,7 @@ page.image=images/cards/card-n-sdk_2x.png
<p>
The Android Wear 2.0 Developer Preview runs from 18 May 2016 until the
- final Android Wear public release to OEMs, planned for Q4 2016.
+ final Android Wear public release to OEMs.
</p>
<p>
@@ -136,7 +141,7 @@ page.image=images/cards/card-n-sdk_2x.png
</p>
<p>
- At milestones 4 and 5 you'll have access to the final Android Wear 2.0
+ At milestone 4, you'll have access to the final Android Wear 2.0
APIs and SDK to develop with, as well as near-final system images to test
system behaviors and features. Android Wear 2.0 will use the Android N
API level at this time. You can begin final compatibility testing of your
@@ -196,9 +201,9 @@ page.image=images/cards/card-n-sdk_2x.png
</h3>
<p>
- You can download these hardware system images at <a href=
+ You can download these hardware system images from the <a href=
"{@docRoot}wear/preview/downloads.html">Download and Test with a
- Device</a>:
+ Device</a> page:
</p>
<ul>
@@ -210,7 +215,15 @@ page.image=images/cards/card-n-sdk_2x.png
</ul>
<p>
- Please keep in mind that the Developer Preview system images
+ To restore your device to its
+ original state during the preview, you can flash the
+ appropriate retail system image from
+ the <a href="{@docRoot}wear/preview/downloads.html">Download and
+ Test with a Device</a> page.
+ </p>
+
+ <p>
+ Please keep in mind that the preview system images
are for app developers only, and for compatibility testing and
early development only, and are not ready for day-to-day use.
</p>
diff --git a/docs/html/wear/preview/start.jd b/docs/html/wear/preview/start.jd
index 65d4b56e164d..8fccdc82cd5a 100644
--- a/docs/html/wear/preview/start.jd
+++ b/docs/html/wear/preview/start.jd
@@ -107,10 +107,10 @@ page.image=images/cards/card-n-sdk_2x.png
<tr>
<td>
- <a href="http://storage.googleapis.com/androiddevelopers/shareables/wear-preview/wearable-support-preview-1-docs.zip">wearable-support-preview-1-docs.zip</a>
+ <a href="http://storage.googleapis.com/androiddevelopers/shareables/wear-preview/wearable-support-preview-2-docs.zip">wearable-support-preview-2-docs.zip</a>
</td>
- <td>MD5: 02f9dc7714c00076b323c9081655c3b2<br>
- SHA-1: 075f3821ee9b66a919a0e8086f79c12bc9576fb2
+ <td>MD5: afb770c9c5c0431bbcbdde186f1eae06<br>
+ SHA-1: 81d681e61cee01f222ea82e83297d23c4e55b8f3
</td>
</tr>
</table>
@@ -146,16 +146,26 @@ page.image=images/cards/card-n-sdk_2x.png
plugin.
</li>
- <li>In the <code>build.gradle</code> file for the Wear module, in the
- <code>dependencies</code> section, update the existing reference to the
+ <li>In the <code>build.gradle</code> file for the Wear module:
+ <ul>
+ <li>In the <code>android</code> section, update the
+ <code>compileSdkVersion</code> to 24.
+ </li>
+
+ <li>In the <code>android</code> section, update the
+ <code>targetSdkVersion</code> to 24.
+ </li>
+
+ <li>In the <code>dependencies</code> section, update
+ the existing reference to the
Wearable Support Library (for example, <code>compile
'com.google.android.support:wearable:1.4.0'</code>) by changing it to the
following, which requires that your the Google Repository <a href=
"#install_android_studio_and_the_latest_packages">is the latest
version</a>:
- <pre>
-compile 'com.google.android.support:wearable:2.0.0-alpha1'
- </pre>
+ <code>compile 'com.google.android.support:wearable:2.0.0-alpha2'</code>
+ </li>
+ </ul>
</li>
<li>See the following page for setting up a watch or emulator with a
@@ -190,13 +200,24 @@ compile 'com.google.android.support:wearable:2.0.0-alpha1'
wizard.
</li>
- <li>In the <code>build.gradle</code> file for the Wear module, in the
- <code>dependencies</code> section, update the existing reference to the
- Wearable Support Library (perhaps <code>compile
- 'com.google.android.support:wearable:1.4.0'</code>) to:
- <pre>
-compile 'com.google.android.support:wearable:2.0.0-alpha1'
- </pre>
+ <li>In the <code>build.gradle</code> file for the Wear module:
+ <ul>
+ <li>In the <code>android</code> section, update the
+ <code>compileSdkVersion</code> to 24.
+ </li>
+ <li>In the <code>android</code> section, update the
+ <code>targetSdkVersion</code> to 24.
+ </li>
+ <li>In the <code>dependencies</code> section, update
+ the existing reference to the
+ Wearable Support Library (for example, <code>compile
+ 'com.google.android.support:wearable:1.4.0'</code>) by changing it to the
+ following, which requires that your the Google Repository <a href=
+ "#install_android_studio_and_the_latest_packages">is the latest
+ version</a>:
+ <code>compile 'com.google.android.support:wearable:2.0.0-alpha2'</code>
+ </li>
+ </ul>
</li>
<li>See the following page for setting up a watch or emulator with a
diff --git a/docs/html/wear/preview/support.jd b/docs/html/wear/preview/support.jd
index d03edf31aacd..78b4e4b854ac 100644
--- a/docs/html/wear/preview/support.jd
+++ b/docs/html/wear/preview/support.jd
@@ -16,48 +16,277 @@ page.tags="preview", "developer preview"
Wear Developer Google+ community</a>.
</p>
-<h2 id="dp">Developer Preview 1</h2>
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>In this document</h2>
+
+<ul>
+ <li><a href="#general">General Advisories</a></li>
+ <li><a href="#deprecations">Deprecations</a></li>
+ <li><a href="#dp2">Developer Preview 2</a></li>
+ <li><a href="#dp1">Developer Preview 1</a></li>
+</ul>
+
+</div>
+</div>
+
+<h2 id="general">General Advisories</h2>
+
+<p>
+ The developer preview is for <strong>app developers and other early
+ adopters</strong> and is available for daily use, development, or
+ compatibility testing. Please be aware of these general notes about the
+ release:
+</p>
+
+<ul>
+ <li>The developer preview may have various <strong>stability issues</strong> on
+ supported devices. Users may encounter system instability, such as kernel
+ panics and crashes.
+ </li>
+ <li>Some apps <strong>may not function as expected</strong> on the new
+ platform version. This includes Google’s apps and other apps.
+ </li>
+</ul>
+
+<h2 id="deprecations">Deprecations</h2>
+
+<p>The following fields are deprecated in the preview:</p>
+
+<ul>
+ <li>The <code>Notification.WearableExtender#setCustomSizePreset(int)</code>
+ method no longer accepts <code>SIZE_FULL_SCREEN</code> and this value is now
+ undefined.
+ </li>
+ <li>The <code>Notification.WearableExtender#setContentIcon(int)</code> method
+ is deprecated.
+ </li>
+</ul>
+
+<h2 id="dp2">Developer Preview 2</h2>
<div class="wrap">
<div class="cols">
<div class="col-6of12">
- <p><em>Date: May 2016<br />
- Builds: Wearable Support 2.0.0-alpha1, NVD36I <br />
+ <p><em>Date: July 2016<br />
+ Builds: Wearable Support 2.0.0-alpha2, NVD83H<br/>
Emulator support: x86 & ARM (32-bit)<br/>
</em></p>
</div>
</div>
</div>
+<h3 id="new-in-fdp2">
+ <strong>New in Preview 2</strong>
+</h3>
-<h3 id="general_advisories">General advisories</h3>
+<h4 id="platform-version-24">
+ Platform API Version
+</h4>
<p>
- This Developer Preview release is for app developers only and is designed for
- use in compatibility testing and early development only.
+ The Android Platform API version is incremented to 24 to match Android Nougat.
+ You can update the following in your Android Wear 2.0 Preview project
+ to <strong>24</strong>:
</p>
-<h4 id="deprecations">Deprecations</h4>
+<ul>
+ <li><code>compileSdkVersion</code></li>
+ <li><code>targetSdkVersion</code></li>
+</ul>
+<h4 id="wearable-drawers">
+ Wearable drawers
+</h4>
-<p>The following fields are deprecated in the Preview:</p>
+<p>
+ The following are feature additions for <a href=
+ "{@docRoot}wear/preview/features/ui-nav-actions.html">
+ wearable drawers</a>:
+</p>
<ul>
- <li>The <code>Notification.WearableExtender#setCustomSizePreset(int)</code>
- method no longer accepts <code>SIZE_FULL_SCREEN</code> and this value is now
- undefined.
+ <li>Drawer peeking is now supported in the <code>onCreate()</code> method
+ of your app's activity.
</li>
- <li>The <code>Notification.WearableExtender#setContentIcon(int)</code> method
- is deprecated.
+ <li>The automatic drawer peeking behavior is
+ inverted. Now the bottom drawer peeks when the user scrolls down the view
+ and top drawer peeks when the user scrolls to the top of the view
+ (previously scrolling down did not show peek view).
+ </li>
+
+ <li>Two new attributes, <code>peek_view</code> and
+ <code>drawer_content</code>, are added to
+ <code>WearableDrawerView</code> to specify contents of custom drawers and
+ peek view in your XML layout (previously, custom drawer contents were
+ specified only through Java code).
+ </li>
+
+ <li>The Navigation drawer now displays page indicator dots.
+ </li>
+
+ <li>Peek views now close automatically after one second.
+ </li>
+
+ <li>The <code>WearableNavigationDrawer</code> now automatically closes
+ after five seconds or when an item is tapped.
+ </li>
+
+ <li>There is improved drawer handling (size and margins) for devices with chins:
+ <ul>
+ <li>Size: The bottom drawer is slightly smaller when there is a
+ chin.
+ </li>
+ <li>Margins: <code>WearableDrawerLayout</code> sets its bottom margin
+ size equal to the size of the chin, so that the bottom drawer is
+ fully visible.
+ </li>
+ </ul>
+ <li>The navigation drawer contents are now updated when
+ <code><a href="{@docRoot}reference/android/widget/ArrayAdapter.html#notifyDataSetChanged()">
+ notifyDataSetChanged</a></code> is called on the adapter.
</li>
+
+ <li>In your <code>WearableActionDrawer</code>, when there is only one
+ action, its icon is shown in the peek view and the action is executed
+ when the peek view is tapped.
+ </li>
+
+ <li>When the peek view of your <code>WearableActionDrawer</code> has
+ more than one action, both the first action and the overflow icons are
+ shown.
+ </li>
</ul>
-<h3 id="known_issues">Known Issues</h3>
+<h4 id="gestures">
+ Wrist gestures
+</h4>
+<p>
+ Wrist gestures can enable quick, one-handed interactions with your app.
+ For example, a user can
+ scroll through notifications with one hand while holding a cup of water
+ with the other. For more information, see <a href=
+ "{@docRoot}wear/preview/features/gestures.html">
+ Wrist Gestures</a>.
+</p>
-<h4 id="notifications">Notifications</h4>
+<h3 id="known-issues-2">
+ <strong>Known Issues</strong>
+</h3>
+
+<h4 id="notifications-2">
+ Notifications
+</h4>
+
+<ul>
+ <li>This preview release does not include support for notification
+ groups.
+ </li>
+
+ <li>The user interface for the action drawer can sometimes have a
+ transparent background.
+ </li>
+
+ <li>The system does not generate Smart Reply responses even if
+ <code>setAllowGeneratedReplies(true)</code> is set.
+ </li>
+</ul>
+
+<h4 id="complications-2">
+ Complications
+</h4>
+
+<ul>
+ <li>When tapping on the music complication on a watch face, Play Music
+ crashes if the Apps launcher provider is used.
+ </li>
+</ul>
+
+<h4 id="system-user-interface-2">
+ System User Interface
+</h4>
+
+<ul>
+ <li>Pressing the hardware button in ambient mode triggers active mode
+ with the app launcher instead of active mode only.
+ </li>
+
+ <li>Double pressing the power hardware button while on the launcher
+ causes the watch screen to turn black.
+ </li>
+
+ <li>Dismissing multiple notifications can cause app to forcibly close.
+ </li>
+
+ <li>Turning screen lock to off (Enable and disable) functionality is not
+ reliable.
+ </li>
+
+ <li>The "Ok Google" detection and voice transcription may not work
+ reliably. Additionally, Search does not retrieve results.
+ </li>
+
+ <li>Tapping Google keyboard English (United States) displays a "Settings
+ under construction" message.
+ </li>
+
+ <li>First calendar event notification must be dismissed in order to show
+ the rest of the event card.
+ </li>
+
+ <li>Unable to turn off the Wi-Fi on a wearable.
+ </li>
+</ul>
+
+<h4 id="companion-app-2">
+ Companion App
+</h4>
+
+<ul>
+ <li>An actions card is shown in the Android Wear companion app, even
+ though there are no actions.
+ </li>
+</ul>
+<h4 id="devices-2">
+ Devices
+</h4>
+
+<ul>
+ <li>On the Huawei Watch, selecting the language, followed by multiple
+ acknowledgement dialogues results in a black screen.
+ </li>
+
+ <li>On the LG Watch Urbane 2nd Edition, when answering a call from the watch, the
+ watch does not provide audio from the caller.
+ </li>
+
+ <li>On the LG Watch Urbane 2nd Edition,
+ please do the following to prevent battery drain:
+ Turn on Airplane mode (to disable the cellular radio) and then
+ turn on Bluetooth.
+ </li>
+</ul>
+
+<h2 id="dp1">Developer Preview 1</h2>
+
+<div class="wrap">
+ <div class="cols">
+ <div class="col-6of12">
+ <p><em>Date: May 2016<br />
+ Builds: Wearable Support 2.0.0-alpha1, NVD36I <br />
+ Emulator support: x86 & ARM (32-bit)<br/>
+ </em></p>
+ </div>
+ </div>
+</div>
+
+<h3 id="known_issues">Known Issues</h3>
+
+<h4 id="notifications">Notifications</h4>
<ul>
<li>This preview release does not include support for notification groups,
@@ -74,18 +303,17 @@ page.tags="preview", "developer preview"
</li>
</ul>
-
<h4 id="complications">Complications</h4>
<ul>
- <li>Battery information is not synchronized between watch face and drop down
- quick menu.
+ <li>Battery information is not synchronized between the
+ watch face and the drop-down Quick menu.
</li>
- <li>Play music crashes when tapping on music complication in watch face.
+ <li>When tapping on the music complication on a watch face, Play Music
+ crashes if the Apps launcher provider is used.
</li>
</ul>
-
<h4 id="system_user_interface">System User Interface</h4>
<ul>
@@ -114,26 +342,24 @@ page.tags="preview", "developer preview"
</li>
</ul>
-
<h4 id="companion_app">Companion App</h4>
<ul>
- <li>'More actions' via Companion app shows a blank screen on phone running
- nyc-release and watch running feldspar-release.
- </li>
- <li>Select watch face on companion wear app will not change watch face on
- wearable.
- </li>
+ <li>Selecting a watch face on the companion app will not change the watch face on
+ wearable.</li>
+ <li>An actions card is shown in the Android Wear companion app, even
+ though there are no actions.
+ </li>
</ul>
-
<h4 id="devices">Devices</h4>
<ul>
<li>On the Huawei Watch, selecting the language, followed by multiple
acknowledgement dialogues results in a black screen.
</li>
- <li>On the LG Watch Urbane LTE, when answering call from the watch, the watch
+ <li>On the LG Watch Urbane 2nd Edition, when
+ answering a call from the watch, the watch
does not provide audio from the caller.
</li>
</ul>
diff --git a/docs/html/work/managed-configurations.jd b/docs/html/work/managed-configurations.jd
index dc3ef0da2ab2..91c0637c2edb 100644
--- a/docs/html/work/managed-configurations.jd
+++ b/docs/html/work/managed-configurations.jd
@@ -149,9 +149,9 @@ enterprise administrator to:</p>
&lt;restriction
android:key="downloadOnCellular"
- android:title="App is allowed to download data via cellular"
+ android:title="@string/download_on_cell_title"
android:restrictionType="bool"
- android:description="If 'false', app can only download data via Wi-Fi"
+ android:description="@string/download_on_cell_description"
android:defaultValue="true" /&gt;
&lt;/restrictions&gt;
diff --git a/docs/image_sources/training/tv/tif/app-link-diagram.graffle.zip b/docs/image_sources/training/tv/tif/app-link-diagram.graffle.zip
new file mode 100644
index 000000000000..8b6779d68c1c
--- /dev/null
+++ b/docs/image_sources/training/tv/tif/app-link-diagram.graffle.zip
Binary files differ
diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h
index 49021bc82825..f9274e173536 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.h
+++ b/libs/hwui/PropertyValuesAnimatorSet.h
@@ -60,7 +60,7 @@ public:
virtual uint32_t dirtyMask();
bool isInfinite() { return mIsInfinite; }
void setVectorDrawable(VectorDrawableRoot* vd) { mVectorDrawable = vd; }
- VectorDrawableRoot* getVectorDrawable() const { return mVectorDrawable; }
+ VectorDrawableRoot* getVectorDrawable() const { return mVectorDrawable.get(); }
AnimationListener* getOneShotListener() { return mOneShotListener.get(); }
void clearOneShotListener() { mOneShotListener = nullptr; }
uint32_t getRequestId() const { return mRequestId; }
@@ -78,7 +78,7 @@ private:
std::vector< std::unique_ptr<PropertyAnimator> > mAnimators;
float mLastFraction = 0.0f;
bool mInitialized = false;
- VectorDrawableRoot* mVectorDrawable = nullptr;
+ sp<VectorDrawableRoot> mVectorDrawable;
bool mIsInfinite = false;
// This request id gets incremented (on UI thread only) when a new request to modfiy the
// lifecycle of an animation happens, namely when start/end/reset/reverse is called.
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index f8797bf63442..6facf20b025c 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -301,7 +301,10 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
LayerType layerType = properties().effectiveLayerType();
// If we are not a layer OR we cannot be rendered (eg, view was detached)
// we need to destroy any Layers we may have had previously
- if (CC_LIKELY(layerType != LayerType::RenderLayer) || CC_UNLIKELY(!isRenderable())) {
+ if (CC_LIKELY(layerType != LayerType::RenderLayer)
+ || CC_UNLIKELY(!isRenderable())
+ || CC_UNLIKELY(properties().getWidth() == 0)
+ || CC_UNLIKELY(properties().getHeight() == 0)) {
if (CC_UNLIKELY(mLayer)) {
destroyLayer(mLayer);
mLayer = nullptr;
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 696cc29de3a4..395279806adb 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -611,9 +611,7 @@ public:
bool fitsOnLayer() const {
const DeviceInfo* deviceInfo = DeviceInfo::get();
return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize()
- && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize()
- && mPrimitiveFields.mWidth > 0
- && mPrimitiveFields.mHeight > 0;
+ && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize();
}
bool promotedToLayer() const {
diff --git a/libs/hwui/tests/unit/RenderPropertiesTests.cpp b/libs/hwui/tests/unit/RenderPropertiesTests.cpp
index 90010983f154..85655fc2728a 100644
--- a/libs/hwui/tests/unit/RenderPropertiesTests.cpp
+++ b/libs/hwui/tests/unit/RenderPropertiesTests.cpp
@@ -42,7 +42,7 @@ TEST(RenderProperties, layerValidity) {
props.setLeftTopRightBottom(0, 0, maxTextureSize + 1, maxTextureSize + 1);
ASSERT_FALSE(props.fitsOnLayer());
- // Too small - can't have 0 dimen layer
+ // Too small, but still 'fits'. Not fitting is an error case, so don't report empty as such.
props.setLeftTopRightBottom(0, 0, 100, 0);
- ASSERT_FALSE(props.fitsOnLayer());
+ ASSERT_TRUE(props.fitsOnLayer());
}
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index 315169472a7c..7db04663c83b 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -98,13 +98,13 @@ public final class GnssMeasurementsEvent implements Parcelable {
throw new InvalidParameterException("Parameter 'clock' must not be null.");
}
if (measurements == null || measurements.length == 0) {
- throw new InvalidParameterException(
- "Parameter 'measurements' must not be null or empty.");
+ mReadOnlyMeasurements = Collections.emptyList();
+ } else {
+ Collection<GnssMeasurement> measurementCollection = Arrays.asList(measurements);
+ mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection);
}
mClock = clock;
- Collection<GnssMeasurement> measurementCollection = Arrays.asList(measurements);
- mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection);
}
/**
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index a4484e757ac5..81cc93da2e6f 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -263,6 +263,9 @@ public final class AudioFormat implements Parcelable {
* on some platforms when converting to short internally.
*/
public static final int ENCODING_IEC61937 = 13;
+ /** Audio data format: DOLBY TRUEHD compressed
+ **/
+ public static final int ENCODING_DOLBY_TRUEHD = 14;
/** Invalid audio channel configuration */
/** @deprecated Use {@link #CHANNEL_INVALID} instead. */
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 4bdc70e37621..f19a2624457e 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2744,6 +2744,7 @@ public class AudioManager {
* to be notified.
* Use {@link AudioManager#getActiveRecordingConfigurations()} to query the current
* configuration.
+ * @see AudioRecordingConfiguration
*/
public static abstract class AudioRecordingCallback {
/**
@@ -2850,6 +2851,7 @@ public class AudioManager {
* Returns the current active audio recording configurations of the device.
* @return a non-null list of recording configurations. An empty list indicates there is
* no recording active when queried.
+ * @see AudioRecordingConfiguration
*/
public @NonNull List<AudioRecordingConfiguration> getActiveRecordingConfigurations() {
final IAudioService service = getService();
diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java
index 593516639e29..354339c545a4 100644
--- a/media/java/android/media/AudioRecordingConfiguration.java
+++ b/media/java/android/media/AudioRecordingConfiguration.java
@@ -28,8 +28,18 @@ import java.util.Objects;
/**
* The AudioRecordingConfiguration class collects the information describing an audio recording
- * session. This information is returned through the
- * {@link AudioManager#getActiveRecordingConfigurations()} method.
+ * session.
+ * <p>Direct polling (see {@link AudioManager#getActiveRecordingConfigurations()}) or callback
+ * (see {@link AudioManager#registerAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback, android.os.Handler)}
+ * methods are ways to receive information about the current recording configuration of the device.
+ * <p>An audio recording configuration contains information about the recording format as used by
+ * the application ({@link #getClientFormat()}, as well as the recording format actually used by
+ * the device ({@link #getFormat()}). The two recording formats may, for instance, be at different
+ * sampling rates due to hardware limitations (e.g. application recording at 44.1kHz whereas the
+ * device always records at 48kHz, and the Android framework resamples for the application).
+ * <p>The configuration also contains the use case for which audio is recorded
+ * ({@link #getClientAudioSource()}), enabling the ability to distinguish between different
+ * activities such as ongoing voice recognition or camcorder recording.
*
*/
public final class AudioRecordingConfiguration implements Parcelable {
@@ -198,4 +208,4 @@ public final class AudioRecordingConfiguration implements Parcelable {
&& (mClientFormat.equals(that.mClientFormat))
&& (mDeviceFormat.equals(that.mDeviceFormat)));
}
-} \ No newline at end of file
+}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 8d4a1510715a..31c7a3249542 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -3498,7 +3498,7 @@ public class MediaPlayer extends PlayerBase
* @param extra an extra code, specific to the info. Typically
* implementation dependent.
* @return True if the method handled the info, false if it didn't.
- * Returning false, or not having an OnErrorListener at all, will
+ * Returning false, or not having an OnInfoListener at all, will
* cause the info to be discarded.
*/
boolean onInfo(MediaPlayer mp, int what, int extra);
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 0f7dc9a819c7..b262d97cfb8e 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -181,10 +181,15 @@ public abstract class PlayerBase {
* @return
*/
boolean isRestricted_sync() {
+ // check app ops
+ if (mHasAppOpsPlayAudio) {
+ return false;
+ }
+ // check bypass flag
if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
return false;
}
- return !mHasAppOpsPlayAudio;
+ return true;
}
// Abstract methods a subclass needs to implement
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 5ede1d5f7c91..9fafda48d652 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -505,27 +505,31 @@ public class SoundPool {
}
private boolean isRestricted() {
- IAudioService service = getService();
- boolean cameraSoundForced = false;
-
- try {
- cameraSoundForced = service.isCameraSoundForced();
- } catch (RemoteException e) {
- Log.e(TAG, "Cannot access AudioService in isRestricted()");
- }
-
- if (cameraSoundForced &&
- ((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0)
-// FIXME: should also check usage when set properly by camera app
-// && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
- ) {
+ // check app ops
+ if (mHasAppOpsPlayAudio) {
return false;
}
-
+ // check bypass flag
if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
return false;
}
- return !mHasAppOpsPlayAudio;
+ // check force audibility flag and camera restriction
+ if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0) {
+// FIXME: should also check usage when set properly by camera app
+// && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ boolean cameraSoundForced = false;
+ try {
+ cameraSoundForced = getService().isCameraSoundForced();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Cannot access AudioService in isRestricted()");
+ } catch (NullPointerException e) {
+ Log.e(TAG, "Null AudioService in isRestricted()");
+ }
+ if (cameraSoundForced) {
+ return false;
+ }
+ }
+ return true;
}
private void updateAppOpsPlayAudio() {
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index df0961bd17d4..d5296ae42031 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -15,6 +15,7 @@
*/
package android.media.soundtrigger;
+import static android.hardware.soundtrigger.SoundTrigger.STATUS_OK;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -243,27 +244,29 @@ public final class SoundTriggerDetector {
boolean allowMultipleTriggers =
(recognitionFlags & RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS) != 0;
+ int status = STATUS_OK;
try {
- mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId),
+ status = mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId),
mRecognitionCallback, new RecognitionConfig(captureTriggerAudio,
allowMultipleTriggers, null, null));
} catch (RemoteException e) {
return false;
}
- return true;
+ return status == STATUS_OK;
}
/**
* Stops recognition for the associated model.
*/
public boolean stopRecognition() {
+ int status = STATUS_OK;
try {
- mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId),
+ status = mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId),
mRecognitionCallback);
} catch (RemoteException e) {
return false;
}
- return true;
+ return status == STATUS_OK;
}
/**
diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp
index d07942b5fd89..2ab7e39fad17 100644
--- a/media/jni/android_media_MediaDataSource.cpp
+++ b/media/jni/android_media_MediaDataSource.cpp
@@ -26,6 +26,7 @@
#include "JNIHelp.h"
#include <binder/MemoryDealer.h>
+#include <drm/drm_framework_common.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/ScopedLocalRef.h>
@@ -159,4 +160,8 @@ String8 JMediaDataSource::toString() {
return String8::format("JMediaDataSource(pid %d, uid %d)", getpid(), getuid());
}
+sp<DecryptHandle> JMediaDataSource::DrmInitialization(const char * /* mime */) {
+ return NULL;
+}
+
} // namespace android
diff --git a/media/jni/android_media_MediaDataSource.h b/media/jni/android_media_MediaDataSource.h
index 378baf433fed..39405d2db579 100644
--- a/media/jni/android_media_MediaDataSource.h
+++ b/media/jni/android_media_MediaDataSource.h
@@ -47,6 +47,7 @@ public:
virtual void close();
virtual uint32_t getFlags();
virtual String8 toString();
+ virtual sp<DecryptHandle> DrmInitialization(const char *mime);
private:
// Protect all member variables with mLock because this object will be
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
index d830c61f30e7..a37590d2e0a6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
@@ -22,6 +22,7 @@ import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
+import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -91,6 +92,14 @@ public class SaveFragment extends Fragment {
return false;
}
+ // Returning false in this method will bubble the event up to
+ // {@link BaseActivity#onKeyDown}. In order to prevent backspace popping
+ // documents once the textView is empty, we are going to trap it here.
+ if (keyCode == KeyEvent.KEYCODE_DEL
+ && TextUtils.isEmpty(mDisplayName.getText())) {
+ return true;
+ }
+
if (keyCode == KeyEvent.KEYCODE_ENTER && mSave.isEnabled()) {
performSave();
return true;
diff --git a/packages/EasterEgg/src/com/android/egg/neko/Cat.java b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
index 8c44fd6b1767..f74a2293050a 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/Cat.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
@@ -312,6 +312,10 @@ public class Cat extends Drawable {
logCatAction(context, "egg_neko_add");
}
+ public void logRename(Context context) {
+ logCatAction(context, "egg_neko_rename");
+ }
+
public void logRemove(Context context) {
logCatAction(context, "egg_neko_remove");
}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
index feada7f9dc37..86f813e0647a 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
@@ -138,7 +138,7 @@ public class NekoLand extends Activity implements PrefsListener {
.setPositiveButton(android.R.string.ok, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- MetricsLogger.count(context, "egg_neko_rename_cat", 1);
+ cat.logRename(context);
cat.setName(text.getText().toString().trim());
mPrefs.addCat(cat);
}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 62f33bf490a8..a3070bddd0f8 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -492,23 +492,26 @@ public class ExternalStorageProvider extends DocumentsProvider {
throw new IllegalStateException("Failed to delete " + file);
}
- final ContentResolver resolver = getContext().getContentResolver();
- final Uri externalUri = MediaStore.Files.getContentUri("external");
+ final File visibleFile = getFileForDocId(docId, true);
+ if (visibleFile != null) {
+ final ContentResolver resolver = getContext().getContentResolver();
+ final Uri externalUri = MediaStore.Files.getContentUri("external");
+
+ // Remove media store entries for any files inside this directory, using
+ // path prefix match. Logic borrowed from MtpDatabase.
+ if (isDirectory) {
+ final String path = visibleFile.getAbsolutePath() + "/";
+ resolver.delete(externalUri,
+ "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
+ new String[] { path + "%", Integer.toString(path.length()), path });
+ }
- // Remove media store entries for any files inside this directory, using
- // path prefix match. Logic borrowed from MtpDatabase.
- if (isDirectory) {
- final String path = file.getAbsolutePath() + "/";
+ // Remove media store entry for this exact file.
+ final String path = visibleFile.getAbsolutePath();
resolver.delete(externalUri,
- "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
- new String[] { path + "%", Integer.toString(path.length()), path });
+ "_data LIKE ?1 AND lower(_data)=lower(?2)",
+ new String[] { path, path });
}
-
- // Remove media store entry for this exact file.
- final String path = file.getAbsolutePath();
- resolver.delete(externalUri,
- "_data LIKE ?1 AND lower(_data)=lower(?2)",
- new String[] { path, path });
}
@Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 60eaad2699ee..038e08d758eb 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -137,12 +137,21 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
entry,
userId,
new LockPatternChecker.OnCheckCallback() {
+
+ @Override
+ public void onEarlyMatched() {
+ onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */,
+ true /* isValidPassword */);
+ }
+
@Override
public void onChecked(boolean matched, int timeoutMs) {
setPasswordEntryInputEnabled(true);
mPendingLockCheck = null;
- onPasswordChecked(userId, matched, timeoutMs,
- true /* isValidPassword */);
+ if (!matched) {
+ onPasswordChecked(userId, false /* matched */, timeoutMs,
+ true /* isValidPassword */);
+ }
}
});
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
index 7ea767c004fb..4f5152aca6f3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
@@ -36,6 +36,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
private final AppearAnimationUtils mAppearAnimationUtils;
private final DisappearAnimationUtils mDisappearAnimationUtils;
+ private final DisappearAnimationUtils mDisappearAnimationUtilsLocked;
private ViewGroup mContainer;
private ViewGroup mRow0;
private ViewGroup mRow1;
@@ -44,6 +45,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
private View mDivider;
private int mDisappearYTranslation;
private View[][] mViews;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
public KeyguardPINView(Context context) {
this(context, null);
@@ -56,8 +58,14 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
125, 0.6f /* translationScale */,
0.45f /* delayScale */, AnimationUtils.loadInterpolator(
mContext, android.R.interpolator.fast_out_linear_in));
+ mDisappearAnimationUtilsLocked = new DisappearAnimationUtils(context,
+ (long) (125 * KeyguardPatternView.DISAPPEAR_MULTIPLIER_LOCKED),
+ 0.6f /* translationScale */,
+ 0.45f /* delayScale */, AnimationUtils.loadInterpolator(
+ mContext, android.R.interpolator.fast_out_linear_in));
mDisappearYTranslation = getResources().getDimensionPixelSize(
R.dimen.disappear_y_translation);
+ mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
}
@Override
@@ -136,7 +144,10 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
setTranslationY(0);
AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 280 /* duration */,
mDisappearYTranslation, mDisappearAnimationUtils.getInterpolator());
- mDisappearAnimationUtils.startAnimation2d(mViews,
+ DisappearAnimationUtils disappearAnimationUtils = mKeyguardUpdateMonitor.isUserUnlocked()
+ ? mDisappearAnimationUtils
+ : mDisappearAnimationUtilsLocked;
+ disappearAnimationUtils.startAnimation2d(mViews,
new Runnable() {
@Override
public void run() {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index e07049262c6e..84b90c44c1a6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -55,9 +55,13 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
// how many cells the user has to cross before we poke the wakelock
private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
+ // How much we scale up the duration of the disappear animation when the current user is locked
+ public static final float DISAPPEAR_MULTIPLIER_LOCKED = 1.5f;
+
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final AppearAnimationUtils mAppearAnimationUtils;
private final DisappearAnimationUtils mDisappearAnimationUtils;
+ private final DisappearAnimationUtils mDisappearAnimationUtilsLocked;
private CountDownTimer mCountdownTimer = null;
private LockPatternUtils mLockPatternUtils;
@@ -109,6 +113,10 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
125, 1.2f /* translationScale */,
0.6f /* delayScale */, AnimationUtils.loadInterpolator(
mContext, android.R.interpolator.fast_out_linear_in));
+ mDisappearAnimationUtilsLocked = new DisappearAnimationUtils(context,
+ (long) (125 * DISAPPEAR_MULTIPLIER_LOCKED), 1.2f /* translationScale */,
+ 0.6f /* delayScale */, AnimationUtils.loadInterpolator(
+ mContext, android.R.interpolator.fast_out_linear_in));
mDisappearYTranslation = getResources().getDimensionPixelSize(
R.dimen.disappear_y_translation);
}
@@ -239,11 +247,21 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
pattern,
userId,
new LockPatternChecker.OnCheckCallback() {
+
+ @Override
+ public void onEarlyMatched() {
+ onPatternChecked(userId, true /* matched */, 0 /* timeoutMs */,
+ true /* isValidPattern */);
+ }
+
@Override
public void onChecked(boolean matched, int timeoutMs) {
mLockPatternView.enableInput();
mPendingLockCheck = null;
- onPatternChecked(userId, matched, timeoutMs, true);
+ if (!matched) {
+ onPatternChecked(userId, false /* matched */, timeoutMs,
+ true /* isValidPattern */);
+ }
}
});
if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
@@ -390,25 +408,30 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
@Override
public boolean startDisappearAnimation(final Runnable finishRunnable) {
+ float durationMultiplier = mKeyguardUpdateMonitor.isUserUnlocked()
+ ? 1f
+ : DISAPPEAR_MULTIPLIER_LOCKED;
mLockPatternView.clearPattern();
enableClipping(false);
setTranslationY(0);
- AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 300 /* duration */,
+ AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */,
+ (long) (300 * durationMultiplier),
-mDisappearAnimationUtils.getStartTranslation(),
mDisappearAnimationUtils.getInterpolator());
- mDisappearAnimationUtils.startAnimation2d(mLockPatternView.getCellStates(),
- new Runnable() {
- @Override
- public void run() {
- enableClipping(true);
- if (finishRunnable != null) {
- finishRunnable.run();
- }
+
+ DisappearAnimationUtils disappearAnimationUtils = mKeyguardUpdateMonitor.isUserUnlocked()
+ ? mDisappearAnimationUtils
+ : mDisappearAnimationUtilsLocked;
+ disappearAnimationUtils.startAnimation2d(mLockPatternView.getCellStates(),
+ () -> {
+ enableClipping(true);
+ if (finishRunnable != null) {
+ finishRunnable.run();
}
}, KeyguardPatternView.this);
if (!TextUtils.isEmpty(mSecurityMessageDisplay.getText())) {
mDisappearAnimationUtils.createAnimation(mSecurityMessageDisplay, 0,
- 200,
+ (long) (200 * durationMultiplier),
- mDisappearAnimationUtils.getStartTranslation() * 3,
false /* appearing */,
mDisappearAnimationUtils.getInterpolator(),
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 94d9550f77e4..dec1fd229e9f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -16,6 +16,16 @@
package com.android.keyguard;
+import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
+import static android.os.BatteryManager.BATTERY_STATUS_FULL;
+import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.BatteryManager.EXTRA_HEALTH;
+import static android.os.BatteryManager.EXTRA_LEVEL;
+import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
+import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE;
+import static android.os.BatteryManager.EXTRA_PLUGGED;
+import static android.os.BatteryManager.EXTRA_STATUS;
+
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
@@ -29,7 +39,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.graphics.Bitmap;
-import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
@@ -42,6 +51,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
@@ -69,16 +79,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
-import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
-import static android.os.BatteryManager.BATTERY_STATUS_FULL;
-import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
-import static android.os.BatteryManager.EXTRA_HEALTH;
-import static android.os.BatteryManager.EXTRA_LEVEL;
-import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
-import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE;
-import static android.os.BatteryManager.EXTRA_PLUGGED;
-import static android.os.BatteryManager.EXTRA_STATUS;
-
/**
* Watches for updates that may be interesting to the keyguard, and provides
* the up to date information as well as a registration for callbacks that care
@@ -176,6 +176,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private boolean mGoingToSleep;
private boolean mBouncer;
private boolean mBootCompleted;
+ private boolean mUserUnlocked;
// Device provisioning state
private boolean mDeviceProvisioned;
@@ -202,6 +203,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private AlarmManager mAlarmManager;
private List<SubscriptionInfo> mSubscriptionInfo;
private TrustManager mTrustManager;
+ private UserManager mUserManager;
private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED;
private final Handler mHandler = new Handler() {
@@ -554,6 +556,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
&& !hasFingerprintUnlockTimedOut(sCurrentUser);
}
+ public boolean isUserUnlocked() {
+ return mUserUnlocked;
+ }
+
public StrongAuthTracker getStrongAuthTracker() {
return mStrongAuthTracker;
}
@@ -1058,6 +1064,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
if (mFpm != null) {
mFpm.addLockoutResetCallback(mLockoutResetCallback);
}
+
+ mUserManager = context.getSystemService(UserManager.class);
}
private void updateFingerprintListeningState() {
@@ -1390,6 +1398,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private void handleKeyguardReset() {
if (DEBUG) Log.d(TAG, "handleKeyguardReset");
updateFingerprintListeningState();
+ mUserUnlocked = mUserManager.isUserUnlocked(getCurrentUser());
}
/**
diff --git a/packages/PrintSpooler/res/drawable/print_button.xml b/packages/PrintSpooler/res/drawable/print_button.xml
index b59afba80293..01141032e66f 100644
--- a/packages/PrintSpooler/res/drawable/print_button.xml
+++ b/packages/PrintSpooler/res/drawable/print_button.xml
@@ -16,7 +16,7 @@
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/print_button_tint_color">
+ android:color="?android:attr/colorControlHighlight">
<item
android:drawable="@drawable/print_button_background">
</item>
diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml
index 47e616ef40c7..9464c678e59c 100644
--- a/packages/PrintSpooler/res/values/colors.xml
+++ b/packages/PrintSpooler/res/values/colors.xml
@@ -16,8 +16,6 @@
<resources>
- <color name="print_button_tint_color">#EEFF41</color>
-
<color name="print_preview_scrim_color">#99000000</color>
<color name="print_preview_background_color">#F2F1F2</color>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index 99145b7bda0a..eea92b5ca62e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -94,6 +94,7 @@ public final class RemotePrintDocument {
// but the content has changed.
if (mNextCommand == null) {
if (mUpdateSpec.pages != null && (mDocumentInfo.changed
+ || mDocumentInfo.writtenPages == null
|| (mDocumentInfo.info.getPageCount()
!= PrintDocumentInfo.PAGE_COUNT_UNKNOWN
&& !PageRangeUtils.contains(mDocumentInfo.writtenPages,
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 2c4025d25380..3e262d08286a 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -526,6 +526,14 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
.setContentType(info.getContentType())
.setPageCount(pageCount)
.build();
+
+ File file = mFileProvider.acquireFile(null);
+ try {
+ adjustedInfo.setDataSize(file.length());
+ } finally {
+ mFileProvider.releaseFile();
+ }
+
mPrintJob.setDocumentInfo(adjustedInfo);
mPrintJob.setPages(document.printedPages);
}
@@ -3077,6 +3085,14 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
.setContentType(oldDocInfo.getContentType())
.setPageCount(newPageCount)
.build();
+
+ File file = mFileProvider.acquireFile(null);
+ try {
+ newDocInfo.setDataSize(file.length());
+ } finally {
+ mFileProvider.releaseFile();
+ }
+
mPrintJob.setDocumentInfo(newDocInfo);
}
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 6ea9ae57ae3e..cf78a01e6fb5 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -322,7 +322,7 @@
<string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Rendszergazda által irányítva"</string>
<string name="enabled_by_admin" msgid="2386503803463071894">"Engedélyezve a rendszergazda által"</string>
<string name="disabled_by_admin" msgid="3669999613095206948">"Letiltva a rendszergazda által"</string>
- <string name="home" msgid="3256884684164448244">"Kezdőlap beállítása"</string>
+ <string name="home" msgid="3256884684164448244">"Beállítások kezdőlapja"</string>
<string-array name="battery_labels">
<item msgid="8494684293649631252">"0%"</item>
<item msgid="8934126114226089439">"50%"</item>
diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml
index 561691dda46e..492b07d8e553 100644
--- a/packages/SettingsLib/res/values-my-rMM/strings.xml
+++ b/packages/SettingsLib/res/values-my-rMM/strings.xml
@@ -200,7 +200,7 @@
<string name="select_application" msgid="5156029161289091703">"အပလီကေးရှင်းရွေးá€á€»á€šá€ºá€›á€”်"</string>
<string name="no_application" msgid="2813387563129153880">"á€á€á€¯á€™á€¾á€™á€›á€¾á€­"</string>
<string name="wait_for_debugger" msgid="1202370874528893091">"အပြစ်ရှာဖွေ ဖယ်ရှားá€á€»á€€á€ºá€€á€­á€¯á€…ောင့်ရန်"</string>
- <string name="wait_for_debugger_summary" msgid="1766918303462746804">"အမှားပြင်ဆင်ရှာဖွေသည့် အပလီကေးရှင်းသည် လုပ်ငန်းမစမှီ á€á€½á€²á€–က်ရန် အမှားရှာဖွေမည့်သူကို စောင့်နေသည်á‹"</string>
+ <string name="wait_for_debugger_summary" msgid="1766918303462746804">"အမှားပြင်ဆင်ရှာဖွေသည့် အပလီကေးရှင်းသည် လုပ်ငန်းမစမီ á€á€½á€²á€–က်ရန် အမှားရှာဖွေမည့်သူကို စောင့်နေသည်á‹"</string>
<string name="debug_input_category" msgid="1811069939601180246">"ထည့်သွင်းရန်"</string>
<string name="debug_drawing_category" msgid="6755716469267367852">"ရေးဆွဲá€á€¼á€„်း"</string>
<string name="debug_hw_drawing_category" msgid="6220174216912308658">"ဟာ့ဒ်á€á€² အရှိန်မြှင့် ပုံဖော်á€á€¼á€„်း"</string>
@@ -213,11 +213,11 @@
<string name="show_touches" msgid="2642976305235070316">"á€á€­á€¯á€·á€á€¼á€„်းများကို ပြပါ"</string>
<string name="show_touches_summary" msgid="6101183132903926324">"á€á€­á€¯á€·á€á€¼á€„်းများအá€á€½á€€á€º အမြင်ဖြင့် á€á€¯á€¶á€·á€•ြန်မှုပြပါ"</string>
<string name="show_screen_updates" msgid="5470814345876056420">"surface အဆင့်မြှင့်မှုများပြပါ"</string>
- <string name="show_screen_updates_summary" msgid="2569622766672785529">"အဆင့်မြှင့်နေစဉ် á€á€„်းဒိုးမျက်နှာá€á€•ြင်လုံးကို အá€á€»á€€á€ºá€•ြရန်"</string>
+ <string name="show_screen_updates_summary" msgid="2569622766672785529">"အပ်ဒိá€á€ºá€œá€¯á€•်စဉ် á€á€„်းဒိုးမျက်နှာပြင်á€á€½á€„် အá€á€»á€€á€ºá€•ြရန်"</string>
<string name="show_hw_screen_updates" msgid="5036904558145941590">"GPUမြင်ကွင်းအဆင့်မြှင့်á€á€¼á€„်းများပြရန်"</string>
<string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"GPU နှင့်ဆွဲစဉ် á€á€„်းဒိုးအá€á€½á€„်းပိုင်း လျှပ်á€á€•ြက်မြင်ကွင်းများ"</string>
<string name="show_hw_layers_updates" msgid="5645728765605699821">"ဟာ့ဒ်á€á€²á€¡á€œá€½á€¾á€¬á€™á€»á€¬á€¸á€¡á€†á€„်မြှင့်မှုကိုပြရန်"</string>
- <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"အဆင့်မြှင်á€á€»á€­á€”် ဟာ့ဒ်á€á€²á€¡á€œá€½á€¾á€¬á€™á€»á€¬á€¸á€€á€­á€¯ အစိမ်းရောင်ဖြင့်အá€á€»á€€á€ºá€•ြရန်"</string>
+ <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"အပ်ဒိá€á€ºá€œá€¯á€•်á€á€»á€­á€”် ဟာ့ဒ်á€á€²á€¡á€œá€½á€¾á€¬á€™á€»á€¬á€¸ အစိမ်းရောင်ပြပါ"</string>
<string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ပိုသုံးစွဲမှုအမှားရှာဖွေပြင်ဆင်ရန်"</string>
<string name="disable_overlays" msgid="2074488440505934665">"HWထပ်ဆင့်အရာများပိá€á€ºá€›á€”်"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"GPU ကိုမျက်နှာပြင်á€á€„်းကျင်းရာá€á€½á€„် အမြဲသုံးပါá‹"</string>
@@ -283,7 +283,7 @@
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ပြောင်းရန်…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ဖိုင်ကို လုံá€á€¼á€¯á€¶á€¡á€±á€¬á€„်ပြုလုပ်ပြီးပါပြီ"</string>
<string name="title_convert_fbe" msgid="1263622876196444453">"ဖိုင်အá€á€¼á€±á€•ြုလုံá€á€¼á€¯á€¶á€¡á€±á€¬á€„်ပြုလုပ်á€á€¼á€„်းသို့ ပြောင်းလဲရန်"</string>
- <string name="convert_to_fbe_warning" msgid="6139067817148865527">"အá€á€»á€€á€ºá€¡á€œá€€á€ºá€¡á€•ိုင်းကို ဖိုင်အá€á€¼á€±á€•ြုလုံá€á€¼á€¯á€¶á€¡á€±á€¬á€„်ပြုလုပ်á€á€¼á€„်းသို့ ပြောင်းပါá‹\n !!သá€á€­!! áŽá€„်းသည်သင့် အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸á€œá€¯á€¶á€¸á€€á€­á€¯ ဖျက်ပါမည်ዠ\n ဤလုပ်ဆောင်á€á€»á€€á€ºá€žá€Šá€º ပထမအဆင့်á€á€½á€„်သာ ရှိသေးပြီး မှန်ကန်စွာ လုပ်ဆောင်လိမ့်မည် မဟုá€á€ºá€•ါá‹\n ရှေ့ဆက်ရန် \'ရှင်းလင်းပြီး ပြောင်းလဲရန်…\' ကိုနှိပ်ပါá‹"</string>
+ <string name="convert_to_fbe_warning" msgid="6139067817148865527">"အá€á€»á€€á€ºá€¡á€œá€€á€ºá€¡á€•ိုင်းကို ဖိုင်အá€á€¼á€±á€•ြုလုံá€á€¼á€¯á€¶á€¡á€±á€¬á€„်ပြုလုပ်á€á€¼á€„်းသို့ ပြောင်းပါá‹\n !!သá€á€­!! áŽá€„်းသည်သင့် အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸á€¡á€¬á€¸á€œá€¯á€¶á€¸á€€á€­á€¯ ဖျက်ပါမည်ዠ\n ဤလုပ်ဆောင်á€á€»á€€á€ºá€žá€Šá€º ပထမအဆင့်á€á€½á€„်သာ ရှိသေးပြီး မှန်ကန်စွာ လုပ်ဆောင်လိမ့်မည် မဟုá€á€ºá€•ါá‹\n ဆက်လုပ်ရန် \'ရှင်းလင်းပြီး ပြောင်းလဲရန်…\' ကိုနှိပ်ပါá‹"</string>
<string name="button_convert_fbe" msgid="5152671181309826405">"ရှင်းလင်းပြီး ပြောင်းလဲရန်…"</string>
<string name="picture_color_mode" msgid="4560755008730283695">"ဓာá€á€ºá€•ုံအရောင်မုဒ်"</string>
<string name="picture_color_mode_desc" msgid="1141891467675548590">"sRGB ကို အသုံးပြုပါ"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 6efd78250643..b8fc9ffa34f7 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -221,7 +221,7 @@
<string name="debug_hw_overdraw" msgid="2968692419951565417">"Depurar sobreposição GPU"</string>
<string name="disable_overlays" msgid="2074488440505934665">"Desativ. sobreposições HW"</string>
<string name="disable_overlays_summary" msgid="3578941133710758592">"Utilizar sempre GPU para a composição do ecrã"</string>
- <string name="simulate_color_space" msgid="6745847141353345872">"Simular espaço de cor"</string>
+ <string name="simulate_color_space" msgid="6745847141353345872">"Simular espaço da cor"</string>
<string name="enable_opengl_traces_title" msgid="6790444011053219871">"Ativar vestígios OpenGL"</string>
<string name="usb_audio_disable_routing" msgid="8114498436003102671">"Desativ. encam. áudio USB"</string>
<string name="usb_audio_disable_routing_summary" msgid="980282760277312264">"Desativar encam. auto. para periféricos áudio USB"</string>
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 108814e66348..978ca9466ff1 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -216,7 +216,4 @@
<!-- Default setting for ability to add users from the lock screen -->
<bool name="def_add_users_from_lockscreen">false</bool>
-
- <!-- Default setting for disallow oem unlock. -->
- <bool name="def_oem_unlock_disallow">false</bool>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index b79ce8027231..bf48e5de1da3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -247,7 +247,6 @@ public class SettingsHelper {
return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) != 0;
case Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES:
case Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES:
- case Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX:
case Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER:
case Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE:
return !TextUtils.isEmpty(Settings.Secure.getString(
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 950c7d33b672..1928f92f5855 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -799,7 +799,8 @@ public class SettingsProvider extends ContentProvider {
// If this is a setting that is currently restricted for this user, do not allow
// unrestricting changes.
- if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value)) {
+ if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value,
+ Binder.getCallingUid())) {
return false;
}
@@ -930,7 +931,8 @@ public class SettingsProvider extends ContentProvider {
// If this is a setting that is currently restricted for this user, do not allow
// unrestricting changes.
- if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value)) {
+ if (isGlobalOrSecureSettingRestrictedForUser(name, callingUserId, value,
+ Binder.getCallingUid())) {
return false;
}
@@ -1153,7 +1155,7 @@ public class SettingsProvider extends ContentProvider {
* @return true if the change is prohibited, false if the change is allowed.
*/
private boolean isGlobalOrSecureSettingRestrictedForUser(String setting, int userId,
- String value) {
+ String value, int callingUid) {
String restriction;
switch (setting) {
case Settings.Secure.LOCATION_MODE:
@@ -1191,6 +1193,15 @@ public class SettingsProvider extends ContentProvider {
restriction = UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
break;
+ case Settings.Secure.ALWAYS_ON_VPN_APP:
+ case Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN:
+ // Whitelist system uid (ConnectivityService) and root uid to change always-on vpn
+ if (callingUid == Process.SYSTEM_UID || callingUid == Process.ROOT_UID) {
+ return false;
+ }
+ restriction = UserManager.DISALLOW_CONFIG_VPN;
+ break;
+
default:
if (setting != null && setting.startsWith(Settings.Global.DATA_ROAMING)) {
if ("0".equals(value)) return false;
@@ -2074,7 +2085,7 @@ public class SettingsProvider extends ContentProvider {
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 128;
+ private static final int SETTINGS_VERSION = 129;
private final int mUserId;
@@ -2330,17 +2341,41 @@ public class SettingsProvider extends ContentProvider {
}
if (currentVersion == 127) {
- // Version 127: Disable OEM unlock setting by default on some devices.
- final SettingsState globalSettings = getGlobalSettingsLocked();
- String defaultOemUnlockDisabled = (getContext().getResources()
- .getBoolean(R.bool.def_oem_unlock_disallow) ? "1" : "0");
- globalSettings.insertSettingLocked(
- Settings.Global.OEM_UNLOCK_DISALLOWED,
- defaultOemUnlockDisabled,
- SettingsState.SYSTEM_PACKAGE_NAME);
+ // version 127 is no longer used.
currentVersion = 128;
}
+ if (currentVersion == 128) {
+ // Version 128: Allow OEMs to grant DND access to default apps. Note that
+ // the new apps are appended to the list of already approved apps.
+ final SettingsState systemSecureSettings =
+ getSecureSettingsLocked(userId);
+
+ final Setting policyAccess = systemSecureSettings.getSettingLocked(
+ Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
+ String defaultPolicyAccess = getContext().getResources().getString(
+ com.android.internal.R.string.config_defaultDndAccessPackages);
+ if (!TextUtils.isEmpty(defaultPolicyAccess)) {
+ if (policyAccess.isNull()) {
+ systemSecureSettings.insertSettingLocked(
+ Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
+ defaultPolicyAccess,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ } else {
+ StringBuilder currentSetting =
+ new StringBuilder(policyAccess.getValue());
+ currentSetting.append(":");
+ currentSetting.append(defaultPolicyAccess);
+ systemSecureSettings.updateSettingLocked(
+ Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
+ currentSetting.toString(),
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+ }
+
+ currentVersion = 129;
+ }
+
// vXXX: Add new settings above this point.
// Return the current version.
diff --git a/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
index 010815a41819..778ccbc5f4a4 100644
--- a/packages/SystemUI/res/drawable/ic_night_mode_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_night_display_off.xml
@@ -14,11 +14,14 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:alpha="0.3">
+
<path
- android:fillColor="#4DFFFFFF"
- android:pathData="M20.71,5.63l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0.0l-3.12,3.12 -1.93,-1.91 -1.41,1.41 1.42,1.42L3.0,16.25L3.0,21.0l4.75,0.0l8.92,-8.92 1.42,1.42 1.41,-1.41 -1.92,-1.92 3.12,-3.12c0.4,0.0 0.4,-1.0 0.01,-1.42zM6.92,19.0L5.0,17.08l8.06,-8.06 1.92,1.92L6.92,19.0z"/>
+ android:fillColor="#FFF"
+ android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
+
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_night_mode.xml b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
index caa7a47ee5b4..aaca663e59e9 100644
--- a/packages/SystemUI/res/drawable/ic_night_mode.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
@@ -14,11 +14,13 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="64dp"
+ android:height="64dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M20.71,5.63l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0.0l-3.12,3.12 -1.93,-1.91 -1.41,1.41 1.42,1.42L3.0,16.25L3.0,21.0l4.75,0.0l8.92,-8.92 1.42,1.42 1.41,-1.41 -1.92,-1.92 3.12,-3.12c0.4,0.0 0.4,-1.0 0.01,-1.42zM6.92,19.0L5.0,17.08l8.06,-8.06 1.92,1.92L6.92,19.0z"/>
+ android:fillColor="#FFF"
+ android:pathData="M6,12c0,5.5,4.5,10,10,10c1,0,2-0.2,3-0.5c-4.1-1.3-7-5.1-7-9.5s2.9-8.3,7-9.5C18.1,2.2,17.1,2,16,2C10.5,2,6,6.5,6,12z" />
+
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
index 258bd0f7902e..4d7f325073dc 100644
--- a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
@@ -1,37 +1,30 @@
<!--
- Copyright (C) 2016 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
+ 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
- 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.
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="18.0dp"
- android:height="24dp"
- android:viewportWidth="36.0"
- android:viewportHeight="36.0">
-
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
<path
- android:fillColor="#FFFFFF"
- android:pathData="M6.797,13.334h1.231v1.522H6.797v2.509h-1.62v-2.509H1.101l-0.039-1.157l4.069-7.643h1.666V13.334z
-M2.648,13.334h2.53V8.721L5.137,8.713L4.984,9.148L2.648,13.334z" />
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
<path
- android:fillColor="#FFFFFF"
- android:pathData="M16.155,15.836c-0.269,0.439-0.695,0.832-1.282,1.177c-0.587,0.344-1.344,0.517-2.271,0.517
-c-1.151,0-2.098-0.432-2.841-1.294c-0.744-0.862-1.115-1.978-1.115-3.345v-2.36c0-1.367,0.359-2.481,1.077-3.343
-c0.719-0.863,1.643-1.293,2.772-1.293c1.132,0,2.017,0.331,2.649,0.994c0.633,0.663,0.941,1.528,0.924,2.594l-0.021,0.047h-1.545
-c0-0.638-0.171-1.15-0.513-1.538c-0.341-0.389-0.831-0.583-1.469-0.583c-0.674,0-1.217,0.292-1.63,0.877
-c-0.413,0.585-0.619,1.328-0.619,2.229v2.375c0,0.912,0.215,1.662,0.645,2.25c0.431,0.587,0.992,0.881,1.684,0.881
-c0.522,0,0.935-0.068,1.238-0.205c0.304-0.138,0.533-0.305,0.688-0.502v-2.338h-2.041v-1.413h3.668V15.836z" />
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M11.9,9.9c-0.2,0.4 -0.6,0.7 -1.0,0.9s-1.0,0.4 -1.8,0.4c-0.9,0.0 -1.7,-0.3 -2.2,-0.8S6.1,9.0 6.1,7.9L6.1,5.6c0.0,-1.1 0.3,-1.9 0.8,-2.4S8.2,2.4 9.0,2.4c1.0,0.0 1.7,0.2 2.1,0.7s0.7,1.2 0.7,2.1l-1.6,0.0c0.0,-0.5 -0.1,-0.9 -0.2,-1.1S9.5,3.7 9.0,3.7c-0.4,0.0 -0.7,0.2 -0.9,0.5S7.8,5.0 7.8,5.6l0.0,2.3c0.0,0.7 0.1,1.1 0.3,1.4c0.2,0.3 0.6,0.5 1.0,0.5c0.3,0.0 0.6,0.0 0.7,-0.1s0.3,-0.2 0.4,-0.3L10.2,7.8L9.0,7.8L9.0,6.6l2.9,0.0L11.9,9.9z"/>
<path
- android:fillColor="#FFFFFF"
- android:pathData="M19.366,14.701v-2.232h-2.25v-1.541h2.25V8.695h1.5v2.232h2.256v1.541h-2.256v2.232H19.366z" />
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M17.7,4.4l-1.900001,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.900001,0.0z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
new file mode 100644
index 000000000000..3af062999728
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
@@ -0,0 +1,33 @@
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M8.3,3.8L7.0,3.8L7.0,11.0L5.4,11.0L5.4,3.8L4.0,3.8L4.0,2.5l4.3,0.0L8.3,3.8z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.4,7.3l-1.7,0.0l0.0,2.4l2.1,0.0L12.799999,11.0L9.0,11.0L9.0,2.5l3.7,0.0l0.0,1.3l-2.1,0.0l0.0,2.1l1.7,0.0L12.4,7.3L12.4,7.3z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M18.4,4.4l-1.9,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.9,0.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
index 17a4394ce6df..3cdd3e104bfb 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_4g_plus.xml
@@ -1,37 +1,30 @@
<!--
- Copyright (C) 2016 The Android Open Source Project
+ Copyright (C) 2016 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
+ http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- 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.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="15dp"
- android:height="20dp"
- android:viewportWidth="36"
- android:viewportHeight="36">
-
+ android:width="17.0dp"
+ android:height="17.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
<path
- android:fillColor="#FFFFFF"
- android:pathData="M6.797,13.334h1.231v1.522H6.797v2.509h-1.62v-2.509H1.101l-0.039-1.157l4.069-7.643h1.666V13.334z
-M2.648,13.334h2.53V8.721L5.137,8.713L4.984,9.148L2.648,13.334z" />
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
<path
- android:fillColor="#FFFFFF"
- android:pathData="M16.155,15.836c-0.269,0.439-0.695,0.832-1.282,1.177c-0.587,0.344-1.344,0.517-2.271,0.517
-c-1.151,0-2.098-0.432-2.841-1.294c-0.744-0.862-1.115-1.978-1.115-3.345v-2.36c0-1.367,0.359-2.481,1.077-3.343
-c0.719-0.863,1.643-1.293,2.772-1.293c1.132,0,2.017,0.331,2.649,0.994c0.633,0.663,0.941,1.528,0.924,2.594l-0.021,0.047h-1.545
-c0-0.638-0.171-1.15-0.513-1.538c-0.341-0.389-0.831-0.583-1.469-0.583c-0.674,0-1.217,0.292-1.63,0.877
-c-0.413,0.585-0.619,1.328-0.619,2.229v2.375c0,0.912,0.215,1.662,0.645,2.25c0.431,0.587,0.992,0.881,1.684,0.881
-c0.522,0,0.935-0.068,1.238-0.205c0.304-0.138,0.533-0.305,0.688-0.502v-2.338h-2.041v-1.413h3.668V15.836z" />
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M11.9,9.9c-0.2,0.4 -0.6,0.7 -1.0,0.9s-1.0,0.4 -1.8,0.4c-0.9,0.0 -1.7,-0.3 -2.2,-0.8S6.1,9.0 6.1,7.9L6.1,5.6c0.0,-1.1 0.3,-1.9 0.8,-2.4S8.2,2.4 9.0,2.4c1.0,0.0 1.7,0.2 2.1,0.7s0.7,1.2 0.7,2.1l-1.6,0.0c0.0,-0.5 -0.1,-0.9 -0.2,-1.1S9.5,3.7 9.0,3.7c-0.4,0.0 -0.7,0.2 -0.9,0.5S7.8,5.0 7.8,5.6l0.0,2.3c0.0,0.7 0.1,1.1 0.3,1.4c0.2,0.3 0.6,0.5 1.0,0.5c0.3,0.0 0.6,0.0 0.7,-0.1s0.3,-0.2 0.4,-0.3L10.2,7.8L9.0,7.8L9.0,6.6l2.9,0.0L11.9,9.9z"/>
<path
- android:fillColor="#FFFFFF"
- android:pathData="M19.366,14.701v-2.232h-2.25v-1.541h2.25V8.695h1.5v2.232h2.256v1.541h-2.256v2.232H19.366z" />
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M17.7,4.4l-1.900001,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.900001,0.0z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
new file mode 100644
index 000000000000..db18fad637e7
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_lte_plus.xml
@@ -0,0 +1,33 @@
+<!--
+ Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="17.0dp"
+ android:height="17.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M8.3,3.8L7.0,3.8L7.0,11.0L5.4,11.0L5.4,3.8L4.0,3.8L4.0,2.5l4.3,0.0L8.3,3.8z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.4,7.3l-1.7,0.0l0.0,2.4l2.1,0.0L12.799999,11.0L9.0,11.0L9.0,2.5l3.7,0.0l0.0,1.3l-2.1,0.0l0.0,2.1l1.7,0.0L12.4,7.3L12.4,7.3z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M18.4,4.4l-1.9,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.9,0.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/battery_detail.xml b/packages/SystemUI/res/layout/battery_detail.xml
index 1f24ab0fad21..8abfcf6057aa 100644
--- a/packages/SystemUI/res/layout/battery_detail.xml
+++ b/packages/SystemUI/res/layout/battery_detail.xml
@@ -25,7 +25,7 @@
android:id="@+id/charge_and_estimation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingStart="72dp"
+ android:paddingStart="16dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/colorAccent" />
diff --git a/packages/SystemUI/res/layout/calibrate_sliders.xml b/packages/SystemUI/res/layout/calibrate_sliders.xml
deleted file mode 100644
index 0dec8a18caa4..000000000000
--- a/packages/SystemUI/res/layout/calibrate_sliders.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/r_group"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="4dp"
- android:paddingBottom="4dp"
- android:orientation="horizontal">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/color_modification_r"
- android:gravity="center"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <SeekBar android:id="@*android:id/seekbar"
- android:layout_marginStart="16dp"
- android:layout_gravity="center_vertical"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1" />
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/g_group"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="4dp"
- android:paddingBottom="4dp"
- android:orientation="horizontal">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/color_modification_g"
- android:gravity="center"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <SeekBar android:id="@*android:id/seekbar"
- android:layout_marginStart="16dp"
- android:layout_gravity="center_vertical"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1" />
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/b_group"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="4dp"
- android:paddingBottom="4dp"
- android:orientation="horizontal">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/color_modification_b"
- android:gravity="center"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <SeekBar android:id="@*android:id/seekbar"
- android:layout_marginStart="16dp"
- android:layout_gravity="center_vertical"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1" />
- </LinearLayout>
-
-</LinearLayout>
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
index c062b6d671a5..f6ca862370ac 100644
--- a/packages/SystemUI/res/layout/qs_detail_header.xml
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -22,19 +22,9 @@
android:background="@drawable/btn_borderless_rect"
android:gravity="center">
- <ImageView
- android:id="@*android:id/up"
- android:layout_width="56dp"
- android:layout_height="56dp"
- android:layout_marginEnd="16dp"
- android:padding="16dp"
- android:clickable="true"
- android:background="?android:attr/selectableItemBackground"
- android:contentDescription="@*android:string/action_bar_up_description"
- android:src="?android:attr/homeAsUpIndicator" />
-
<TextView
android:id="@android:id/title"
+ android:paddingStart="16dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 3b8b909118f1..6673d6e8255f 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -111,7 +111,7 @@
android:layout_alignParentTop="true"
android:paddingStart="16dp"
android:paddingEnd="16dp"
- android:paddingTop="2dp"
+ android:paddingTop="6dp"
android:visibility="gone"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.EmergencyCallsOnly"
android:text="@*android:string/emergency_calls_only"
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 68395cd69890..4cd635e40c2d 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -48,6 +48,7 @@
android:clickable="true"
android:soundEffectsEnabled="false"
android:src="@drawable/ic_volume_collapse_animation"
+ android:background="@drawable/ripple_drawable"
tools:ignore="RtlHardcoded"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index a30fc4356a51..95019b873dcf 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -22,7 +22,8 @@
android:id="@+id/volume_dialog_row"
android:paddingEnd="@dimen/volume_dialog_padding_end"
android:orientation="vertical"
- android:paddingBottom="@dimen/volume_row_padding_bottom" >
+ android:paddingBottom="@dimen/volume_row_padding_bottom"
+ android:animateLayoutChanges="true">
<TextView
android:id="@+id/volume_row_header"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 710be7a4075a..536a50b1a3a6 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Meer instellings"</string>
<string name="notification_done" msgid="5279426047273930175">"Klaar"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g>-kennisgewingkontroles"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Kleur en voorkoms"</string>
- <string name="night_mode" msgid="3540405868248625488">"Nagmodus"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibreer skerm"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Aan"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Af"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Skakel outomaties aan"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Skakel oor na Nagmodus soos gepas vir ligging en tyd van die dag"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Wanneer Nagmodus aan is"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Gebruik donkertema vir Android-bedryfstelsel"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Verstel tint"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Verstel helderheid"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Die donkertema word toegepas op kernareas van Android-bedryfstelsel wat gewoonlik in \'n ligtema gewys word, soos instellings."</string>
- <string name="color_apply" msgid="9212602012641034283">"Pas toe"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Bevestig instellings"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Sommige kleurinstellings kan hierdie toestel onbruikbaar maak. Klik OK om hierdie kleurinstellings te bevestig; andersins sal hierdie instellings ná 10 sekondes teruggestel word."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batterygebruik"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterybespaarder is nie beskikbaar wanneer gelaai word nie"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterybespaarder"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 7e0cfef2ab63..2c13ff158482 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"ተጨማሪ ቅንብሮች"</string>
<string name="notification_done" msgid="5279426047273930175">"ተከናá‹áŠ—áˆ"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> ማሳወቂያ á‰áŒ¥áŒ¥áˆ®á‰½"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"ቀለሠእና መáˆáŠ­"</string>
- <string name="night_mode" msgid="3540405868248625488">"የሌሊት áˆáŠá‰³"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ማሳያን ይለኩ"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"በርቷáˆ"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ጠáቷáˆ"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"በራስ-ሰር አብራ"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"ለአካባቢዠእና ለሰዓቱ ተገቢ በሆአመáˆáŠ© ወደ የማታ áˆáŠá‰³ ለá‹áŒ¥"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"የማታ áˆáŠá‰³ ሲበራ"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"ለAndroid ስርዓተ ክወና ጨለማ ገጽታን ተጠቀáˆ"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ቅáˆáˆ አስተካክáˆ"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ብሩህáŠá‰µ አስተካክáˆ"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"ጨለማ ገጽታዠእንደ ቅንብሮች ያሉ በመደበኛáŠá‰µ በብርሃን ገጽታ በሚታዩ የAndroid ስርዓተ ክወና ዋና ክáሎች ላይ ይተገበራáˆá¢"</string>
- <string name="color_apply" msgid="9212602012641034283">"ተáŒá‰¥áˆ­"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"ቅንብሮችን ያረጋáŒáŒ¡"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"አንዳንድ የቀለሠቅንብሮች ይህን መሣሪያ የማይጠቅሠሊያደርጉት ይችላሉᢠእáŠá‹šáˆ…ን የቀለሠቅንብሮች ለማረጋገጥ እሺ የሚለá‹áŠ• ጠቅ ያድርጉᣠአለበለዚያ እáŠá‹šáˆ… ቅንብሮች ከ10 ሰከንዶች በኋላ ዳáŒáˆ ይጀáˆáˆ«áˆ‰á¢"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"የባትሪ አጠቃቀáˆ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ኃይሠበሚሞላበት ጊዜ ባትሪ ቆጣቢ አይገáŠáˆ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ባትሪ ቆጣቢ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 7ef02c14d76e..3bcd0a285234 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -525,21 +525,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"المزيد من الإعدادات"</string>
<string name="notification_done" msgid="5279426047273930175">"تم"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"عناصر التحكم ÙÙŠ إشعارات <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"اللون والمظهر"</string>
- <string name="night_mode" msgid="3540405868248625488">"الوضع الليلي"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"معايرة الشاشة"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"تشغيل"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"إيقاÙ"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"التشغيل تلقائيًا"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"التبديل إلى الوضع الليلي بما يتناسب مع الموقع والوقت من اليوم"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"عند تشغيل الوضع الليلي"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"â€Ø§Ø³ØªØ®Ø¯Ø§Ù… مظهر معتم لنظام التشغيل Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ضبط التلوين الخÙÙŠÙ"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ضبط السطوع"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"â€ÙŠØªÙ… تطبيق المظهر المعتم على المناطق الأساسية ÙÙŠ نظام التشغيل Android والتي يتم عرضها عادة ÙÙŠ مظهر مضيء، مثل الإعدادات."</string>
- <string name="color_apply" msgid="9212602012641034283">"تطبيق"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"تأكيد الإعدادات"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"يمكن أن تتسبب بعض إعدادات الألوان ÙÙŠ تعطيل إمكانية استخدام الجهاز. يمكنك النقر على \"مواÙÙ‚\" لتأكيد إعدادات الألوان هذه، وإلا ÙØ³ØªØªÙ… إعادة تعيين هذه الإعدادات بعد Û±Û° ثوانÙ."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"استخدام البطارية"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"وضع توÙير شحن البطارية غير متاح أثناء الشحن."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"توÙير شحن البطارية"</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index a081e0a26eba..a129a43a0853 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Daha çox ayar"</string>
<string name="notification_done" msgid="5279426047273930175">"Hazırdır"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> bildiriş nəzarəti"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Rəng və görünüş"</string>
- <string name="night_mode" msgid="3540405868248625488">"GecÉ™ rejimi"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Ekranı kalibrləyin"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Aktiv"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Deaktiv"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Avtomatik aktivləşdirin"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Məkana və günün vaxtına uyğun olaraq Gecə Rejiminə keçin"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"GecÉ™ Rejimi aktiv olduqda"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS üçün tünd tema istifadə edin"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Çaları nizamlayın"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Parlaqlığı nizamlayın"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Tünd tema Android sisteminin adətən açıq tonda göstərilən əsas elementlərinə (məsələn, \"Ayarlar\") tətbiq edilir."</string>
- <string name="color_apply" msgid="9212602012641034283">"Tətbiq edin"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Ayarları təsdiq edin"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Bəzi renk ayarları bu cihazı yararsız edə bilər. Bu rənk ayarlarını təsdiq etmək üçün OK basın, əks halda bu ayarlar 10 saniyə sonra sıfırlanacaq."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batareya istifadəsi"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Enerji Qənaəti doldurulma zamanı əlçatan deyil"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Enerji Qənaəti"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index d313af16d73d..f34130e5fd05 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Още наÑтройки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Контроли за извеÑтиÑта от <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"ЦвÑÑ‚ и облик"</string>
- <string name="night_mode" msgid="3540405868248625488">"Ðощен режим"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Калибриране на диÑплеÑ"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Вкл."</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Изкл."</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Ðвтоматично включване"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Превключване към нощен режим Ñпоред меÑтоположението и чаÑа от денонощието"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"При включен нощен режим"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Ползв. на тъмната тема за опер. Ñ-ма Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Коригиране на нюанÑирането"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Коригиране на ÑркоÑтта"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Тъмната тема Ñе прилага към оÑновните облаÑти на операционната ÑиÑтема Android, които обикновено Ñе показват ÑÑŠÑ Ñветла тема, като например наÑтройките."</string>
- <string name="color_apply" msgid="9212602012641034283">"Прилагане"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Потвърждаване на наÑтройките"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"ÐÑкои наÑтройки за цветовете могат да направÑÑ‚ това уÑтройÑтво неизползваемо. За да ги потвърдите, кликнете върху „OK“. Ð’ противен Ñлучай те ще бъдат нулирани Ñлед 10 Ñекунди."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Ползв. на батериÑта"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Режимът за запазване на батериÑта не е налице при зареждане"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Режим за запазване на батериÑта"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 9d8b3515cd9f..93207c418ee8 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"আরো সেটিংস"</string>
<string name="notification_done" msgid="5279426047273930175">"সমà§à¦ªà¦¨à§à¦¨"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> বিজà§à¦žà¦ªà§à¦¤à¦¿à¦° নিয়নà§à¦¤à§à¦°à¦£à¦—à§à¦²à¦¿"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"রঙ à¦à¦¬à¦‚ চেহারা"</string>
- <string name="night_mode" msgid="3540405868248625488">"রাতের মোড"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"পà§à¦°à¦¦à¦°à§à¦¶à¦¨ কà§à¦¯à¦¾à¦²à¦¿à¦¬à§à¦°à§‡à¦Ÿ করà§à¦¨"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"চালৠআছে"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"বনà§à¦§ আছে"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"সà§à¦¬à¦¯à¦¼à¦‚কà§à¦°à¦¿à¦¯à¦¼à¦­à¦¾à¦¬à§‡ চালৠকরà§à¦¨"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"অবসà§à¦¥à¦¾à¦¨ à¦à¦¬à¦‚ সময়ের হিসাবে উপযà§à¦•à§à¦¤ রাতের মোডে পালà§à¦Ÿà¦¾à¦¨"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"যখন রাতের মোড চালৠথাকবে"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS à¦à¦° জনà§à¦¯ গাঢ় থিম বà§à¦¯à¦¬à¦¹à¦¾à¦° করà§à¦¨"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"টিনà§à¦Ÿ সমনà§à¦¬à¦¯à¦¼ করà§à¦¨"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"উজà§à¦œà§à¦¬à¦²à¦¤à¦¾ সমনà§à¦¬à¦¯à¦¼ করà§à¦¨"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Android OS à¦à¦° মূল অংশগà§à¦²à¦¿à¦¤à§‡ গাঢ় থিম পà§à¦°à¦¯à¦¼à§‹à¦— করা হয়েছে যেটা সাধারণত à¦à¦•টি হালকা থিমে পà§à¦°à¦¦à¦°à§à¦¶à¦¿à¦¤ হয়, যেমন সেটিংস৷"</string>
- <string name="color_apply" msgid="9212602012641034283">"পà§à¦°à¦¯à¦¼à§‹à¦— করà§à¦¨"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"সেটিংস নিশà§à¦šà¦¿à¦¤ করà§à¦¨"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"কিছৠরঙের সেটিংস à¦à¦‡ ডিভাইসকে বà§à¦¯à¦¬à¦¹à¦¾à¦°à§‡à¦° অযোগà§à¦¯ করে দিতে পারে৷ à¦à¦‡ রঙের সেটিংস নিশà§à¦šà¦¿à¦¤ করতে ঠিক আছে ঠকà§à¦²à¦¿à¦• করà§à¦¨, অনà§à¦¯à¦¥à¦¾à¦¯à¦¼ ১০ সেকেনà§à¦¡ পরে à¦à¦‡ সেটিংস পà§à¦¨à¦°à¦¾à¦¯à¦¼ সেট হবে৷"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"বà§à¦¯à¦¾à¦Ÿà¦¾à¦°à¦¿à¦° বà§à¦¯à¦¬à¦¹à¦¾à¦°"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"চারà§à¦œ করার সময় বà§à¦¯à¦¾à¦Ÿà¦¾à¦°à¦¿ সেভার উপলবà§à¦§ নয়"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"বà§à¦¯à¦¾à¦Ÿà¦¾à¦°à¦¿ সেভার"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index a3054f29c531..f680f9dd9d92 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Més opcions"</string>
<string name="notification_done" msgid="5279426047273930175">"Fet"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Controls de notificació de l\'aplicació <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Color i aparença"</string>
- <string name="night_mode" msgid="3540405868248625488">"Mode nocturn"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibra la pantalla"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Activat"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Desactivat"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Activa automàticament"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Canvia al mode nocturn d\'acord amb la ubicació i l\'hora del dia"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Quan el mode nocturn estigui activat"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Fes servir un tema fosc per a Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ajusta el color"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Ajusta la brillantor"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"El tema fosc s\'aplica a les àrees clau d\'Android OS que normalment es mostren amb un tema clar, com ara Configuració."</string>
- <string name="color_apply" msgid="9212602012641034283">"Aplica"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirma la configuració"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Algunes opcions de configuració de color poden deixar el dispositiu inservible. Fes clic a D\'acord per confirmar la configuració de color; en cas contrari, la configuració es restablirà al cap de 10 segons."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Ús de la bateria"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"La funció Estalvi de bateria no està disponible durant la càrrega"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Estalvi de bateria"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index e29cd82f2f9f..8a290e438592 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -523,21 +523,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Další nastavení"</string>
<string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Nastavení oznámení aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Barva a vzhled"</string>
- <string name="night_mode" msgid="3540405868248625488">"NoÄní režim"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibrovat displej"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Zapnuto"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Vypnuto"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Zapnout automaticky"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"PÅ™ejít do noÄního režimu automaticky na základÄ› místa a denní doby"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Když je noÄní režim zapnutý"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Použít v systému Android tmavý motiv"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Upravit tónování"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Upravit jas"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"V hlavních oblastech systému Android, které jsou běžně zobrazovány ve světlém motivu (například Nastavení), se použije tmavý motiv."</string>
- <string name="color_apply" msgid="9212602012641034283">"Použít"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Ověření nastavení"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"NÄ›která nastavení barev mohou způsobit, že zařízení nebude použitelné. Kliknutím na OK toto nastavení barev potvrdíte, v opaÄném případÄ› se nastavení po 10 sekundách resetuje."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Využití baterie"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"SpoÅ™iÄ baterie pÅ™i nabíjení není k dispozici."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"SpoÅ™iÄ baterie"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index d0dcdc7a6025..8ebf9fd5dd16 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Flere indstillinger"</string>
<string name="notification_done" msgid="5279426047273930175">"Færdig"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Kontrolelementer til underretninger for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Farve og udseende"</string>
- <string name="night_mode" msgid="3540405868248625488">"Nattilstand"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibrer skærmen"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Til"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Fra"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Slå automatisk til"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Skift til natfunktion alt efter stedet og tidspunktet"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Når natfunktion er slået til"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Brug mørkt tema til Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Juster farvetonen"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Juster lysstyrken"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Det mørke tema anvendes på centrale områder i Android OS, der normalt vises med lyst tema, f.eks. Indstillinger."</string>
- <string name="color_apply" msgid="9212602012641034283">"Anvend"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Bekræft indstillingerne"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Nogle farveindstillinger kan medføre, at du ikke kan bruge enheden. Klik på OK for at bekræfte disse farveindstillinger. Ellers nulstilles disse indstillinger efter ti sekunder."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batteriforbrug"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparefunktionen er ikke tilgængelig under opladning"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparefunktion"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index e6fe48c6b2ac..5a0bc1093300 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Weitere Einstellungen"</string>
<string name="notification_done" msgid="5279426047273930175">"Fertig"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g>-Benachrichtigungseinstellungen"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Farbe und Darstellung"</string>
- <string name="night_mode" msgid="3540405868248625488">"Nachtmodus"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Bildschirm kalibrieren"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"An"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Aus"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Automatisch aktivieren"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Abhängig von Standort und Tageszeit in den Nachtmodus wechseln"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Bei aktiviertem Nachtmodus"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Dunkles Design unter Android OS verwenden"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Farbton anpassen"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Helligkeit anpassen"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Das dunkle Design wird unter Android OS in allen Hauptbereichen übernommen, die normalerweise hell dargestellt werden, wie beispielsweise Einstellungen."</string>
- <string name="color_apply" msgid="9212602012641034283">"Übernehmen"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Einstellungen bestätigen"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Einige Farbeinstellungen können dazu führen, dass das Gerät nicht mehr genutzt werden kann. Klicke auf \"OK\", um diese Farbeinstellungen zu bestätigen. Anderenfalls werden diese Einstellungen in 10 Sekunden zurückgesetzt."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akkunutzung"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Der Energiesparmodus ist beim Aufladen nicht verfügbar."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Energiesparmodus"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 4c0e760a79fb..8f563307bd8c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"ΠεÏισσότεÏες Ïυθμίσεις"</string>
<string name="notification_done" msgid="5279426047273930175">"Τέλος"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Στοιχεία ελέγχου κοινοποίησης <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"ΧÏώμα και εμφάνιση"</string>
- <string name="night_mode" msgid="3540405868248625488">"ÎυχτεÏινή λειτουÏγία"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Βαθμονόμηση οθόνης"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ΕνεÏγή"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ΑνενεÏγή"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Αυτόματη ενεÏγοποίηση"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Αλλαγή σε νυχτεÏινή λειτουÏγία όπως απαιτείται βάσει τοποθεσίας και ÏŽÏας της ημέÏας"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Όταν είναι ενεÏγή η νυχτεÏινή λειτουÏγία"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"ΧÏήση ÏƒÎºÎ¿Ï„ÎµÎ¹Î½Î¿Ï Î¸Î­Î¼Î±Ï„Î¿Ï‚ για Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ΡÏθμιση απόχÏωσης"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ΡÏθμιση φωτεινότητας"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Το σκοÏÏο θέμα εφαÏμόζεται σε βασικές πεÏιοχές του λειτουÏÎ³Î¹ÎºÎ¿Ï ÏƒÏ…ÏƒÏ„Î®Î¼Î±Ï„Î¿Ï‚ Android οι οποίες συνήθως εμφανίζονται με φωτεινό θέμα, όπως οι Ρυθμίσεις."</string>
- <string name="color_apply" msgid="9212602012641034283">"ΕφαÏμογή"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Επιβεβαίωση Ïυθμίσεων"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"ΟÏισμένες Ïυθμίσεις χÏωμάτων μποÏεί να μην επιτÏέπουν τη χÏήση αυτής της συσκευής. Κάντε κλικ στην επιλογή OK για να επιβεβαιώσετε αυτές τις Ïυθμίσεις χÏωμάτων, διαφοÏετικά θα γίνει επαναφοÏά αυτών των Ïυθμίσεων μετά από 10 δευτεÏόλεπτα."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ΧÏήση της μπαταÏίας"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Η εξοικονόμηση μπαταÏίας δεν είναι διαθέσιμη κατά τη διάÏκεια της φόÏτισης"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Εξοικονόμηση μπαταÏίας"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 35307611e0f6..beb29b7a488e 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
<string name="notification_done" msgid="5279426047273930175">"Done"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> notification controls"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
- <string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrate display"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"On"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Off"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Turn on automatically"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Switch into Night Mode as appropriate for location and time of day"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"When Night Mode is on"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Use dark theme for Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Adjust tint"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Adjust brightness"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings."</string>
- <string name="color_apply" msgid="9212602012641034283">"Apply"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 35307611e0f6..beb29b7a488e 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
<string name="notification_done" msgid="5279426047273930175">"Done"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> notification controls"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
- <string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrate display"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"On"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Off"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Turn on automatically"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Switch into Night Mode as appropriate for location and time of day"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"When Night Mode is on"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Use dark theme for Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Adjust tint"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Adjust brightness"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings."</string>
- <string name="color_apply" msgid="9212602012641034283">"Apply"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 35307611e0f6..beb29b7a488e 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
<string name="notification_done" msgid="5279426047273930175">"Done"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> notification controls"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
- <string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrate display"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"On"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Off"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Turn on automatically"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Switch into Night Mode as appropriate for location and time of day"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"When Night Mode is on"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Use dark theme for Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Adjust tint"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Adjust brightness"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"The dark theme is applied to core areas of Android OS that are normally displayed in a light theme, such as Settings."</string>
- <string name="color_apply" msgid="9212602012641034283">"Apply"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirm Settings"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Some colour settings can make this device unusable. Click OK to confirm these colour settings, otherwise these settings will reset after 10 seconds."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Battery Saver not available during charging"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index de7832f5ff8d..d81f7cdd75ae 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Más opciones de configuración"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Controles de notificaciones de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Color y apariencia"</string>
- <string name="night_mode" msgid="3540405868248625488">"Modo nocturno"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrar pantalla"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Activado"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Desactivado"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Activar automáticamente"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Cambiar a modo nocturno según corresponda en relación con la ubicación y hora del día"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Cuando el modo nocturno está activado"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Usar tema oscuro para el SO Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tinte"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brillo"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"El tema oscuro se aplica en las áreas principales del SO Android que suelen mostrarse con un tema claro, como Configuración."</string>
- <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirmar la configuración"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Algunas opciones de configuración de color pueden provocar que el dispositivo quede inutilizable. Haz clic en Aceptar para confirmar estos parámetros de color. De lo contrario, la configuración se restablecerá en diez segundos."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ahorro de batería no está disponible durante la carga"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Ahorro de batería"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index e078865b3c7f..902a676bfd5b 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Más ajustes"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Controles de notificaciones de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Color y aspecto"</string>
- <string name="night_mode" msgid="3540405868248625488">"Modo nocturno"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrar pantalla"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Sí"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"No"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Activar automáticamente"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Cambiar al modo nocturno cuando proceda según la ubicación y la hora del día"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Cuando el modo nocturno esté activado"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Tema oscuro para sistema operativo Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tono"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brillo"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"El tema oscuro se aplica a las áreas principales del sistema operativo Android que normalmente se muestran con un tema claro, como la aplicación Ajustes."</string>
- <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirmar configuración"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Algunas opciones de configuración de color pueden hacer que el dispositivo no se pueda utilizar. Haz clic en Aceptar para confirmar esta configuración. Si no lo haces, se restablecerá esta configuración cuando transcurran 10 segundos."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ahorro de batería no disponible mientras se carga el dispositivo"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Ahorro de batería"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index b0b56c594138..fd5115243208 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Rohkem seadeid"</string>
<string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> märguannete juhtnupud"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Värv ja ilme"</string>
- <string name="night_mode" msgid="3540405868248625488">"Öörežiim"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Ekraani kalibreerimine"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Sees"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Väljas"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Lülita automaatselt sisse"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Lülita öörežiimile, kui see on asukoha ja kellaaja suhtes sobilik"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Kui öörežiim on sees"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Kasuta Android OS-is tumedat teemat"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Reguleeri tooni"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Reguleeri heledust"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Tume teema rakendatakse Android OS-i põhialadele, mis kuvatakse tavaliselt heleda teemaga (nt seaded)."</string>
- <string name="color_apply" msgid="9212602012641034283">"Rakenda"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Seadete kinnitamine"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Mõni värviseade ei saa seadet võib-olla kasutada. Nende värviseadete kinnitamiseks klõpsake OK, muidu lähtestatakse need seaded 10 sekundi pärast."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akukasutus"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akusäästja pole laadimise ajal saadaval"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Akusäästja"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 5308811ac875..28804015f111 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Ezarpen gehiago"</string>
<string name="notification_done" msgid="5279426047273930175">"Eginda"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren jakinarazpenak kontrolatzeko aukerak"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Kolorea eta itxura"</string>
- <string name="night_mode" msgid="3540405868248625488">"Gau modua"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibratu pantaila"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Aktibatuta"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Desaktibatuta"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Aktibatu automatikoki"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Aldatu Gau modura, kokapena eta ordua kontuan izanda"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Gau modua aktibatuta dagoenean"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Erabili gai iluna Android sistema eragilean"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Doitu kolorea"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Doitu distira"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Gai iluna Android sistema eragileko eremu nagusietan aplikatzen da. Normalean gai argian bistaratzen dira eremu horiek, adibidez, Ezarpenak atalean."</string>
- <string name="color_apply" msgid="9212602012641034283">"Aplikatu"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Berretsi ezarpenak"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Baliteke gailua kolore-ezarpen batzuekin ezin erabili izatea. Kolore-ezarpenak berresteko, sakatu Ados. Bestela, hamar segundoren buruan berrezarriko dira ezarpenak."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Bateriaren erabilera"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Bateria-aurrezlea ez dago erabilgarri gailua kargatzen ari denean"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Bateria-aurrezlea"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index cfe807885fb2..ab6b5255116e 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"تنظیمات بیشتر"</string>
<string name="notification_done" msgid="5279426047273930175">"تمام"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"کنترل‌های اعلان <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"رنگ و ظاهر"</string>
- <string name="night_mode" msgid="3540405868248625488">"حالت شب"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"درجه‌بندی نمایشگر"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"روشن"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"خاموش"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"روشن شدن خودکار"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"تغییر به حالت شب وقتی برای مکان و زمان روز مناسب است"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"وقتی حالت شب روشن است"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"â€Ø§Ø³ØªÙاده از زمینه تیره برای سیستم‌عامل Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"تنظیم سایه‌رنگ"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"تنظیم روشنایی"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"â€Ø²Ù…ینه تیره بر قسمت‌های اصلی سیستم‌عامل Android Ú©Ù‡ به‌طور معمول با زمینه روشن نشان داده می‌شوند (مثل «تنظیمات») اعمال می‌شود."</string>
- <string name="color_apply" msgid="9212602012641034283">"اعمال‌ کردن"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"تأیید تنظیمات"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"بعضی از تنظیمات رنگ می‌توانند این دستگاه را غیرقابل Ø§Ø³ØªÙØ§Ø¯Ù‡ کنند. برای تأیید این تنظیمات رنگ روی «تأیید» کلیک کنید، در غیر این صورت این تغییرات بعد از Û±Û° ثانیه بازنشانی می‌شوند."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"مصر٠باتری"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"هنگام شارژ شدن، «بهینه‌سازی باتری» در دسترس نیست"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"بهینه‌سازی باتری"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 2a0f8d4fd4db..c91d3cbf0801 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Lisäasetukset"</string>
<string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ilmoitusten hallinta"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Väri ja ulkoasu"</string>
- <string name="night_mode" msgid="3540405868248625488">"Yötila"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibroi näyttö"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Käytössä"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Pois käytöstä"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Ota käyttöön automaattisesti"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Ota yötila käyttöön sijainnin ja kellonajan perusteella."</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Kun yötila on käytössä"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Käytä tummaa teemaa käyttöjärjestelmässä"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Säädä sävytystä"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Säädä kirkkautta"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Tumma teema tulee käyttöön Android-käyttöjärjestelmän ydinosissa, kuten Asetuksissa, joissa käytetään tavallisesti vaaleaa teemaa."</string>
- <string name="color_apply" msgid="9212602012641034283">"Käytä"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Vahvista asetukset"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Jotkin väriasetukset voivat häiritä laitteen käyttöä. Vahvista uudet väriasetukset valitsemalla OK. Muussa tapauksessa aiemmat asetukset palautetaan 10 sekunnin kuluttua."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akun käyttö"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Virransäästö ei ole käytettävissä latauksen aikana."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Virransäästö"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 2cde9b72adec..5efe3a08d9eb 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Commandes de notification pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Couleur et apparence"</string>
- <string name="night_mode" msgid="3540405868248625488">"Mode Nuit"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrer l\'affichage"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Activé"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Désactivé"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Activer automatiquement"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Passer en mode Nuit en fonction de la position et de l\'heure de la journée"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Lorsque le mode Nuit est activé"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Utiliser thème foncé pour Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ajuster la coloration"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Régler la luminosité"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Le thème foncé est appliqué à des zones essentielles de la plateforme Android qui sont habituellement affichées dans un thème clair, comme les paramètres."</string>
- <string name="color_apply" msgid="9212602012641034283">"Appliquer"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirmer les paramètres"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Certains paramètres de couleurs peuvent rendre cet appareil inutilisable. Cliquez sur « OK » pour valider ces paramètres, sinon ils seront réinitialisés après 10 secondes."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Utilisation de la pile"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Le mode Économie d\'énergie n\'est pas accessible pendant la charge"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Économie d\'énergie"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 585d439eafe9..f59b456dfc33 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Commandes de notification de l\'application <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Couleur et apparence"</string>
- <string name="night_mode" msgid="3540405868248625488">"Mode Nuit"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrer l\'affichage"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Activé"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Désactivé"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Activer automatiquement"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Passer en mode Nuit en fonction de la position et de l\'heure de la journée"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Lorsque le mode Nuit est activé"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Utiliser thème foncé pour plate-forme Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ajuster la coloration"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Régler la luminosité"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Le thème foncé est appliqué à des zones essentielles de la plate-forme Android qui sont habituellement affichées dans un thème clair, telles que les paramètres."</string>
- <string name="color_apply" msgid="9212602012641034283">"Appliquer"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Vérifier les paramètres"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Certains paramètres de couleurs peuvent rendre cet appareil inutilisable. Cliquez sur \"OK\" pour valider ces paramètres, sans quoi ils seront réinitialisés après 10 secondes."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Utilisation batterie"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"L\'économiseur de batterie n\'est pas disponible lorsque l\'appareil est en charge."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Économiseur de batterie"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 6274e361c6b6..27a3eb32940e 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Máis opcións"</string>
<string name="notification_done" msgid="5279426047273930175">"Feito"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Controis de notificacións de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aspecto"</string>
- <string name="night_mode" msgid="3540405868248625488">"Modo nocturno"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrar pantalla"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Activado"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Desactivado"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Activar automaticamente"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Cambia ao modo nocturno segundo proceda para a localización e a hora do día"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Cando o modo nocturno está activado"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Usar tema escuro para SO Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Axustar ton"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Axustar brillo"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro aplícase ás áreas principais do SO Android que se mostran normalmente nun tema claro, como a configuración."</string>
- <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirmar configuración"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Algunhas opcións de configuración de cor poden facer que este dispositivo sexa inutilizable. Fai clic en Aceptar para confirmar esta configuración de cor; en caso contrario, a configuración restablecerase tras 10 segundos."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso de batería"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"A función aforro de batería non está dispoñible durante a carga"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Aforro de batería"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index a992f8e8f7a6..f13436c6f4a2 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"વધૠસેટિંગà«àª¸"</string>
<string name="notification_done" msgid="5279426047273930175">"થઈ ગયà«àª‚"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> સૂચના નિયંતà«àª°àª£à«‹"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"રંગ અને દેખાવ"</string>
- <string name="night_mode" msgid="3540405868248625488">"રાતà«àª°àª¿ મોડ"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"પà«àª°àª¦àª°à«àª¶àª¨ કૅલિબà«àª°à«‡àªŸ કરો"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ચાલà«"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"બંધ"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"આપમેળે ચાલૠકરો"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"સà«àª¥àª¾àª¨ અને દિવસના સમય માટે યોગà«àª¯ હોય તે રાતà«àª°àª¿ મોડ પર સà«àªµàª¿àªš કરો"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"જà«àª¯àª¾àª°à«‡ રાતà«àª°àª¿ મોડ ચાલૠહોય"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS માટે ઘાટી થીમનો ઉપયોગ કરો"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ટિંટ સમાયોજિત કરો"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"તેજ સમાયોજિત કરો"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"ઘાટી થીમને Android OS ના મà«àª–à«àª¯ કà«àª·à«‡àª¤à«àª°à«‹ પર લાગૠકરે છે જે સામાનà«àª¯ રીતે સેટિંગà«àª¸ જેવી લાઇટ થીમમાં પà«àª°àª¦àª°à«àª¶àª¿àª¤ કરવામાં આવે છે."</string>
- <string name="color_apply" msgid="9212602012641034283">"લાગૠકરો"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"સેટિંગà«àª¸àª¨à«€ પà«àª·à«àªŸàª¿ કરો"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"કેટલીક રંગ સેટિંગà«àª¸ આ ઉપકરણને બિનઉપયોગી બનાવી શકે છે. આ રંગ સેટિંગà«àª¸àª¨à«€ પà«àª·à«àªŸàª¿ કરવા માટે ઓકે કà«àª²àª¿àª• કરો, અનà«àª¯àª¥àª¾ 10 સેકંડ પછી આ સેટિંગà«àª¸ ફરીથી સેટ થશે."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"બૅટરી વપરાશ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ચારà«àªœàª¿àª‚ગ દરમિયાન બૅટરી બચતકરà«àª¤àª¾ ઉપલબà«àª§ નથી"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"બૅટરી બચતકરà«àª¤àª¾"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index a92dc93df810..6f4e519deade 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"और सेटिंग"</string>
<string name="notification_done" msgid="5279426047273930175">"हो गया"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> नोटिफ़िकेशन नियंतà¥à¤°à¤£"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"रंग और दिखावट"</string>
- <string name="night_mode" msgid="3540405868248625488">"रातà¥à¤°à¤¿ मोड"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"सà¥à¤•à¥à¤°à¥€à¤¨ को कैलिबà¥à¤°à¥‡à¤Ÿ करें"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"चालू"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"बंद"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"अपने आप चालू करें"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"सà¥à¤¥à¤¾à¤¨ और दिन के समय के लिठउपयà¥à¤•à¥à¤¤ रातà¥à¤°à¤¿ मोड में बदलें"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"रातà¥à¤°à¤¿ मोड के चालू होने पर"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS के लिठगहरी थीम का उपयोग करें"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"टिंट समायोजित करें"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"सà¥à¤•à¥à¤°à¥€à¤¨ की रोशनी समायोजित करें"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"गहरी थीम को Android OS के मà¥à¤–à¥à¤¯ कà¥à¤·à¥‡à¤¤à¥à¤°à¥‹à¤‚ पर लागू किया जाता है जिनà¥à¤¹à¥‡à¤‚ सामानà¥à¤¯à¤¤à¤ƒ सेटिंग जैसी हलà¥à¤•ी थीम में पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ किया जाता है."</string>
- <string name="color_apply" msgid="9212602012641034283">"लागू करें"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"सेâ€à¥‡à¤Ÿà¤¿à¤‚ग की पà¥à¤·à¥à¤Ÿà¤¿ करें"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"कà¥à¤› रंग सेटिंग इस डिवाइस को अनà¥à¤ªà¤¯à¥‹à¤—ी बना सकती हैं. इन रंग सेटिंग की पà¥à¤·à¥à¤Ÿà¤¿ करने के लिठठीक कà¥à¤²à¤¿à¤• करें, अनà¥à¤¯à¤¥à¤¾ 10 सेकंड के बाद ये सेटिंग रीसेट हो जाà¤à¤‚गी."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"बैटरी उपयोग"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"चारà¥à¤œ किठजाने के दौरान बैटरी सेवर उपलबà¥à¤§ नहीं है"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"बैटरी सेवर"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 07fc68a63af0..0a8a788a4307 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Kontrole obavijesti za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
- <string name="night_mode" msgid="3540405868248625488">"Noćni naÄin rada"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibriranje zaslona"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"UkljuÄeno"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"IskljuÄeno"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"UkljuÄi automatski"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Prebacivanje na noćni naÄin rada prema lokaciji i dobu dana"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Kada je noćni naÄin rada ukljuÄen"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Koristi tamnu temu za OS Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Prilagodi nijansu"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Prilagodi svjetlinu"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Tamna se tema primjenjuje na glavna podruÄja OS-a Android, kao Å¡to su, primjerice, postavke, koja se inaÄe prikazuju u svijetloj temi."</string>
- <string name="color_apply" msgid="9212602012641034283">"Primijeni"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Potvrdite postavke"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Neke postavke boja mogu uÄiniti ureÄ‘aj neupotrebljivim. Kliknite U redu da biste potvrdili postavke boja jer će se u suprotnom poniÅ¡titi za 10 sekundi."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Å tednja baterije nije dostupna tijekom punjenja"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Å tednja baterije"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8fa6757ad825..b4643ceae646 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"További beállítások"</string>
<string name="notification_done" msgid="5279426047273930175">"Kész"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g>-értesítések vezérlői"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Szín és megjelenés"</string>
- <string name="night_mode" msgid="3540405868248625488">"Éjszakai mód"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kijelző kalibrálása"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Bekapcsolva"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Kikapcsolva"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Automatikus bekapcsolás"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Váltás az Éjszakai módra a helynek és napszaknak megfelelően"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Amikor be van kapcsolva az Éjszakai mód"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Sötét téma használata az Android operációs rendszernél"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Színárnyalat módosítása"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Fényerő módosítása"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Sötét téma látható az Android operációs rendszer olyan alapterületeinél, amelyek normál állapotban világosan jelennek meg (például a Beállítások)."</string>
- <string name="color_apply" msgid="9212602012641034283">"Alkalmaz"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Beállítások megerősítése"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Bizonyos színbeállítások használhatatlanná tehetik ezt az eszközt. A színbeállítás megerősítéséhez kattintson az OK lehetőségre, máskülönben a rendszer 10 másodpercen belül visszaáll a korábbira."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akkumulátorhasználat"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Az Akkumulátorkímélő módot töltés közben nem lehet használni"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Akkumulátorkímélő mód"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index f1c3eba97f8f..e0311118bd7f 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Ô±ÕµÕ¬ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€"</string>
<string name="notification_done" msgid="5279426047273930175">"ÕŠÕ¡Õ¿Ö€Õ¡Õ½Õ¿ Õ§"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> Õ°Õ¡Õ¾Õ¥Õ¬Õ¾Õ¡Õ®Õ« Õ®Õ¡Õ¶Õ¸Ö‚ÖÕ¸Ö‚Õ´Õ¶Õ¥Ö€Õ« Õ¯Õ¡Õ¼Õ¡Õ¾Õ¡Ö€Õ¶Õ¥Ö€"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Ô³Õ¸Ö‚ÕµÕ¶Õ¨ Ö‡ Õ¡Ö€Õ¿Õ¡Ö„Õ«Õ¶ Õ¿Õ¥Õ½Ö„Õ¨"</string>
- <string name="night_mode" msgid="3540405868248625488">"Ô³Õ«Õ·Õ¥Ö€Õ¡ÕµÕ«Õ¶ Õ¼Õ¥ÕªÕ«Õ´"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Õ‰Õ¡ÖƒÕ¡Õ¢Õ¥Ö€Õ¥Õ¬ Õ§Õ¯Ö€Õ¡Õ¶Õ¨"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Õ„Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Ô±Õ¶Õ»Õ¡Õ¿Õ¾Õ¡Õ® Õ§"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Õ„Õ«Õ¡ÖÕ¶Õ¥Õ¬ Õ¡Õ¾Õ¿Õ¸Õ´Õ¡Õ¿ Õ¯Õ¥Ö€ÕºÕ¸Õ¾"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Ô±Õ¶ÖÕ¥Ö„ Ô³Õ«Õ·Õ¥Ö€Õ¡ÕµÕ«Õ¶ Õ¼Õ¥ÕªÕ«Õ´Õ«, Õ¥Õ©Õ¥ Õ¤Õ¡ ÕºÕ¡Õ°Õ¡Õ¶Õ»Õ¸Ö‚Õ´ Õ§ Õ¿Õ¥Õ²Õ¨ Ö‡ Ö…Ö€Õ¾Õ¡ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¨"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"ÔµÖ€Õ¢ Ô³Õ«Õ·Õ¥Ö€Õ¡ÕµÕ«Õ¶ Õ¼Õ¥ÕªÕ«Õ´Õ¨ Õ´Õ«Õ¡ÖÕ¾Õ¡Õ® Õ§"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Õ•Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¥Õ¬ Õ´Õ¸Ö‚Õ£ Õ©Õ¥Õ´Õ¡Õ¶ Android OS-Õ« Õ°Õ¡Õ´Õ¡Ö€"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¥Õ¬ Õ¥Ö€Õ¡Õ¶Õ£Õ¨"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¥Õ¬ ÕºÕ¡ÕµÕ®Õ¡Õ¼Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Õ„Õ¸Ö‚Õ£ Õ©Õ¥Õ´Õ¡Õ¶ Õ¯Õ«Ö€Õ¡Õ¼Õ¾Õ¸Ö‚Õ´ Õ§ Android OS-Õ« Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ°Õ¡Õ¿Õ¾Õ¡Õ®Õ¶Õ¥Ö€Õ« Õ¶Õ¯Õ¡Õ¿Õ´Õ¡Õ´Õ¢, Õ¸Ö€Õ¸Õ¶Ö„ Õ½Õ¸Õ¾Õ¸Ö€Õ¡Õ¢Õ¡Ö€ ÖÕ¸Ö‚ÖÕ¡Õ¤Ö€Õ¾Õ¸Ö‚Õ´ Õ¥Õ¶ Õ¢Õ¡Ö Õ©Õ¥Õ´Õ¡ÕµÕ¸Ö‚Õ´ (Ö…Ö€Õ«Õ¶Õ¡Õ¯Õ Ô¿Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€):"</string>
- <string name="color_apply" msgid="9212602012641034283">"Ô¿Õ«Ö€Õ¡Õ¼Õ¥Õ¬"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Õ€Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Ô³Õ¸Ö‚Õ¶Õ¡ÕµÕ«Õ¶ Õ¸Ö€Õ¸Õ· Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¡Ö€Õ¸Õ² Õ¥Õ¶ Õ¡ÕµÕ½ Õ½Õ¡Ö€Ö„Õ¨ Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ´Õ¡Õ¶ Õ°Õ¡Õ´Õ¡Ö€ Õ¸Õ¹ ÕºÕ«Õ¿Õ¡Õ¶Õ« Õ¤Õ¡Ö€Õ±Õ¶Õ¥Õ¬: ÕÕ¥Õ²Õ´Õ¥Ö„ Ô¼Õ¡Õ¾ Õ¯Õ¸Õ³Õ¡Õ¯Õ¨Õ Õ£Õ¸Ö‚Õ¶Õ¡ÕµÕ«Õ¶ Õ¡ÕµÕ½ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ°Õ¡Õ½Õ¿Õ¡Õ¿Õ¥Õ¬Õ¸Ö‚ Õ°Õ¡Õ´Õ¡Ö€: Õ€Õ¡Õ¯Õ¡Õ¼Õ¡Õ¯ Õ¤Õ¥ÕºÖ„Õ¸Ö‚Õ´ Õ¡ÕµÕ½ Õ¯Õ¡Ö€Õ£Õ¡Õ¾Õ¸Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ¨ Õ¯Õ¾Õ¥Ö€Õ¡Õ¯Õ¡ÕµÕ¾Õ¥Õ¶ 10 Õ¾Õ¡ÕµÖ€Õ¯ÕµÕ¡Õ¶ Õ°Õ¥Õ¿Õ¸:"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Õ„Õ¡Ö€Õ¿Õ¯Õ¸ÖÕ« Ö…Õ£Õ¿Õ¡Õ£Õ¸Ö€Õ®Õ¸Ö‚Õ´"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Õ„Õ¡Ö€Õ¿Õ¯Õ¸ÖÕ« Õ¿Õ¶Õ¿Õ¥Õ½Õ¸Ö‚Õ´Õ¨ Õ¬Õ«ÖÖ„Õ¡Õ¾Õ¸Ö€Õ´Õ¡Õ¶ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯ Õ°Õ¡Õ½Õ¡Õ¶Õ¥Õ¬Õ« Õ¹Õ§"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Õ„Õ¡Ö€Õ¿Õ¯Õ¸ÖÕ« Õ¿Õ¶Õ¿Õ¥Õ½Õ¸Ö‚Õ´"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 1678e6478aa3..13f9a15bbeec 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Setelan lainnya"</string>
<string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Kontrol notifikasi <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Warna dan tampilan"</string>
- <string name="night_mode" msgid="3540405868248625488">"Mode malam"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibrasi layar"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Aktif"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Nonaktif"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Aktifkan secara otomatis"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Beralih ke Mode Malam yang sesuai untuk lokasi dan waktu"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Saat Mode Malam aktif"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Gunakan tema gelap untuk OS Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Sesuaikan rona"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Sesuaikan kecerahan"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema gelap diterapkan ke area inti OS Android yang biasanya ditampilkan di tema terang, seperti Setelan."</string>
- <string name="color_apply" msgid="9212602012641034283">"Terapkan"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Konfirmasi setelan"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Beberapa setelan warna dapat membuat perangkat ini tidak dapat digunakan. Klik OKE untuk mengonfirmasi setelan warna ini. Jika tidak, setelan ini akan disetel ulang setelah 10 detik."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Pemakaian baterai"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Penghemat Baterai tidak tersedia selama pengisian daya"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Penghemat Baterai"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index d298eb428fdf..aabcc7642368 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Fleiri stillingar"</string>
<string name="notification_done" msgid="5279426047273930175">"Lokið"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Tilkynningastýringar <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Litur og útlit"</string>
- <string name="night_mode" msgid="3540405868248625488">"Næturstilling"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kvarða skjáinn"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Kveikt"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Slökkt"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Kveikja sjálfkrafa"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Skipta í næturstillingu í samræmi við staðsetningu og tíma dags"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Þegar kveikt er á næturstillingu"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Nota dökkt þema fyrir Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Stilla litblæ"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Stilla birtustig"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Dökka þemað er notað á þeim aðalsvæðum Android OS sem venjulega eru ljós, s.s. í stillingum."</string>
- <string name="color_apply" msgid="9212602012641034283">"Nota"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Staðfesta stillingar"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Sumar litastillingar kunna að bitna á notagildi tækisins. Veldu „à lagi“ til að staðfesta þessar litastillingar, að öðrum kosti verða litirnir endurstilltir eftir tíu sekúndur."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Rafhlöðunotkun"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Ekki er hægt að nota rafhlöðusparnað meðan á hleðslu stendur"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Rafhlöðusparnaður"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 0fd8fdc74c40..a7ce343c0cc2 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Altre impostazioni"</string>
<string name="notification_done" msgid="5279426047273930175">"Fine"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Controlli di notifica per <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Colore e aspetto"</string>
- <string name="night_mode" msgid="3540405868248625488">"Modalità notturna"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibra display"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Attiva"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Disattivata"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Attiva automaticamente"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Attiva la modalità notturna in base alla località e all\'ora del giorno"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Quando la modalità notturna è attiva"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Utilizza tema scuro per sistema Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Regola tinta"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Regola luminosità"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Il tema scuro viene applicato agli elementi fondamentali del sistema operativo Android che vengono generalmente visualizzati con un tema chiaro, ad esempio le impostazioni."</string>
- <string name="color_apply" msgid="9212602012641034283">"Applica"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Conferma le impostazioni"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Alcune impostazioni relative ai colori potrebbero rendere inutilizzabile il dispositivo. Fai clic su OK per confermare queste impostazioni; in caso contrario, le impostazioni verranno reimpostate dopo 10 secondi."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Utilizzo batteria"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Risparmio energetico non disponibile durante la ricarica"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Risparmio energetico"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 40ce8e62f188..1702926fa417 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -521,21 +521,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"הגדרות נוספות"</string>
<string name="notification_done" msgid="5279426047273930175">"סיו×"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> פקדי הודעות"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"צבע ומר××”"</string>
- <string name="night_mode" msgid="3540405868248625488">"מצב לילה"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"כיול תצוגה"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"פועל"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"כבוי"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"הפעל ×וטומטית"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"החלף למצב לילה בהת×× ×œ×ž×™×§×•× ×•×œ×©×¢×” ביו×"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"×›×שר מצב לילה מופעל"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"â€×”שתמש בעיצוב ×›×”×” למערכת ההפעלה של Android."</string>
- <string name="adjust_tint" msgid="3398569573231409878">"הת×מת גוון"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"הת×מת בהירות"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"â€×”עיצוב ×”×›×”×” מוחל על ×”×ª×—×•×ž×™× ×”×¢×™×§×¨×™×™× ×‘×ž×¢×¨×›×ª ההפעלה Android ×©×ž×•×¦×’×™× ×‘×“×¨×š כלל בעיצוב בהיר, כמו \'הגדרות\'."</string>
- <string name="color_apply" msgid="9212602012641034283">"החל"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"×ישור הגדרות"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"הגדרות צבע מסוימות עלולות להפוך ×ת המכשיר ×”×–×” לבלתי שמיש. לחץ על ×ישור כדי ל×שר ×ת הגדרות הצבע ×”×לה, ×חרת הגדרות ×לה ית×פסו ל×חר 10 שניות."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"שימוש בסוללה"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"תכונת החיסכון בסוללה ××™× ×” זמינה בעת טעינת המכשיר"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"חיסכון בסוללה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index eaeeec45e60b..eebd09f058cc 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"詳細設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完了"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"「<xliff:g id="APP_NAME">%1$s</xliff:g>ã€ã®é€šçŸ¥ã®ç®¡ç†"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"色ã¨è¡¨ç¤º"</string>
- <string name="night_mode" msgid="3540405868248625488">"夜間モード"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"表示ã®èª¿æ•´"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ON"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"OFF"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"自動的㫠ON"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"場所や時間ã«å¿œã˜ã¦å¤œé–“モードã«åˆ‡ã‚Šæ›¿ãˆã¾ã™"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"夜間モード㌠ON ã®ã¨ã"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS ã§ãƒ€ãƒ¼ã‚¯ãƒ†ãƒ¼ãƒžã‚’使用"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ティントを調整"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"明るã•を調整"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"通常ライトテーマã§è¡¨ç¤ºã•れる Android OS ã®ä¸»è¦é ˜åŸŸï¼ˆè¨­å®šãªã©ï¼‰ã«ãƒ€ãƒ¼ã‚¯ãƒ†ãƒ¼ãƒžãŒé©ç”¨ã•れã¾ã™ã€‚"</string>
- <string name="color_apply" msgid="9212602012641034283">"é©ç”¨"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"設定ã®ç¢ºèª"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"一部ã®è‰²è¨­å®šã‚’é©ç”¨ã™ã‚‹ã¨ã€ã“ã®ç«¯æœ«ã‚’使用ã§ããªããªã‚‹ã“ã¨ãŒã‚りã¾ã™ã€‚ã“ã®è‰²è¨­å®šã‚’確èªã™ã‚‹ã«ã¯ã€[OK] をクリックã—ã¦ãã ã•ã„。確èªã—ãªã„å ´åˆã€10 秒後ã«è¨­å®šã¯ãƒªã‚»ãƒƒãƒˆã•れã¾ã™ã€‚"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"電池ã®ä½¿ç”¨çжæ³"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"充電中ã¯ãƒãƒƒãƒ†ãƒªãƒ¼ セーãƒãƒ¼ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ãƒãƒƒãƒ†ãƒªãƒ¼ セーãƒãƒ¼"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 222e24b59fbf..d066bd348df9 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"დáƒáƒ›áƒáƒ¢áƒ”ბითი პáƒáƒ áƒáƒ›áƒ”ტრები"</string>
<string name="notification_done" msgid="5279426047273930175">"მზáƒáƒ“áƒáƒ"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> შეტყáƒáƒ‘ინებების მáƒáƒ áƒ—ვის სáƒáƒ¨áƒ£áƒáƒšáƒ”ბები"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"ფერი დრიერსáƒáƒ®áƒ”"</string>
- <string name="night_mode" msgid="3540405868248625488">"ღáƒáƒ›áƒ˜áƒ¡ რეჟიმი"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ეკრáƒáƒœáƒ˜áƒ¡ კáƒáƒšáƒ˜áƒ‘რáƒáƒªáƒ˜áƒ"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ჩáƒáƒ áƒ—ული"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"გáƒáƒ›áƒáƒ áƒ—ული"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"áƒáƒ•ტáƒáƒ›áƒáƒ¢áƒ£áƒ áƒáƒ“ ჩáƒáƒ áƒ—ვáƒ"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"ღáƒáƒ›áƒ˜áƒ¡ რეჟიმზე გáƒáƒ“áƒáƒ áƒ—ვრმდებáƒáƒ áƒ”áƒáƒ‘ისრდრდღე-ღáƒáƒ›áƒ˜áƒ¡ მáƒáƒœáƒáƒ™áƒ•ეთის შესáƒáƒ‘áƒáƒ›áƒ˜áƒ¡áƒáƒ“."</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"ღáƒáƒ›áƒ˜áƒ¡ რეჟიმის ჩáƒáƒ áƒ—ვისáƒáƒ¡"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS-ისთვის მუქი თემის გáƒáƒ›áƒáƒ§áƒ”ნებáƒ"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ელფერის გáƒáƒ¡áƒ¬áƒáƒ áƒ”ბáƒ"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"სიკáƒáƒ¨áƒ™áƒáƒ¨áƒ˜áƒ¡ გáƒáƒ¡áƒ¬áƒáƒ áƒ”ბáƒ"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"მუქი თემრმიესáƒáƒ“áƒáƒ’ებრAndroid OS-ის ძირითáƒáƒ“ áƒáƒ áƒ”ებს, რáƒáƒ›áƒšáƒ”ბიც, ჩვეულებრივ, ღირთემის მეშვეáƒáƒ‘ით áƒáƒ áƒ˜áƒ¡ ნáƒáƒ©áƒ•ენები. მáƒáƒ’áƒáƒšáƒ˜áƒ—áƒáƒ“, პáƒáƒ áƒáƒ›áƒ”ტრებს."</string>
- <string name="color_apply" msgid="9212602012641034283">"გáƒáƒ›áƒáƒ§áƒ”ნებáƒ"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"პáƒáƒ áƒáƒ›áƒ”ტრების დáƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბáƒ"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"ფერთრზáƒáƒ’იერთ პáƒáƒ áƒáƒ›áƒ”ტრს áƒáƒ› მáƒáƒ¬áƒ§áƒáƒ‘ილáƒáƒ‘áƒáƒ¡áƒ—áƒáƒœ მუშáƒáƒáƒ‘ის გáƒáƒ áƒ—ულებრშეუძლიáƒ. ფერთრáƒáƒ›áƒŸáƒáƒ›áƒ˜áƒœáƒ“ელი პáƒáƒ áƒáƒ›áƒ”ტრების დáƒáƒ¡áƒáƒ“áƒáƒ¡áƒ¢áƒ£áƒ áƒ”ბლáƒáƒ“, დáƒáƒáƒ¬áƒ™áƒáƒžáƒ£áƒœáƒ”თ „კáƒáƒ áƒ’ი“-ზე. წინáƒáƒáƒ¦áƒ›áƒ“ეგ შემთხვევáƒáƒ¨áƒ˜, პáƒáƒ áƒáƒ›áƒ”ტრები 10 წáƒáƒ›áƒ˜áƒ¡ შემდეგ ჩáƒáƒ›áƒáƒ˜áƒ§áƒ áƒ”ბáƒ."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ბáƒáƒ¢áƒáƒ áƒ”ის მáƒáƒ®áƒ›áƒáƒ áƒ”ბáƒ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ბáƒáƒ¢áƒáƒ áƒ”ის დáƒáƒ›áƒ–áƒáƒ’ი დáƒáƒ¢áƒ”ნვისáƒáƒ¡ მიწვდáƒáƒ›áƒ”ლიáƒ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ბáƒáƒ¢áƒáƒ áƒ”ის დáƒáƒ›áƒ–áƒáƒ’ი"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index a07513af1989..7d089508a056 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"ҚоÑымша параметрлер"</string>
<string name="notification_done" msgid="5279426047273930175">"Дайын"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> хабарландыруларды баÑқару Ñлементтері"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Ð¢Ò¯Ñ Ð¶Ó™Ð½Ðµ Ñыртқы түрі"</string>
- <string name="night_mode" msgid="3540405868248625488">"Түнгі режим"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ДиÑплейді калибрлеу"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ҚоÑулы"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Өшірулі"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Ðвтоматты түрде қоÑу"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Орынға және күн уақытына тиіÑті түнгі режимге ауыÑу"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Түнгі режим қоÑулы кезде"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android ОЖ үшін күңгірт тақырыпты пайдалану"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Реңкті реттеу"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Жарықтықты реттеу"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Күңгірт тақырып Android операциÑлық жүйеÑінің әдетте \"Параметрлер\" ÑиÑқты ашық тақырыпта көрÑетілетін негізгі аумақтарына қолданылады."</string>
- <string name="color_apply" msgid="9212602012641034283">"Қолдану"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Параметрлерді раÑтау"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Кейбір Ñ‚Ò¯Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð»ÐµÑ€Ñ– бұл құрылғыны пайдалану мүмкін ÐµÐ¼ÐµÑ ÐµÑ‚ÑƒÑ– мүмкін. Бұл Ñ‚Ò¯Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ð»ÐµÑ€Ñ–Ð½ раÑтау үшін OK түймеÑін баÑыңыз, әйтпеÑе параметрлер 10 Ñекундтан кейін Ñ‹Ñырылады."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"БатареÑны пайдалану"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ЗарÑдтау кезінде Ð‘Ð°Ñ‚Ð°Ñ€ÐµÑ Ò¯Ð½ÐµÐ¼Ð´ÐµÐ³Ñ–Ñˆ қол жетімді емеÑ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Ð‘Ð°Ñ‚Ð°Ñ€ÐµÑ Ò¯Ð½ÐµÐ¼Ð´ÐµÐ³Ñ–Ñˆ"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 1f2a98864d57..907b26fa641f 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"ការកំណážáŸ‹áž…្រើនទៀáž"</string>
<string name="notification_done" msgid="5279426047273930175">"រួចរាល់"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"អង្គគ្រប់គ្រងការជូនដំណឹង <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"ពណ៌ និងរូបរាង"</string>
- <string name="night_mode" msgid="3540405868248625488">"របៀបពáŸáž›áž™áž”់"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ការបង្ហាញក្រិáž"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"បើក"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"បិទ"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"បើក​ដោយ​ស្វáŸáž™â€‹áž”្រវážáŸ’ážáž·"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"ប្ážáž¼ážšáž‘ៅជារបៀបពáŸáž›áž™áž”់ដែលសមស្របទៅážáž¶áž˜áž‘ីកន្លែង និងពáŸáž›ážœáŸáž›áž¶"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"នៅពáŸáž›áž”ើករបៀបពáŸáž›áž™áž”់"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"ប្រើធីមងងឹážážŸáž˜áŸ’រាប់ប្រពáŸáž“្ធប្រážáž·áž”ážáŸ’ážáž·áž€áž¶ážš Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"កែសម្រួលពណ៌ព្រឿងៗ"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"កែសម្រួលពន្លឺ"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"ធីមងងឹážážáŸ’រូវបានប្រើសម្រាប់ចំណុចស្នូលនៃប្រពáŸáž“្ធប្រážáž·áž”ážáŸ’ážáž·áž€áž¶ážš Android ដែលជាទូទៅážáŸ’រូវបានបង្ហាញជាធីមភ្លឺ ដូចជាការកំណážáŸ‹áž‡áž¶ážŠáž¾áž˜áŸ”"</string>
- <string name="color_apply" msgid="9212602012641034283">"អនុវážáŸ’áž"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"បញ្ជាក់ការកំណážáŸ‹"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"ការកំណážáŸ‹áž–ណ៌មួយចំនួនអាចធ្វើឲ្យឧបករណáŸáž“áŸáŸ‡áž˜áž·áž“អាចប្រើបាន។ សូមចុច យល់ព្រម ដើម្បីបញ្ជាក់ការកំណážáŸ‹áž–ណ៌ទាំងនáŸáŸ‡ បើមិនដូច្នáŸáŸ‡áž‘áŸáž€áž¶ážšáž€áŸ†ážŽážáŸ‹áž‘ាំងនáŸáŸ‡áž“ឹងកំណážáŸ‹áž¡áž¾áž„វិញក្នុងរយៈពáŸáž› 10 វិនាទីបន្ទាប់។"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ការប្រើប្រាស់ážáŸ’ម"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"កម្មវិធីសន្សំážáŸ’មមិនអាចប្រើបានអំឡុងពáŸáž›ážŸáž¶áž€ážáŸ’មទáŸ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"កម្មវិធីសន្សំážáŸ’ម"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index ce085ce60de4..f1da673623f0 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"ಹೆಚà³à²šà²¿à²¨ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳà³"</string>
<string name="notification_done" msgid="5279426047273930175">"ಮà³à²—ಿದಿದೆ"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಅಧಿಸೂಚನೆ ನಿಯಂತà³à²°à²£à²—ಳà³"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"ಬಣà³à²£ ಮತà³à²¤à³ ಗೋಚರತೆ"</string>
- <string name="night_mode" msgid="3540405868248625488">"ರಾತà³à²°à²¿ ಮೋಡà³"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ಅಣಿಗೊಳಿಸà³à²µ ಪà³à²°à²¦à²°à³à²¶à²¨"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ಆನà³"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ಆಫà³"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"ಸà³à²µà²¯à²‚ಚಾಲಿತವಾಗಿ ಆನೠಮಾಡà³"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"ಸà³à²¥à²³ ಮತà³à²¤à³ ದಿನದ ಸಮಯಕà³à²•ೆ ಸೂಕà³à²¤à²µà²¾à²—à³à²µà²‚ತೆ ರಾತà³à²°à²¿ ಮೋಡà³â€Œ ಅನà³à²¨à³ ಬದಲಾಯಿಸಿ"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"ರಾತà³à²°à²¿ ಮೋಡà³â€Œ ಆನà³â€Œ ಆಗಿರà³à²µà²¾à²—"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS ಗೆ ಕಪà³à²ªà³ ಥೀಮà³â€Œ ಬಳಸಿ"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ಟಿಂಟà³â€Œ ಸರಿಹೊಂದಿಸà³"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ಪà³à²°à²–ರತೆಯನà³à²¨à³ ಸರಿಹೊಂದಿಸà³"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"ಕಪà³à²ªà³ ಥೀಮà³â€Œ ಅನà³à²¨à³ Android OS ನ ಕೋರà³â€Œ ಪà³à²°à²¦à³‡à²¶à²—ಳಿಗೆ ಅನà³à²µà²¯à²¿à²¸à²²à²¾à²—ಿರà³à²¤à³à²¤à²¦à³†. ಇದನà³à²¨à³ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œâ€Œà²—ಳಂತಹ ತಿಳಿಯಾದ ಥೀಮà³â€Œà²¨à²²à³à²²à²¿ ಸಾಮಾನà³à²¯à²µà²¾à²—ಿ ಪà³à²°à²¦à²°à³à²¶à²¿à²¸à²²à²¾à²—à³à²¤à³à²¤à²¦à³†."</string>
- <string name="color_apply" msgid="9212602012641034283">"ಅನà³à²µà²¯à²¿à²¸à³"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳನà³à²¨à³ ಖಚಿತಪಡಿಸಿ"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"ಕೆಲವೠಬಣà³à²£ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳೠಈ ಸಾಧನವನà³à²¨à³ ಅನà³à²ªà²¯à³à²•à³à²¤à²—ೊಳಿಸಬಹà³à²¦à³. ಈ ಬಣà³à²£ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳನà³à²¨à³ ಖಚಿತಪಡಿಸಲೠಸರಿ ಕà³à²²à²¿à²•ೠಮಾಡಿ, ಇಲà³à²²à²µà²¾à²¦à²°à³† ಈ ಸೆಟà³à²Ÿà²¿à²‚ಗà³â€Œà²—ಳನà³à²¨à³ 10 ಸೆಕೆಂಡà³à²—ಳ ನಂತರ ಮರà³à²¹à³Šà²‚ದಿಸಿ."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ಬà³à²¯à²¾à²Ÿà²°à²¿ ಬಳಕೆ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ಚಾರà³à²œà²¿à²‚ಗೠಸಮಯದಲà³à²²à²¿ ಬà³à²¯à²¾à²Ÿà²°à²¿ ಸೇವರà³â€Œâ€Œ ಲಭà³à²¯à²µà²¿à²°à³à²µà³à²¦à²¿à²²à³à²²"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ಬà³à²¯à²¾à²Ÿà²°à²¿ ಸೇವರà³â€Œâ€Œ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 8aec874feae3..b48548adcb5f 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"설정 ë”보기"</string>
<string name="notification_done" msgid="5279426047273930175">"완료"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> 알림 관리"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"ìƒ‰ìƒ ë° ëª¨ì–‘"</string>
- <string name="night_mode" msgid="3540405868248625488">"야간 모드"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ë””ìŠ¤í”Œë ˆì´ ë³´ì •"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"사용"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"사용 안함"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"ìžë™ìœ¼ë¡œ 사용 설정"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"위치 ë° ì‹œê°„ëŒ€ì— ë§žê²Œ 야간 모드로 전환"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"야간 모드 사용 ì¤‘ì¼ ë•Œ"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OSìš© ì–´ë‘ìš´ 테마 사용"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ë†ë‹´ 효과 ì¡°ì •"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ë°ê¸° ì¡°ì •"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"설정 등 ë°ì€ 테마ì—서 ì¼ë°˜ì ìœ¼ë¡œ 표시ë˜ëŠ” Android OSì˜ í•µì‹¬ ì˜ì—­ì— ì–´ë‘ìš´ 테마가 ì ìš©ë©ë‹ˆë‹¤."</string>
- <string name="color_apply" msgid="9212602012641034283">"ì ìš©"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"설정 확ì¸"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"ì¼ë¶€ ìƒ‰ìƒ ì„¤ì •ìœ¼ë¡œ ì¸í•´ ì´ ê¸°ê¸°ë¥¼ 사용하지 못할 수 있습니다. 확ì¸ì„ í´ë¦­í•˜ì—¬ ì´ëŸ¬í•œ ìƒ‰ìƒ ì„¤ì •ì„ í™•ì¸í•˜ì§€ 않으면 10ì´ˆ í›„ì— ì„¤ì •ì´ ì´ˆê¸°í™”ë©ë‹ˆë‹¤."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"배터리 사용량"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"충전하는 ë™ì•ˆ 배터리 세ì´ë²„는 사용할 수 없습니다."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"배터리 세ì´ë²„"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index cc882764d7b9..baed26f1f346 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Дагы жөндөөлөр"</string>
<string name="notification_done" msgid="5279426047273930175">"Бүттү"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> ÑÑкертмеÑин башкаруу каражаттары"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"ТүÑÒ¯ жана көрүнүшү"</string>
- <string name="night_mode" msgid="3540405868248625488">"Түнкү режим"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ДиÑплейди калибрлөө"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Күйүк"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Өчүк"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Ðвтоматтык түрдө күйгүзүү"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Жайгашкан жерге жана убакытка жараша түнкү режимге которулуңуз"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Түнкү режим күйүп турганда"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS үчүн караңгы тема колдонуу"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Кошумча түÑүн тууралоо"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Жарыктыгын тууралоо"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Ðдатта жарык темада көрÑөтүлүүчү Android тутумунун негизги Ñлементтерине (Жөндөөлөр ÑÑ‹Ñктуу) колдонула турган караңгы тема."</string>
- <string name="color_apply" msgid="9212602012641034283">"Колдонуу"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Жөндөөлөрдү ыраÑтоо"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Ðйрым Ñ‚Ò¯Ñ Ð¶Ó©Ð½Ð´Ó©Ó©Ð»Ó©Ñ€Ò¯ бул түзмөктү ÐºÐ¾Ð»Ð´Ð¾Ð½ÑƒÐ»Ð³ÑƒÑ ÐºÑ‹Ð»Ñ‹Ð¿ коюшу мүмкүн. Бул Ñ‚Ò¯Ñ Ð¶Ó©Ð½Ð´Ó©Ó©Ð»Ó©Ñ€Ò¯Ð½ ыраÑтоо үчүн OK баÑкычын чыкылдатыңыз, болбоÑо бул жөндөөлөр 10 Ñекунддан кийин баштапкы абалына келтирилет."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Ð‘Ð°Ñ‚Ð°Ñ€ÐµÑ ÐºÐ¾Ð»Ð´Ð¾Ð½ÑƒÐ»ÑƒÑˆÑƒ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"БатареÑны үнөмдөгүч түзмөк кубатталып жатканда иштебейт"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"БатареÑны үнөмдөгүч"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index f692329129a4..75fa023267d7 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"​àºàº²àº™â€‹àº•ັ້ງ​ຄ່າ​ເພີ່ມ​ເຕີມ"</string>
<string name="notification_done" msgid="5279426047273930175">"ສຳເລັດà»àº¥à»‰àº§"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"àºàº²àº™àº„ວບຄຸມàºàº²àº™à»àºˆà»‰àº‡à»€àº•ືອນ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"ສີ à»àº¥àº° ລັàºàºªàº°àº™àº°"</string>
- <string name="night_mode" msgid="3540405868248625488">"ໂà»àº”àºàº²àº‡àº„ືນ"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ປັບໜ້າຈà»"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ເປີດ"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ປິດ"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"ເປີດ​ໃຊ້​ອັດ​ຕະ​ໂນ​ມັດ"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"ສະລັບໄປໃຊ້ໂà»àº”àºàº²àº‡àº„ືນຕາມຄວາມເà»àº²àº°àºªàº»àº¡àºàº±àºšàºªàº°àº–ານທີ່ à»àº¥àº° ເວລາໃນà»àº•່ລະມື້"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"ເມື່ອເປີດໂà»àº”àºàº²àº‡àº„ືນ"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"ໃຊ້ຮູບà»àºšàºšàºªàºµàºªàº±àº™à»àºšàºšàº¡àº·àº”ສຳລັບ Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ປັບà»àº•່ງໂທນສີ"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ປັບà»àº•່ງຄວາມສະຫວ່າງ"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"ຮູບà»àºšàºšàºªàºµàºªàº±àº™àº¡àº·àº”à»àº¡à»ˆàº™àº™àº³à»ƒàºŠà»‰àºàº±àºšàºžàº·à»‰àº™àº—ີ່ຫຼັàºàº‚ອງ Android OS ທີ່ປົàºàºàº°àº•ິຈະສະà»àº”ງເປັນຮູບà»àºšàºšàºªàºµàºªàº±àº™à»àºˆà»‰àº‡ ເຊັ່ນ: àºàº²àº™àº•ັ້ງຄ່າ."</string>
- <string name="color_apply" msgid="9212602012641034283">"ນຳໃຊ້"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"ຢືນ​ຢັນ​àºàº²àº™â€‹àº•ັ້ງ​ຄ່າ"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"ບາງàºàº²àº™àº•ັ້ງຄ່າສີສາມາດເຮັດໃຫ້ອຸປະàºàº­àº™àº™àºµà»‰àºšà»à»ˆàºªàº²àº¡àº²àº”ໃຊ້ໄດ້. ຄລິຠຕົàºàº¥àº»àº‡ ເພື່ອຢືນຢັນàºàº²àº™àº•ັ້ງຄ່າສີເຫຼົ່ານີ້, ຖ້າບà»à»ˆàº”ັ່ງນັ້ນ àºàº²àº™àº•ັ້ງຄ່າເຫຼົ່ານີ້ຈະຕັ້ງຄືນໃà»à»ˆ ຫຼັງຈາຠ10 ວິນາທີ."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"àºàº²àº™à»ƒàºŠà»‰à»àºšàº±àº”ເຕີຣີ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ຕົວປະຢັດà»àºšàº±àº”ເຕີຣີບà»à»ˆàº¡àºµà»ƒàº«à»‰àº™àº³à»ƒàºŠà»‰à»ƒàº™àº¥àº°àº«àº§à»ˆàº²àº‡àºàº²àº™àºªàº²àº"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ຕົວປະຢັດ​à»àºšàº±àº”ເຕີຣີ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index fef707719bad..fa843c6c95f2 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -521,21 +521,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Daugiau nustatymų"</string>
<string name="notification_done" msgid="5279426047273930175">"Atlikta"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ pranešimų valdikliai"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Spalva ir išvaizda"</string>
- <string name="night_mode" msgid="3540405868248625488">"Naktinis režimas"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibruoti ekranÄ…"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Įjungta"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Išjungta"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Įjungti automatiškai"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Perjungti į naktinį režimą pagal vietovę ir dienos laiką"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Kai įjungtas naktinis režimas"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Naudoti tamsią „Android“ OS temą"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Koreguoti atspalvį"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Koreguoti šviesumą"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"PagrindinÄ—ms „Android“ OS dalims, kurioms paprastai taikoma Å¡viesi tema, pvz., skilÄiai „Nustatymai“, bus pritaikyta tamsi tema."</string>
- <string name="color_apply" msgid="9212602012641034283">"Taikyti"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Nustatymų patvirtinimas"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Dėl kai kurių spalvų nustatymų įrenginys gali būti netinkamas naudoti. Spustelėkite „Gerai“, kad patvirtintumėte šiuos spalvų nustatymus. Kitaip šie nustatymai bus nustatyti iš naujo po 10 sekundžių."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akum. energ. vartoj."</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akumuliatoriaus tausojimo priemonė nepasiekiama įkraunant"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Akumuliatoriaus tausojimo priemonÄ—"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e977e1c5b88c..4b98e29ef109 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Citi iestatījumi"</string>
<string name="notification_done" msgid="5279426047273930175">"Gatavs"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> paziņojumu vadīklas"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"KrÄsas un izskats"</string>
- <string name="night_mode" msgid="3540405868248625488">"Nakts režīms"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"EkrÄna kalibrēšana"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Ieslēgts"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Izslēgts"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"IeslÄ“gt automÄtiski"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"PÄrslÄ“gt uz nakts režīmu atbilstoÅ¡i atraÅ¡anÄs vietai un diennakts laikam"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Ja ir ieslēgts nakts režīms"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Izmantot tumÅ¡o motÄ«vu operÄ“tÄjsistÄ“mai Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Regulēt toni"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Regulēt spilgtumu"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"TumÅ¡ais motÄ«vs tiek lietots galvenajos operÄ“tÄjsistÄ“mas Android elementos, kas parasti tiek rÄdÄ«ti ar gaiÅ¡u motÄ«vu, piemÄ“ram, lietotnÄ“ IestatÄ«jumi."</string>
- <string name="color_apply" msgid="9212602012641034283">"Lietot"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"IestatÄ«jumu apstiprinÄÅ¡ana"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Noteiktu krÄsu iestatÄ«jumu dēļ šī ierÄ«ce var kļūt nelietojama. Lai apstiprinÄtu Å¡os krÄsu iestatÄ«jumus, noklikšķiniet uz Labi. Ja to neizdarÄ«siet, pÄ“c 10 sekundÄ“m Å¡ie iestatÄ«jumi tiks atiestatÄ«ti."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Akumulatora lietojums"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Akumulatora jaudas taupīšanas režīms uzlÄdes laikÄ nav pieejams."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Akumulatora jaudas taupīšanas režīms"</string>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index bc7a1c1af609..df05c0681f57 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Повеќе поÑтавки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Контроли за извеÑтувања на <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Боја и изглед"</string>
- <string name="night_mode" msgid="3540405868248625488">"Ðоќен режим"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Калибрирај го екранот"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Вклучено"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ИÑклучено"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Вклучи автоматÑки"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Префрли во Ðоќен режим како што е Ñоодветно за локацијата и времето во денот"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Кога Ðоќниот режим е вклучен"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"КориÑтете ја темната тема за ОС Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ПриÑпоÑоби ја бојата"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ПриÑпоÑоби ја оÑветленоÑта"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Темната тема Ñе применува на оÑновните облаÑти на Android OS што обично Ñе прикажуваат во Ñветла тема, како ПоÑтавки."</string>
- <string name="color_apply" msgid="9212602012641034283">"Примени"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Потврдете ги поÑтавките"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Ðекои поÑтавки на боите може да го направат уредот неупотреблив. Кликнете на Во ред за да ги потврдите овие поÑтавки на боите, инаку тие поÑтавки ќе Ñе реÑетираат по 10 Ñекунди."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"КориÑтење батерија"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Штедачот на батерија не е доÑтапен при полнење"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Штедач на батерија"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index c78e2e399cec..db2f30acb2ec 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"കൂടàµà´¤àµ½ à´•àµà´°à´®àµ€à´•രണം"</string>
<string name="notification_done" msgid="5279426047273930175">"പൂർതàµà´¤à´¿à´¯à´¾à´¯à´¿"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> അറിയിപàµà´ªàµ നിയനàµà´¤àµà´°à´£à´™àµà´™àµ¾"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"വർണàµà´£à´µàµà´‚ രൂപഭാവവàµà´‚"</string>
- <string name="night_mode" msgid="3540405868248625488">"നൈറàµà´±àµ മോഡàµ"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"à´¡à´¿à´¸àµà´ªàµà´²àµ‡ കാലിബàµà´°àµ‡à´±àµà´±àµà´šàµ†à´¯àµà´¯àµà´•"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ഓൺ"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"à´“à´«àµ"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"à´¸àµà´µà´¯à´®àµ‡à´µ ഓണാകàµà´•àµà´•"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"ലൊകàµà´•േഷനàµà´‚ ദിവസതàµà´¤à´¿à´²àµ† സമയതàµà´¤à´¿à´¨àµà´‚ à´…à´¨àµà´¯àµ‹à´œàµà´¯à´®à´¾à´¯ തരതàµà´¤à´¿àµ½ നൈറàµà´±àµ മോഡിലേകàµà´•ൠസàµà´µà´¿à´šàµà´šàµà´šàµ†à´¯àµà´¯àµà´•"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"നൈറàµà´±àµ മോഡൠഓണായിരികàµà´•àµà´®àµà´ªàµ‹àµ¾"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS-à´¨àµà´³àµà´³ ഇരàµà´£àµà´Ÿ തീം ഉപയോഗികàµà´•àµà´•"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"à´Ÿà´¿à´¨àµà´±àµ à´•àµà´°à´®à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´•"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"തെളിചàµà´šà´‚ à´•àµà´°à´®à´ªàµà´ªàµ†à´Ÿàµà´¤àµà´¤àµà´•"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"à´•àµà´°à´®àµ€à´•രണം പോലെയàµà´³àµà´³, ഒരൠലൈറàµà´±àµ തീമിൽ സാധാരണ ഗതിയിൽ à´ªàµà´°à´¦àµ¼à´¶à´¿à´ªàµà´ªà´¿à´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´¨àµà´¨ Android OS-à´¨àµà´±àµ† à´…à´Ÿà´¿à´¸àµà´¥à´¾à´¨ ഇടങàµà´™à´³à´¿à´²àµ‡à´•àµà´•àµ, ഇരàµà´£àµà´Ÿ തീം à´ªàµà´°à´¯àµ‹à´—à´¿à´•àµà´•àµà´¨àµà´¨àµ."</string>
- <string name="color_apply" msgid="9212602012641034283">"ബാധകമാകàµà´•àµà´•"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"à´•àµà´°à´®àµ€à´•രണം à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•àµà´•"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"à´šà´¿à´² വർണàµà´£ à´•àµà´°à´®àµ€à´•രണതàµà´¤à´¿à´¨àµ à´ˆ ഉപകരണതàµà´¤àµ† ഉപയോഗരഹിതമാകàµà´•ാനാകàµà´‚. à´ˆ വർണàµà´£ à´•àµà´°à´®àµ€à´•രണം à´¸àµà´¥à´¿à´°àµ€à´•à´°à´¿à´•àµà´•àµà´¨àµà´¨à´¤à´¿à´¨àµ à´¶à´°à´¿ à´Žà´¨àµà´¨à´¤à´¿àµ½ à´•àµà´²à´¿à´•àµà´•àµà´šàµ†à´¯àµà´¯àµà´•, à´…à´²àµà´²àµ†à´™àµà´•ിൽ 10 സെകàµà´•ൻഡിനൠശേഷം à´ˆ à´•àµà´°à´®àµ€à´•രണം à´ªàµà´¨à´ƒà´•àµà´°à´®àµ€à´•à´°à´¿à´•àµà´•à´ªàµà´ªàµ†à´Ÿàµà´‚."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ബാറàµà´±à´±à´¿ ഉപയോഗം"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ചാർജàµà´šàµ†à´¯àµà´¯àµà´¨àµà´¨ സമയതàµà´¤àµ ബാറàµà´±à´±à´¿ സേവർ ലഭàµà´¯à´®à´²àµà´²"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ബാറàµà´±à´±à´¿ സേവർ"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 0a24ae128d44..a878c7ff15ed 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"БуÑад тохиргоо"</string>
<string name="notification_done" msgid="5279426047273930175">"ДууÑÑан"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> мÑдÑгдлийн Ñ…Ñналт"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Өнгө, харагдах байдал"</string>
- <string name="night_mode" msgid="3540405868248625488">"Шөнийн горим"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ДÑлгÑцийг тохируулах"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ИдÑвхтÑй"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ИдÑвхгүй"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Ðвтоматаар аÑаах"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Тухайн өдрийн байршил, цагийн тохиромжтой үед Шөнийн горимд шилжүүлÑÑ…"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Шөнийн горим идÑвхтÑй үед"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android-н үйлдлийн ÑиÑтемд бараан загварыг ашиглах"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Өнгөний нÑгтаршилыг тохируулах"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ГÑÑ€Ñлтүүлгийг тохируулах"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Тохиргоо зÑÑ€Ñг тогтмол цайвар загварт харуулдаг Android үйлдлийн ÑиÑтемийн гол Ñ…ÑÑгийг бараан загварт харуулна."</string>
- <string name="color_apply" msgid="9212602012641034283">"Ð¥ÑÑ€ÑгжүүлÑÑ…"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Тохиргоог баталгаажуулах"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Зарим өнгөний тохиргоо ÑÐ½Ñ Ñ‚Ó©Ñ…Ó©Ó©Ñ€Ó©Ð¼Ð¶Ð¸Ð¹Ð³ ашиглах боломжгүй болгож болзошгүй. OK товчлуурыг дарж ÑдгÑÑÑ€ өнгөний тохиргоог зөвшөөрөхгүй бол ÑÐ½Ñ Ñ‚Ð¾Ñ…Ð¸Ñ€Ð³Ð¾Ð¾ нь 10 Ñекундын дараа шинÑчлÑгдÑÑ… болно."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ТÑжÑÑл ашиглалт"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ЦÑнÑглÑÑ… үед Ñ‚ÑжÑÑл Ñ…ÑмнÑгч ажиллахгүй"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ТÑжÑÑл Ñ…ÑмнÑгч"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 525becefcd43..0abc667228ea 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंगà¥à¤œ"</string>
<string name="notification_done" msgid="5279426047273930175">"पूरà¥à¤£ à¤à¤¾à¤²à¥‡"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> सूचना नियंतà¥à¤°à¤£à¥‡"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"रंग आणि सà¥à¤µà¤°à¥‚प"</string>
- <string name="night_mode" msgid="3540405868248625488">"रातà¥à¤° मोड"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"पà¥à¤°à¤¦à¤°à¥à¤¶à¤¨à¤¾à¤šà¥‡ मापन करा"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"चालू"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"बंद"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"सà¥à¤µà¤¯à¤‚चलितपणे चालू करा"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"सà¥à¤¥à¤¾à¤¨ आणि दिवसाचà¥à¤¯à¤¾ वेळेसाठी योगà¥à¤¯ असलà¥à¤¯à¤¾à¤¨à¥à¤¸à¤¾à¤° रातà¥à¤° मोड मधà¥à¤¯à¥‡ सà¥à¤µà¤¿à¤š करा"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"रातà¥à¤° मोड चालू असताना"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS साठी गडद थीमचा वापर करा"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"रंगाची छटा समायोजित करा"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"चकाकी समायोजित करा"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"सेटिंगà¥à¤œ सारखà¥à¤¯à¤¾ पà¥à¤°à¤•ाश थीममधà¥à¤¯à¥‡ पà¥à¤°à¤¦à¤°à¥à¤¶à¤¿à¤¤ केलà¥à¤¯à¤¾ जाणाऱà¥à¤¯à¤¾ Android OS चà¥à¤¯à¤¾ मà¥à¤–à¥à¤¯ कà¥à¤·à¥‡à¤¤à¥à¤°à¤¾à¤‚वर गडद थीम लागू केली जाते."</string>
- <string name="color_apply" msgid="9212602012641034283">"लागू करा"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"सेटिंगà¥à¤œà¤šà¥€ पà¥à¤·à¥à¤Ÿà¥€ करा"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"काही रंग सेटिंगà¥à¤œ या डिवà¥à¤¹à¤¾à¤‡à¤¸à¤²à¤¾ निरà¥à¤ªà¤¯à¥‹à¤—ी करू शकतात. या रंग सेटिंगà¥à¤œà¤šà¥€ पà¥à¤·à¥à¤Ÿà¥€ करणà¥â€à¤¯à¤¾à¤¸à¤¾à¤ à¥€ ठीक आहे दाबा अनà¥à¤¯à¤¥à¤¾ या सेटिंगà¥à¤œ 10 सेकंदांनंतर रीसेट होतील."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"बॅटरी वापर"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"चारà¥à¤œ करताना बॅटरी बचतकरà¥à¤¤à¤¾ उपलबà¥à¤§ नाही"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"बॅटरी बचतकरà¥à¤¤à¤¾"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 4c55344dd0ef..fa5ba0a56671 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Lagi tetapan"</string>
<string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Kawalan pemberitahuan <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Warna dan penampilan"</string>
- <string name="night_mode" msgid="3540405868248625488">"Mod malam"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Tentukur paparan"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Hidup"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Mati"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Hidupkan secara automatik"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Beralih ke Mod Malam sebagaimana sesuai untuk lokasi dan masa"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Apabila Mod Malam dihidupkan"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Gunakan tema gelap untuk OS Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Laraskan seri warna"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Laraskan kecerahan"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema gelap digunakan pada bahagian teras OS Android yang biasanya dipaparkan dalam tema cerah, seperti Tetapan."</string>
- <string name="color_apply" msgid="9212602012641034283">"Gunakan"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Sahkan tetapan"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Sesetengah tetapan warna boleh menjadikan peranti ini tidak dapat digunakan. Klik OK untuk mengesahkan tetapan warna ini, jika tidak, tetapan ini akan ditetapkan semula selepas 10 saat."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Penggunaan bateri"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Penjimat Bateri tidak tersedia semasa mengecas"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Penjimat Bateri"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index b5ce1e67784f..5f7478834eb0 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -24,7 +24,7 @@
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"စာရင်းမှ ဖယ်မည်"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"အက်ပ်အá€á€»á€€á€ºá€¡á€œá€€á€ºá€™á€»á€¬á€¸"</string>
<string name="status_bar_no_recent_apps" msgid="7374907845131203189">"သင်á မကြာမီက မျက်နှာပြင်များ ဒီမှာ ပေါ်လာကြမည်"</string>
- <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"လá€á€ºá€á€œá€±á€¬á€¡á€•်ပလီကေးရှင်းများအား ဖယ်ထုá€á€ºá€™á€Šá€º"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"လá€á€ºá€á€œá€±á€¬á€¡á€€á€ºá€•်များအား ပယ်ရန်"</string>
<plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
<item quantity="other">á€á€¼á€¯á€¶á€€á€¼á€Šá€·á€ºá€™á€¾á€¯á€‘ဲမှ မျက်နှာပြင် %d á€á€¯</item>
<item quantity="one">á€á€¼á€¯á€¶á€€á€¼á€Šá€·á€ºá€™á€¾á€¯á€‘ဲမှ မျက်နှာပြင် 1 á€á€¯</item>
@@ -65,7 +65,7 @@
<string name="usb_debugging_always" msgid="303335496705863070">"ဒီကွန်ပျူá€á€¬á€™á€¾ အမြဲá€á€½á€„့်ပြုရန်"</string>
<string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"USB အမှားပြင်ဆင်á€á€¼á€„်း á€á€½á€„့်မပြုပါ"</string>
<string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"ဤစက်ပစ္စည်းသို့ လက်ရှိá€á€„်ရောက်ထားသည့် အသုံးပြုသူသည် USB အမှားပြင်ဆင်á€á€¼á€„်း ဖွင့်áမရပါዠဤအင်္ဂါရပ်ကို အသုံးပြုရန်አကျေးဇူးပြုá ကြီးကြပ်သူသို့ပြောင်းပါá‹"</string>
- <string name="compat_mode_on" msgid="6623839244840638213">"ဖန်သားပြင်ပြည့် á€á€»á€²á€·á€á€¼á€„်း"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"ဇူးမ်အပြည့်ဆွဲá€á€¼á€„်း"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"ဖန်သားပြင်အပြည့်ဆန့်á€á€¼á€„်း"</string>
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"ဖန်သားပြင်ဓါá€á€ºá€•ုံသိမ်းစဉ်.."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"ဖန်သားပြင်ဓါá€á€ºá€•ုံရိုက်á€á€¼á€„်းအား သိမ်းဆည်းပါမည်"</string>
@@ -97,8 +97,8 @@
<string name="camera_label" msgid="7261107956054836961">"ကင်မရာ ဖွင့်ရန်"</string>
<string name="recents_caption_resize" msgid="3517056471774958200">"အလုပ်သစ်စီစဥ်မှုကို ရွေးပါá‹"</string>
<string name="cancel" msgid="6442560571259935130">"မလုပ်á€á€±á€¬á€·"</string>
- <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"အံ့á€á€„်သောá€á€»á€¯á€¶á€·á€á€»á€²á€·á€á€œá€¯á€á€º"</string>
- <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ဖန်သားပြင်ပေါ်á€á€½á€„် အသေးမှအကြီးသို့á€á€»á€²á€·á€á€¼á€„်း"</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"အံá€á€„်á€á€½á€„်ကျ ဇူးမ်á€á€œá€¯á€á€º"</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ဖန်သားပြင်ပေါ်á€á€½á€„် အသေးမှအကြီးသို့ ဇူးမ်ဆွဲá€á€¼á€„်း"</string>
<string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ဘလူးá€á€¯á€žá€ºá€á€»á€­á€á€ºá€†á€€á€ºá€‘ားမှု"</string>
<string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"ဘလူးá€á€¯á€žá€ºá€á€»á€­á€á€ºá€†á€€á€ºá€™á€¾á€¯á€•ြá€á€ºá€á€±á€¬á€€á€ºá€žá€Šá€º"</string>
<string name="accessibility_no_battery" msgid="358343022352820946">"ဘက်ထရီမရှိပါá‹"</string>
@@ -171,10 +171,10 @@
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
<string name="accessibility_work_mode" msgid="2478631941714607225">"အလုပ် မုဒ်"</string>
- <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>ကို ပယ်လိုက်ရန်"</string>
+ <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ကို ပယ်ရန်"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ထုá€á€ºá€‘ားသည်á‹"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"မကြာသေးမီက အပလီကေးရှင်းများအားလုံး ဖယ်ထုá€á€ºá€•ြီးပါပြီá‹"</string>
- <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> အက်ပ်အá€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯ ဖွင့်ပါá‹"</string>
+ <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> အပလီကေးရှင်းအá€á€»á€€á€ºá€¡á€œá€€á€ºá€€á€­á€¯ ဖွင့်ပါá‹"</string>
<string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g>ကို စá€á€„်နေသည်á‹"</string>
<string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g><xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"အကြောင်းကြားá€á€»á€€á€ºá€€á€­á€¯á€–ယ်ရှားပြီး"</string>
@@ -320,7 +320,7 @@
<string name="quick_settings_work_mode_label" msgid="6244915274350490429">"အလုပ် မုဒ်"</string>
<string name="recents_empty_message" msgid="808480104164008572">"မကြာမီကဖွင့်ထားသည်များ မရှိပါ"</string>
<string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"သင်အားလုံးကို ရှင်းလင်းပြီးပါပြီ"</string>
- <string name="recents_app_info_button_label" msgid="2890317189376000030">"အက်ပ်အင်ဖို"</string>
+ <string name="recents_app_info_button_label" msgid="2890317189376000030">"အပလီကေးရှင်းအင်ဖို"</string>
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"မျက်နှာပြင် ပင်ထိုးမှု"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ရှာဖွေရန်"</string>
<string name="recents_launch_error_message" msgid="2969287838120550506">"<xliff:g id="APP">%s</xliff:g> ကို မစနိုင်ပါá‹"</string>
@@ -450,7 +450,7 @@
<string name="volume_stream_content_description_unmute" msgid="4436631538779230857">"%1$sዠအသံပြန်ဖွင့်ရန် á€á€­á€¯á€·á€•ါá‹"</string>
<string name="volume_stream_content_description_vibrate" msgid="1187944970457807498">"%1$sá‹ á€á€¯á€”်á€á€«á€™á€¾á€¯á€€á€­á€¯ သá€á€ºá€™á€¾á€á€ºá€›á€”် á€á€­á€¯á€·á€•ါዠအများသုံးစွဲနိုင်မှု á€á€”်ဆောင်မှုများကို အသံပိá€á€ºá€‘ားနိုင်ပါသည်á‹"</string>
<string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$sዠအသံပိá€á€ºá€›á€”် á€á€­á€¯á€·á€•ါዠအများသုံးစွဲနိုင်မှု á€á€”်ဆောင်မှုများကို အသံပိá€á€ºá€‘ားနိုင်ပါသည်á‹"</string>
- <string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"အသံအá€á€­á€¯á€¸á€¡á€œá€»á€¾á€±á€¬á€·á€á€œá€¯á€á€º %s ပြသထားပါသည်ዠပယ်ဖျက်ရန် ပွá€á€ºá€†á€½á€²á€•ါá‹"</string>
+ <string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"အသံအá€á€­á€¯á€¸á€¡á€œá€»á€¾á€±á€¬á€·á€á€œá€¯á€á€º %s ပြသထားပါသည်ዠပယ်ရန် အပေါ်သို့ပွá€á€ºá€†á€½á€²á€•ါá‹"</string>
<string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"အသံအá€á€­á€¯á€¸á€¡á€œá€»á€¾á€±á€¬á€·á€á€œá€¯á€á€ºá€™á€»á€¬á€¸á€€á€­á€¯ á€á€¾á€€á€ºá€‘ားပါသည်"</string>
<string name="system_ui_tuner" msgid="708224127392452018">"စနစ် UI ဖမ်းစက်"</string>
<string name="show_battery_percentage" msgid="5444136600512968798">"မြုá€á€ºá€‘ားသည့် ဘက်ထရီ ရာá€á€­á€¯á€„်နှုန်းကို ပြပါ"</string>
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"နောက်ထပ် ဆက်á€á€„်များ"</string>
<string name="notification_done" msgid="5279426047273930175">"ပြီးပါပြီ"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> အကြောင်းကြားá€á€»á€€á€º ထိန်းá€á€»á€¯á€•်မှုများ"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"အရောင်နှင့် အပြင်အဆင်"</string>
- <string name="night_mode" msgid="3540405868248625488">"ညသုံးမုဒ်"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ပြသမှုအá€á€»á€­á€”်အဆကို ညှိပါ"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ဖွင့်ပါ"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ပိá€á€ºá€•ါ"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"အလိုအလျောက် ဖွင့်ပါ"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"á€á€Šá€ºá€”ေရာနှင့် á€á€…်ရက်á€á€¬á€¡á€á€»á€­á€”်နှင့် သင့်လျော်သလို ညသုံးမုဒ်သို့ ပြောင်းပါ"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"ညသုံမုဒ်ဖွင့်ထားစဉ်"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS အá€á€½á€€á€ºá€¡á€›á€±á€¬á€„်ရင့်အပြင်အဆင်ကို သုံးပါ"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"အရောင်မွဲမှုကို á€á€»á€­á€”်ပါ"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"အလင်းအမှောင်á€á€»á€­á€”်ပါ"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"အရောင်ရင့်အပြင်အဆင်သည် ဆက်á€á€„်များကဲ့သို့ ပုံမှန်အားဖြင့် အရောင်ဖျော့အပြင်အဆင်အဖြစ်ရှိသည့် Android OS áအဓိကနေရာများကို ပြောင်းလဲပေးပါသည်á‹"</string>
- <string name="color_apply" msgid="9212602012641034283">"အသုံးပြုပါ"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"ဆက်á€á€„်များကို အá€á€Šá€ºá€•ြုပါ"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"အá€á€»á€­á€¯á€·á€žá€±á€¬ အရောင်ဆက်á€á€€á€ºá€™á€»á€¬á€¸á€€ ဤကိရိယာကို သုံးမရအောင် လုပ်ပစ်နိုင်ပါသည်ዠဤအရောင် ဆက်á€á€„်များကို အá€á€Šá€ºá€•ြုရန် အိုကေကို နှိပ်ပါአသို့မဟုá€á€º ဤဆက်á€á€„်များကို áဠစက္ကန့် အကြာá€á€½á€„် ပြန်ညှိလိုက်ပါမည်á‹"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ဘက်ထရီ အသုံးပြုမှု"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"အားသွင်းနေá€á€»á€­á€”်မှာ Battery Saver ကို သုံးမရပါ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Battery Saver"</string>
@@ -556,7 +541,7 @@
<string name="keyboard_key_media_fast_forward" msgid="3849417047738200605">"ရှေ့သို့ရစ်ပါ"</string>
<string name="keyboard_key_page_up" msgid="5654098530106845603">"အပေါ်စာမျက်နှာသို့သွားပါ"</string>
<string name="keyboard_key_page_down" msgid="8720502083731906136">"အောက်စာမျက်နှာသို့သွားပါ"</string>
- <string name="keyboard_key_forward_del" msgid="1391451334716490176">"ဖျက်ပါ"</string>
+ <string name="keyboard_key_forward_del" msgid="1391451334716490176">"ဖျက်ရန်"</string>
<string name="keyboard_key_move_home" msgid="2765693292069487486">"ပင်မ"</string>
<string name="keyboard_key_move_end" msgid="5901174332047975247">"ပြီးပါပြီ"</string>
<string name="keyboard_key_insert" msgid="8530501581636082614">"ထည့်ပါ"</string>
@@ -600,7 +585,7 @@
<string name="menu_ime" msgid="4943221416525250684">"မန်နယူး / ကီးဘုá€á€ºá€•ြောင်းစနစ်"</string>
<string name="select_button" msgid="1597989540662710653">"ပေါင်းထည့်ရန် á€á€œá€¯á€á€ºá€€á€­á€¯á€›á€½á€±á€¸á€•ါ"</string>
<string name="add_button" msgid="4134946063432258161">"á€á€œá€¯á€á€ºá€•ေါင်းထည့်ပါ"</string>
- <string name="save" msgid="2311877285724540644">"သိမ်းဆည်းပါ"</string>
+ <string name="save" msgid="2311877285724540644">"သိမ်းရန်"</string>
<string name="reset" msgid="2448168080964209908">"ပြန်လည်သá€á€ºá€™á€¾á€á€ºá€›á€”်"</string>
<string name="no_home_title" msgid="1563808595146071549">"ပင်မá€á€œá€¯á€á€ºá€™á€á€½á€±á€·á€•ါ"</string>
<string name="no_home_message" msgid="5408485011659260911">"ဤစက်ပစ္စည်းကိုရွှေ့လျားနိုင်ရန် ပင်မá€á€œá€¯á€á€º လိုအပ်ပါသည်ዠမသိမ်းဆည်းမီ ပင်မá€á€œá€¯á€á€ºá€€á€­á€¯ ပေါင်းထည့်ပါá‹"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings_tv.xml b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
index 2c5b94b3cf45..f91c5bc2e467 100644
--- a/packages/SystemUI/res/values-my-rMM/strings_tv.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
@@ -27,7 +27,7 @@
<string name="pip_onboarding_title" msgid="7850436557670253991">"ပုံထဲမှပုံ"</string>
<string name="pip_onboarding_description" msgid="4028124563309465267">"နောက်á€á€…်á€á€¯á€™á€–ွင့်မá€á€»á€„်း သင့်ဗီဒီယိုကို ပြသထားပါမည်ዠáŽá€„်းကိုထိန်းá€á€»á€¯á€•်ရန် "<b>"ပင်မ"</b>" á€á€œá€¯á€á€ºá€€á€­á€¯ နှိပ်ပြီးဖိထားပါá‹"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ရပါပြီ"</string>
- <string name="recents_tv_dismiss" msgid="3555093879593377731">"ပယ်ပါ"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"ပယ်ရန်"</string>
<string-array name="recents_tv_blacklist_array">
</string-array>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index ae6f71e6d986..63ae35b2021e 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Flere innstillinger"</string>
<string name="notification_done" msgid="5279426047273930175">"Ferdig"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Varselinnstillinger for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Farge og utseende"</string>
- <string name="night_mode" msgid="3540405868248625488">"Nattmodus"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibrer skjermen"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"PÃ¥"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Av"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Slå på automatisk"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Bytt til nattmodus avhengig av tid og sted"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Når nattmodus er på"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Bruk et mørkt tema for Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Juster fargen"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Juster lysstyrken"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Det mørke temaet brukes på kjerneområdene i Android OS som vanligvis vises i et lyst tema, for eksempel Innstillinger."</string>
- <string name="color_apply" msgid="9212602012641034283">"Bruk"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Bekreft innstillingene"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Noen fargeinnstillinger kan gjøre denne enheten ubrukelig. Klikk på OK for å bekrefte disse fargeinnstillingene, ellers blir de tilbakestilt etter ti sekunder."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batteribruk"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparing er ikke tilgjengelig under lading"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparing"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index a0991362a666..06baec1d0b20 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"थप सेटिङहरू"</string>
<string name="notification_done" msgid="5279426047273930175">"समà¥à¤ªà¤¨à¥â€à¤¨ भयो"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> का सूचनाका लागि नियनà¥à¤¤à¥à¤°à¤£à¤¹à¤°à¥‚"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"रंग र रूप"</string>
- <string name="night_mode" msgid="3540405868248625488">"रातà¥à¤°à¥€ मोड"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"पà¥à¤°à¤¦à¤°à¥à¤¶à¤¨à¤•ो सà¥à¤¤à¤° मिलाउनà¥à¤¹à¥‹à¤¸à¥"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"सकà¥à¤°à¤¿à¤¯"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"निषà¥à¤•à¥à¤°à¤¿à¤¯"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"सà¥à¤µà¤¤à¤ƒ सकà¥à¤°à¤¿à¤¯ पारà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"सà¥à¤¥à¤¾à¤¨ र दिनको समयको लागि उपयà¥à¤•à¥à¤¤ रातà¥à¤°à¥€ मोडमा सà¥à¤µà¤¿à¤š गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"रातà¥à¤°à¥€ मोड सकà¥à¤°à¤¿à¤¯ हà¥à¤à¤¦à¤¾"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS का लागि गाढा रंगको विषयवसà¥à¤¤à¥ पà¥à¤°à¤¯à¥‹à¤— गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"रङà¥à¤—लाई समायोजन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"चमकलाई समायोजन गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"गहिरो रंगको विषयवसà¥à¤¤à¥à¤²à¤¾à¤ˆ Android OS का तà¥à¤¯à¤¸à¥à¤¤à¤¾ मà¥à¤–à¥à¤¯ कà¥à¤·à¥‡à¤¤à¥à¤°à¤¹à¤°à¥‚मा लागू गरिनà¥à¤› जसलाई सामानà¥à¤¯à¤¤à¤¯à¤¾ हलà¥à¤•ा रंगमा देखाइनà¥à¤›, जसà¥à¤¤à¥ˆ सेटिङहरू।"</string>
- <string name="color_apply" msgid="9212602012641034283">"लागू गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"सेटिङहरूको पà¥à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"केही रङ सेटिङहरूले यस यनà¥à¤¤à¥à¤°à¤²à¤¾à¤ˆ अनà¥à¤ªà¤¯à¥‹à¤—ी बनाउन सकà¥à¤›à¤¨à¥à¥¤ यी रङ सेटिङहरू पà¥à¤·à¥à¤Ÿà¤¿ गरà¥à¤¨ ठीक छ मा कà¥à¤²à¤¿à¤• गरà¥à¤¨à¥à¤¹à¥‹à¤¸à¥, अनà¥à¤¯à¤¥à¤¾ यी सेटिङहरू १० सेकेणà¥à¤¡à¤ªà¤›à¤¿ रिसेट हà¥à¤¨à¥‡à¤›à¤¨à¥à¥¤"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"बà¥à¤¯à¤¾à¤Ÿà¥à¤°à¥€ उपयोग"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"चारà¥à¤œ गरà¥à¤¨à¥‡ समयमा बà¥à¤¯à¤¾à¤Ÿà¥à¤°à¥€ सेभर उपलबà¥à¤§ छैन"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"बà¥à¤¯à¤¾à¤Ÿà¥à¤°à¥€ सेभर"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 94636cc0cb68..546025591fdf 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Meer instellingen"</string>
<string name="notification_done" msgid="5279426047273930175">"Gereed"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Beheeropties voor <xliff:g id="APP_NAME">%1$s</xliff:g>-meldingen"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Kleur en uiterlijk"</string>
- <string name="night_mode" msgid="3540405868248625488">"Nachtmodus"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Display kalibreren"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Aan"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Uit"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Automatisch inschakelen"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Overschakelen naar nachtmodus indien van toepassing voor locatie en tijd van de dag"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Als nachtmodus is ingeschakeld"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Donker thema gebruiken voor Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Tint aanpassen"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Helderheid aanpassen"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Het donkere thema wordt toegepast op kerngedeelten van het Android-besturingssysteem die normaal gesproken worden weergegeven met een licht thema, zoals Instellingen."</string>
- <string name="color_apply" msgid="9212602012641034283">"Toepassen"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Instellingen bevestigen"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Bij sommige kleurinstellingen kan het apparaat onbruikbaar worden. Klik op OK om deze kleurinstellingen te bevestigen, anders worden deze instellingen na tien seconden gereset."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Accugebruik"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Accubesparing niet beschikbaar tijdens opladen"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Accubesparing"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index 7b677796a977..ee29c466adbf 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
<string name="notification_done" msgid="5279426047273930175">"ਹੋ ਗਿਆ"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਸੂਚਨਾ ਕੰਟਰੋਲ"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"ਰੰਗ ਅਤੇ ਵਿਖਾਲਾ"</string>
- <string name="night_mode" msgid="3540405868248625488">"ਰਾਤ ਮੋਡ"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ਡਿਸਪਲੇ ਨੂੰ ਕੈਲੀਬà©à¨°à©‡à¨Ÿ ਕਰੋ"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ਚਾਲੂ"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ਬੰਦ"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"ਸਵੈਚਾਲਿਤ ਤੌਰ \'ਤੇ ਚਾਲੂ ਕਰੋ"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"ਟਿਕਾਣੇ ਅਤੇ ਦਿਨ ਦੇ ਸਮੇਂ ਲਈ ਢà©à¨•ਵੇਂ ਰਾਤ ਮੋਡ \'ਤੇ ਸਵਿੱਚ ਕਰੋ"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"ਜਦੋਂ ਰਾਤ ਮੋਡ ਚਾਲੂ ਹੋਵੇ"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS ਲਈ ਗੂੜà©à¨¹à©‡ ਥੀਮ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ਟਿੰਟ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ਚਮਕ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"ਗੂੜà©à¨¹à©‡ ਥੀਮ ਨੂੰ Android OS ਦੇ ਉਹਨਾਂ ਮà©à©±à¨– ਖੇਤਰਾਂ \'ਤੇ ਲਾਗੂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਜੋ ਆਮ ਤੌਰ \'ਤੇ ਇੱਕ ਹਲਕੇ ਥੀਮ ਵਿੱਚ ਵਿਖਾਠਜਾਂਦੇ ਹਨ, ਜਿਵੇਂ ਕਿ ਸੈਟਿੰਗਾਂ।"</string>
- <string name="color_apply" msgid="9212602012641034283">"ਲਾਗੂ ਕਰੋ"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"ਸੈਟਿੰਗਾਂ ਦੀ ਪà©à¨¸à¨¼à¨Ÿà©€ ਕਰੋ"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"ਕà©à¨ ਰੰਗ ਸੈਟਿੰਗਾਂ ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਬੇਕਾਰ ਕਰ ਸਕਦੀਆਂ ਹਨ। ਇਹਨਾਂ ਰੰਗ ਸੈਟਿੰਗਾਂ ਦੀ ਪà©à¨¸à¨¼à¨Ÿà©€ ਕਰਨ ਲਈ ਠੀਕ \'ਤੇ ਕਲਿੱਕ ਕਰੋ, ਨਹੀਂ ਤਾਂ ਇਹ ਸੈਟਿੰਗਾਂ 10 ਸਕਿੰਟ ਬਾਅਦ ਮà©à©œ-ਸੈੱਟ ਹੋ ਜਾਣਗੀਆਂ।"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ਬੈਟਰੀ ਵਰਤੋਂ"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਰਜਿੰਗ ਦੌਰਾਨ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"ਬੈਟਰੀ ਸੇਵਰ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 59c188885ee0..90a0099402bd 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -521,21 +521,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Więcej ustawień"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotowe"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> – ustawienia powiadomień"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Kolor i wyglÄ…d"</string>
- <string name="night_mode" msgid="3540405868248625488">"Tryb nocny"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibracja wyświetlacza"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"WÅ‚."</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Wył."</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Włącz automatycznie"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Przełączaj na tryb nocny odpowiednio do lokalizacji i pory dnia"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Gdy jest włączony tryb nocny"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Użyj motywu ciemnego dla Androida"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Dostosuj odcień"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Dostosuj jasność"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Motyw ciemny zostanie zastosowany do głównych obszarów Androida, które normalnie są jasne, takich jak Ustawienia."</string>
- <string name="color_apply" msgid="9212602012641034283">"Zastosuj"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Potwierdź ustawienia"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Niektóre ustawienia kolorów mogą utrudniać korzystanie z urządzenia. Kliknij OK, by potwierdzić te ustawienia kolorów. Jeśli tego nie zrobisz, zostaną one zresetowane po 10 sekundach."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Wykorzystanie baterii"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Oszczędzanie baterii nie jest dostępne podczas ładowania"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Oszczędzanie baterii"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index b91681041ccb..b860c099dd27 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Controles de notificação do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aparência"</string>
- <string name="night_mode" msgid="3540405868248625488">"Modo noturno"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrar tela"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Ativado"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Desativado"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Ativar automaticamente"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Alternar para o modo noturno conforme apropriado para o local e hora do dia"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Quando o modo noturno está ativado"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Usar o tema escuro para o SO Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como as configurações."</string>
- <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirmar configurações"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Algumas configurações de cor podem tornar o dispositivo inutilizável. Clique em \"OK\" para confirmar essas configurações de cor; caso contrário, essas configurações serão redefinidas após 10 segundos."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"A Economia de bateria não fica disponível durante o carregamento"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Economia de bateria"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 144dbef67009..00afbc148b27 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Mais definições"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Controlos de notificações do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aspeto"</string>
- <string name="night_mode" msgid="3540405868248625488">"Modo noturno"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrar ecrã"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Ativado"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Desativado"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Ligar automaticamente"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Alternar para o Modo noturno consoante a localização e a hora do dia"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Quando o Modo noturno está ativado"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Utilizar o tema escuro para o SO Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas essenciais do SO Android que são normalmente apresentadas num tema claro, como as Definições."</string>
- <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirmar as definições"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Algumas definições de cor podem tornar este dispositivo instável. Clique em OK para confirmar estas definições de cor. Caso contrário, estas definições serão repostas após 10 segundos."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Utiliz. da bateria"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Poupança de bateria não disponível durante o carregamento"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Poupança de bateria"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index b91681041ccb..b860c099dd27 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Controles de notificação do <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Cor e aparência"</string>
- <string name="night_mode" msgid="3540405868248625488">"Modo noturno"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrar tela"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Ativado"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Desativado"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Ativar automaticamente"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Alternar para o modo noturno conforme apropriado para o local e hora do dia"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Quando o modo noturno está ativado"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Usar o tema escuro para o SO Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como as configurações."</string>
- <string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirmar configurações"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Algumas configurações de cor podem tornar o dispositivo inutilizável. Clique em \"OK\" para confirmar essas configurações de cor; caso contrário, essas configurações serão redefinidas após 10 segundos."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"A Economia de bateria não fica disponível durante o carregamento"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Economia de bateria"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 523880d7ed03..6c0cab283c98 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -521,21 +521,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Mai multe setări"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminat"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Opțiuni privind notificările pentru <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Culoare și aspect"</string>
- <string name="night_mode" msgid="3540405868248625488">"Modul Noapte"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Calibrați afișarea"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Activat"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Dezactivat"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Activați automat"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Comutați la modul Noapte în funcție de locație și de momentul zilei"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Când modul Noapte este activat"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Folosiți tema întunecată pentru SO Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ajustați culoarea"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Ajustați luminozitatea"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema întunecată se aplică zonelor principale ale sistemului de operare Android care sunt de obicei afișate cu o temă deschisă la culoare, cum ar fi Setările."</string>
- <string name="color_apply" msgid="9212602012641034283">"Aplicați"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Confirmați setările"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Unele setări pentru culori pot face dispozitivul să nu mai funcționeze. Dați clic pe OK pentru a confirma aceste setări pentru culori. În caz contrar, acestea se vor reseta după 10 secunde."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Utilizarea bateriei"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Economisirea bateriei nu este disponibilă pe durata încărcării"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Economisirea bateriei"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 60a3896c8d6f..f606f77be23e 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -523,21 +523,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Другие наÑтройки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Управление уведомлениÑми (<xliff:g id="APP_NAME">%1$s</xliff:g>)"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Цвета и Ñтиль"</string>
- <string name="night_mode" msgid="3540405868248625488">"Ðочной режим"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Калибровка диÑплеÑ"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Включен"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Отключен"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Включать автоматичеÑки"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Включать ночной режим Ñ ÑƒÑ‡ÐµÑ‚Ð¾Ð¼ меÑÑ‚Ð¾Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸ времени Ñуток"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"В ночном режиме"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"ИÑпользовать темное оформление Ð´Ð»Ñ Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ИзменÑть оттенок"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ЯркоÑть"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Темное оформление применÑетÑÑ Ðº оÑновным Ñлементам ÑиÑтемы Android (таким, как приложение \"ÐаÑтройки\"), которые обычно показываютÑÑ Ð² Ñветлом."</string>
- <string name="color_apply" msgid="9212602012641034283">"Применить"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Подтвердите наÑтройки"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Ðекоторые цветовые наÑтройки могут затруднить работу Ñ ÑƒÑтройÑтвом. Чтобы применить выбранные параметры, нажмите \"ОК\". Ð’ противном Ñлучае они будут Ñброшены через 10 Ñекунд."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Уровень зарÑда"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Режим ÑнергоÑÐ±ÐµÑ€ÐµÐ¶ÐµÐ½Ð¸Ñ Ð½ÐµÐ»ÑŒÐ·Ñ Ð²ÐºÐ»ÑŽÑ‡Ð¸Ñ‚ÑŒ во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ñ€Ñдки"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Режим ÑнергоÑбережениÑ"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index bffb443447a5..57cc5dfa1be6 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"à¶­à·€ à·ƒà·à¶šà·ƒà·“ම්"</string>
<string name="notification_done" msgid="5279426047273930175">"නිමයි"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> දà·à¶±à·”ම්දීම් à¶´à·à¶½à¶±"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"වර්ණය සහ පෙනුම"</string>
- <string name="night_mode" msgid="3540405868248625488">"à¶»à·à¶­à·Šâ€à¶»à·“ à¶´à·Šâ€à¶»à¶šà·à¶»à¶º"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"සංදර්à·à¶šà¶º à¶šà·Šâ€à¶»à¶¸à·à¶‚කනය කරන්න"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"à¶šà·Šâ€à¶»à·’යà·à¶­à·Šà¶¸à¶šà¶ºà·’"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"à¶šà·Šâ€à¶»à·’යà·à·€à·’රහිතයි"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"ස්වයංක්â€à¶»à·’යව à¶šà·Šâ€à¶»à·’යà·à¶­à·Šà¶¸à¶š කරන්න"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"ස්ථà·à¶±à¶º සහ දවසේ වේලà·à·€à¶§ à¶œà·à·…පෙන ලෙස à¶»à·à¶­à·Šâ€à¶»à·“ à¶´à·Šâ€à¶»à¶šà·à¶»à¶ºà¶§ මà·à¶»à·” වන්න"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"à¶»à·à¶­à·Šâ€à¶»à·“ à¶´à·Šâ€à¶»à¶šà·à¶»à¶º à¶šà·Šâ€à¶»à·’යà·à¶­à·Šà¶¸à¶š විට"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS සඳහ෠අඳුරු තේමà·à·€ à¶·à·à·€à·’à¶­ කරන්න"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"à¶´à·à·„à·à¶º සීරුමà·à¶»à·” කරන්න"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"දීප්තිය සීරුමà·à¶»à·” කරන්න"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"à·ƒà·à¶šà·ƒà·“ම් à·€à·à¶±à·’, à·ƒà·à¶¸à·à¶±à·Šâ€à¶ºà¶ºà·™à¶±à·Š ල෠පà·à·„෠තේමà·à·€à¶š සංදර්à·à¶±à¶º වන Android OS à·„à·’ මූලික à¶´à·Šâ€à¶»à¶¯à·šà·à·€à¶½à¶§ අඳුරු තේමà·à·€ යෙදේ."</string>
- <string name="color_apply" msgid="9212602012641034283">"යොදන්න"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"à·ƒà·à¶šà·ƒà·“ම් තහවුරු කරන්න"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"සමහර වර්ණ à·ƒà·à¶šà·ƒà·“ම් මෙම à¶‹à¶´à·à¶‚ගය à¶·à·à·€à·’à¶­ à¶šà·… නොහà·à¶šà·’ තත්ත්වයට à¶´à¶­à·Š à¶šà·… à·„à·à¶šà·’ය. මෙම වර්ණ à·ƒà·à¶šà·ƒà·“ම් තහවුරු කිරීමට හරි ක්ලික් කරන්න, à¶±à·à¶­à·„ොත් මෙම à·ƒà·à¶šà·ƒà·“ම් à¶­à¶­à·Šà¶´à¶» 10à¶šà¶§ පසුව යළි සකසනු ඇත."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"à¶¶à·à¶§à¶»à·’ à¶·à·à·€à·’තය"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ආරà·à¶´à¶«à¶º අතරතුර à¶¶à·à¶§à¶»à·’ සුරà·à¶šà·”ම ලබ෠ගත නොහà·à¶šà·’ය."</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"à¶¶à·à¶§à¶»à·’ සුරà·à¶šà·”ම"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 95460f5c1f7c..a96367ed88a2 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -523,21 +523,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Ďalšie nastavenia"</string>
<string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Ovládacie prvky pre upozornenia z aplikácie <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Farba a vzhľad"</string>
- <string name="night_mode" msgid="3540405868248625488">"NoÄný režim"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibrovať obrazovku"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Zapnutý"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Vypnutý"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Zapínať automaticky"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Prepnúť do NoÄného režimu podľa miesta a Äasu dňa"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"KeÄ je zapnutý NoÄný režim"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Použiť tmavý motív pre systém Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Upraviť tónovanie"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Upraviť jas"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"V hlavných oblastiach systému Android OS (ako sú Nastavenia), ktoré sú obyÄajne zobrazené vo svetlom motíve, je použitý tmavý motív."</string>
- <string name="color_apply" msgid="9212602012641034283">"Použiť"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Potvrdenie nastavení"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Niektoré nastavenia farieb môžu toto zariadenie znefunkÄniÅ¥. Tieto nastavenia farieb potvrdíte kliknutím na tlaÄidlo OK, inÃ¡Ä sa tieto nastavenia o 10 sekúnd obnovia."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Využitie batérie"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"PoÄas nabíjania nie je Å etriÄ batérie k dispozícii"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Å etriÄ batérie"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index f993f4d89864..d2cd947f919a 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -523,21 +523,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"VeÄ nastavitev"</string>
<string name="notification_done" msgid="5279426047273930175">"DokonÄano"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Kontrolniki obvestil za aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Barva in videz"</string>
- <string name="night_mode" msgid="3540405868248625488">"NoÄni naÄin"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Umerjanje zaslona"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Vklopljeno"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Izklopljeno"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Samodejni vklop"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Preklop v noÄni naÄin, kot je ustrezno glede na lokacijo in uro v dnevu"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Ko je vklopljen noÄni naÄin"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Uporaba temne teme za sistem Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Prilagodi odtenek"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Prilagodi svetlost"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Za osrednja podroÄja sistema Android, ki so obiÄajno prikazana v svetli temi, na primer nastavitve, je uporabljena temna tema."</string>
- <string name="color_apply" msgid="9212602012641034283">"Uporabi"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Potrditev nastavitev"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Zaradi nekaterih barvnih nastavitev lahko postane ta naprava neuporabna. Kliknite »V redu«, Äe želite potrditi te barvne nastavitve. V nasprotnem primeru se bodo Äez 10 sekund ponastavile na prvotno vrednost."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Poraba akumulatorja"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"VarÄevanje z energijo akumulatorja med polnjenjem ni na voljo"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"VarÄevanje z energijo akumulatorja"</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 4fbd8339e076..06182b1649ac 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Cilësime të tjera"</string>
<string name="notification_done" msgid="5279426047273930175">"U krye"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Kontrollet e njoftimeve të <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Ngjyra dhe pamja"</string>
- <string name="night_mode" msgid="3540405868248625488">"Modaliteti i natës"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibro ekranin"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Aktiv"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Joaktiv"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Aktivizoje automatikisht"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Kalo në \"Modalitetin e natës\" sipas përshtatshmërisë për vendin dhe kohën e ditës"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Kur \"Modaliteti i natës\" është aktiv"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Përdor temën e errët për Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Rregullo nuancën"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Rregullo ndriçimin"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Tema e errët zbatohet në zonat kryesore të Android OS që shfaqen zakonisht në një temë të çelur, siç janë \"Cilësimet\"."</string>
- <string name="color_apply" msgid="9212602012641034283">"Zbato"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Konfirmo cilësimet"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Disa cilësime ngjyrash mund ta bëjnë këtë pajisje të papërdorshme. Kliko OK për të konfirmuar këto cilësime ngjyrash, përndryshe këto cilësime do të rivendosen pas 10 sekondash."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Përdorimi i baterisë"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"\"Kursyesi i baterisë\" nuk është i disponueshëm gjatë karikimit"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Kursyesi i baterisë"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index eed01c1b0743..67292a6cb887 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Још подешавања"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Контроле обавештења за апликацију <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Боја и изглед"</string>
- <string name="night_mode" msgid="3540405868248625488">"Ðоћни режим"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Калибришите екран"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Укључено"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ИÑкључено"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"ÐутоматÑки укључи"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Пређите на ноћни режим у завиÑноÑти од локације и доба дана"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Када је ноћни режим укључен"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"КориÑти тамну тему за Android ОС"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Прилагоди Ñенку"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Прилагоди оÑветљеноÑÑ‚"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Тамна тема Ñе примењује на кључне делове Android ОС-а који Ñе обично приказују у Ñветлој теми, попут Подешавања."</string>
- <string name="color_apply" msgid="9212602012641034283">"Примени"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Потврдите подешавања"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Ðека подешавања боја могу да учине уређај неупотребљивим. Кликните на Потврди да биÑте потврдили ова подешавања боја, пошто ће Ñе у Ñупротном ова подешавања реÑетовати након 10 Ñекунди."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Потрошња батерије"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Уштеда батерије није доÑтупна током пуњења"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Уштеда батерије"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 39a6b2f70611..6b274936c85c 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Fler inställningar"</string>
<string name="notification_done" msgid="5279426047273930175">"Klar"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Inställningar för <xliff:g id="APP_NAME">%1$s</xliff:g>-aviseringar"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Färg och utseende"</string>
- <string name="night_mode" msgid="3540405868248625488">"Nattläge"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Kalibrera skärmen"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Aktiverat"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Inaktiverat"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Aktivera automatiskt"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Byt till Nattläge vid passande platser och tider på dygnet"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"När Nattläget är aktiverat"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Använd mörkt tema för Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Justera ton"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Justera ljusstyrka"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Det mörka temat används för kärnfunktioner i Android OS som brukar visas med ett ljust tema, t.ex. inställningarna."</string>
- <string name="color_apply" msgid="9212602012641034283">"Verkställ"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Bekräfta inställningarna"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Vissa färginställningar kan göra den här enheten oanvändbar. Klicka på OK om du vill bekräfta färginställningarna, annars återställs inställningarna efter 10 sekunder."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batteriförbrukning"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Batterisparläget är inte tillgängligt vid laddning"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Batterisparläge"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index d1ca28ba5848..20cd2aa9ba93 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Mipangilio zaidi"</string>
<string name="notification_done" msgid="5279426047273930175">"Nimemaliza"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Vidhibiti vya arifa za <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Rangi na mwonekano"</string>
- <string name="night_mode" msgid="3540405868248625488">"Hali ya usiku"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Rekebisha onyesho"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Imewashwa"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Imezimwa"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Washa kiotomatiki"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Badilisha kuwa Hali ya Usiku kulingana na mahali na wakati"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Hali ya Usiku inapowashwa"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Tumia mandhari ya giza katika Mfumo wa Uendeshaji wa Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Rekebisha kivulivuli"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Rekebisha mwangaza"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Mandhari yenye giza yametumika katika maeneo muhimu ya Mfumo wa Uendeshaji wa Android ambayo kwa kawaida huonyeshwa katika mandhari yenye mwangaza, kama vile Mipangilio."</string>
- <string name="color_apply" msgid="9212602012641034283">"Tumia"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Thibitisha mipangilio"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Baadhi ya mipangilio ya rangi inaweza kufanya kifaa hiki kisitumike. Bofya Sawa ili uthibitishe mipangilio hii ya rangi, vinginevyo, mipangilio hii itajiweka upya baada ya sekunde 10."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Matumizi ya betri"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Kiokoa Betri hakipatikani unapochaji betri"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Kiokoa Betri"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 6ba18c382ea5..ea444bf7cf00 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"மேலà¯à®®à¯ அமைபà¯à®ªà¯à®•ளà¯"</string>
<string name="notification_done" msgid="5279426047273930175">"à®®à¯à®Ÿà®¿à®¨à¯à®¤à®¤à¯"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> அறிவிபà¯à®ªà¯à®•௠கடà¯à®Ÿà¯à®ªà¯à®ªà®¾à®Ÿà¯à®•ளà¯"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"வணà¯à®£à®®à¯à®®à¯ தோறà¯à®±à®®à¯à®®à¯"</string>
- <string name="night_mode" msgid="3540405868248625488">"இரவà¯à®ªà¯ பயனà¯à®®à¯à®±à¯ˆ"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"திரையை அளவà¯à®¤à¯à®¤à®¿à®°à¯à®¤à¯à®¤à®®à¯ செயà¯"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"இயகà¯à®•தà¯à®¤à®¿à®²à¯"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"à®®à¯à®Ÿà®•à¯à®•தà¯à®¤à®¿à®²à¯"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"தானாகவே இயகà¯à®•à¯"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"இரà¯à®ªà¯à®ªà®¿à®Ÿà®®à¯ மறà¯à®±à¯à®®à¯ நேரதà¯à®¤à®¿à®©à¯à®ªà®Ÿà®¿ இரவà¯à®ªà¯ பயனà¯à®®à¯à®±à¯ˆà®•à¯à®•௠மாறà¯à®±à¯"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"இரவà¯à®ªà¯ பயனà¯à®®à¯à®±à¯ˆ இயகà¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®¿à®°à¯à®•à¯à®•à¯à®®à¯ போதà¯"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OSகà¯à®•ாக அடர௠தீமினைப௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"டிணà¯à®Ÿà¯à®Ÿà¯ˆà®šà¯ சரிசெயà¯"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ஒளிரà¯à®µà¯ˆà®šà¯ சரிசெயà¯"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"வழகà¯à®•மாக வெளிர௠தீமில௠காடà¯à®Ÿà®ªà¯à®ªà®Ÿà¯à®•ிற Android OS இன௠மà¯à®•à¯à®•ிய பகà¯à®¤à®¿à®•ளில௠(எ.கா. அமைபà¯à®ªà¯à®•ளà¯) அடர௠தீம௠பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à®ªà¯à®ªà®Ÿà¯à®•ிறதà¯."</string>
- <string name="color_apply" msgid="9212602012641034283">"பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"அமைபà¯à®ªà¯à®•ளை உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤à¯"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"சில வணà¯à®£ அமைபà¯à®ªà¯à®•ள௠இநà¯à®¤à®šà¯ சாதனதà¯à®¤à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ à®®à¯à®Ÿà®¿à®¯à®¾à®¤à®ªà®Ÿà®¿ செயà¯à®¯à®²à®¾à®®à¯. இநà¯à®¤ வணà¯à®£ அமைபà¯à®ªà¯à®•ளை உறà¯à®¤à®¿à®ªà¯à®ªà®Ÿà¯à®¤à¯à®¤, சரி எனà¯à®ªà®¤à¯ˆà®•௠கிளிக௠செயà¯à®¯à®µà¯à®®à¯, இலà¯à®²à¯ˆà®¯à¯†à®©à®¿à®²à¯ இநà¯à®¤ அமைபà¯à®ªà¯à®•ள௠10 வினாடிகளà¯à®•à¯à®•à¯à®ªà¯ பின௠மீடà¯à®Ÿà®®à¯ˆà®•à¯à®•பà¯à®ªà®Ÿà¯à®®à¯."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"பேடà¯à®Ÿà®°à®¿ உபயோகமà¯"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"சாரà¯à®œà¯ செயà¯à®¯à¯à®®à¯ போத௠பேடà¯à®Ÿà®°à®¿ சேமிபà¯à®ªà®¾à®©à¯ˆà®ªà¯ பயனà¯à®ªà®Ÿà¯à®¤à¯à®¤ à®®à¯à®Ÿà®¿à®¯à®¾à®¤à¯"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"பேடà¯à®Ÿà®°à®¿ சேமிபà¯à®ªà®¾à®©à¯"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index 42705fe39674..5c9988b7c07c 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"మరినà±à°¨à°¿ సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à±"</string>
<string name="notification_done" msgid="5279426047273930175">"పూరà±à°¤à°¯à°¿à°‚ది"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> నోటిఫికేషనౠనియంతà±à°°à°£à°²à±"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"రంగౠమరియౠకనిపించే తీరà±"</string>
- <string name="night_mode" msgid="3540405868248625488">"రాతà±à°°à°¿ మోడà±"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"à°¡à°¿à°¸à±â€Œà°ªà±à°²à±‡à°¨à°¿ à°•à±à°°à°®à°¾à°‚కనం చేయండి"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"ఆనà±â€Œà°²à±‹ ఉంది"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ఆఫà±â€Œà°²à±‹ ఉంది"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"à°¸à±à°µà°¯à°‚చాలకంగా ఆనౠచేయి"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"à°¸à±à°¥à°¾à°¨à°‚ మరియౠరోజà±à°²à±‹ సమయానికి తగినటà±à°²à±à°—à°¾ రాతà±à°°à°¿ మోడà±â€Œà°•à°¿ మారà±à°¸à±à°¤à±à°‚ది"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"రాతà±à°°à°¿ మోడౠఆనà±â€Œà°²à±‹ ఉనà±à°¨à°ªà±à°ªà±à°¡à±"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS కోసం à°®à±à°¦à±à°°à± రంగౠథీమౠఉపయోగించండి"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"లేత à°°à°‚à°—à±à°¨à± సరà±à°¦à±à°¬à°¾à°Ÿà± చేయండి"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"à°ªà±à°°à°•ాశానà±à°¨à°¿ సరà±à°¦à±à°¬à°¾à°Ÿà± చేయండి"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"సాధారణంగా లేత రంగౠథీమà±â€Œà°²à±‹ à°ªà±à°°à°¦à°°à±à°¶à°¿à°‚చబడే సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°² వంటి Android OS à°ªà±à°°à°§à°¾à°¨ అంశాలకౠమà±à°¦à±à°°à± రంగౠథీమౠవరà±à°¤à°¿à°‚పజేయబడà±à°¤à±à°‚ది."</string>
- <string name="color_apply" msgid="9212602012641034283">"వరà±à°¤à°¿à°‚పజేయి"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°¨à± నిరà±à°§à°¾à°°à°¿à°‚à°šà°‚à°¡à°¿"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"కొనà±à°¨à°¿ రంగౠసెటà±à°Ÿà°¿à°‚à°—à±â€Œà°² వలన à°ˆ పరికరం ఉపయోగించలేని విధంగా అయిపోవచà±à°šà±. à°ˆ రంగౠసెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à°¨à± నిరà±à°§à°¾à°°à°¿à°‚చడానికి సరే à°•à±à°²à°¿à°•ౠచేయండి లేదంటే à°ˆ సెటà±à°Ÿà°¿à°‚à°—à±â€Œà°²à± 10 సెకనà±à°² తరà±à°µà°¾à°¤ రీసెటౠచేయబడతాయి."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"à°¬à±à°¯à°¾à°Ÿà°°à±€ వినియోగం"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ఛారà±à°œà± à°…à°µà±à°¤à±à°¨à±à°¨ సమయంలో à°¬à±à°¯à°¾à°Ÿà°°à±€ సేవరౠఅందà±à°¬à°¾à°Ÿà±à°²à±‹ ఉండదà±"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"à°¬à±à°¯à°¾à°Ÿà°°à±€ సేవరà±"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 7474ab33f445..f7337187723d 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"à¸à¸²à¸£à¸•ั้งค่าเพิ่มเติม"</string>
<string name="notification_done" msgid="5279426047273930175">"เสร็จสิ้น"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"ส่วนควบคุมà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ือนของ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"สีà¹à¸¥à¸°à¸¥à¸±à¸à¸©à¸“ะที่ปราà¸à¸"</string>
- <string name="night_mode" msgid="3540405868248625488">"โหมดà¸à¸¥à¸²à¸‡à¸„ืน"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"ปรับเทียบà¸à¸²à¸£à¹à¸ªà¸”งผล"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"เปิด"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"ปิด"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"เปิดอัตโนมัติ"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"เปลี่ยนเป็นโหมดà¸à¸¥à¸²à¸‡à¸„ืนตามความเหมาะสมà¸à¸±à¸šà¸ªà¸–านที่à¹à¸¥à¸°à¹€à¸§à¸¥à¸²à¸‚องวัน"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"เมื่อเปิดโหมดà¸à¸¥à¸²à¸‡à¸„ืน"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"ใช้ธีมสีเข้มสำหรับ Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ปรับà¸à¸²à¸£à¹à¸•้มสี"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"ปรับความสว่าง"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"ใช้ธีมสีเข้มในบริเวณสำคัà¸à¸‚องระบบปà¸à¸´à¸šà¸±à¸•ิà¸à¸²à¸£ Android ซึ่งปà¸à¸•ิà¹à¸¥à¹‰à¸§à¸ˆà¸°à¹à¸ªà¸”งด้วยธีมสีอ่อน เช่น à¸à¸²à¸£à¸•ั้งค่า"</string>
- <string name="color_apply" msgid="9212602012641034283">"ใช้"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"ยืนยันà¸à¸²à¸£à¸•ั้งค่า"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"à¸à¸²à¸£à¸•ั้งค่าสีบางอย่างอาจทำให้อุปà¸à¸£à¸“์นี้ใช้งานไม่ได้ คลิà¸à¸•à¸à¸¥à¸‡à¹€à¸žà¸·à¹ˆà¸­à¸¢à¸·à¸™à¸¢à¸±à¸™à¸à¸²à¸£à¸•ั้งค่าสีเหล่านี้ มิฉะนั้นระบบจะรีเซ็ตà¸à¸²à¸£à¸•ั้งค่าหลังจาภ10 วินาที"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"à¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¹à¸šà¸•เตอรี่"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"ไม่สามารถใช้โหมดประหยัดà¹à¸šà¸•เตอรี่ระหว่างà¸à¸²à¸£à¸Šà¸²à¸£à¹Œà¸ˆ"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"โหมดประหยัดà¹à¸šà¸•เตอรี่"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 35b239271af5..c5a6dcc2629d 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Higit pang mga setting"</string>
<string name="notification_done" msgid="5279426047273930175">"Tapos Na"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Mga kontrol sa notification ng <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Kulay at hitsura"</string>
- <string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"I-calibrate ang display"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Naka-on"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Naka-off"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Awtomatikong i-on"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Lumipat sa Night Mode kapag naaangkop sa lokasyon at oras"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Kapag naka-on ang Night Mode"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Gumamit ng madilim na tema para sa Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Isaayos ang tint"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Isaayos ang liwanag"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Ilalapat ang madilim na tema sa mga mahalagang bahagi ng Android OS na karaniwang ipinapakita nang may maliwanag na tema, gaya ng Mga Setting."</string>
- <string name="color_apply" msgid="9212602012641034283">"Ilapat"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Kumpirmahin ang mga setting"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Maaaring hindi magamit ang device na ito dahil sa ilang setting ng kulay. I-click ang OK upang kumpirmahin ang mga setting ng kulay na ito, kung hindi ay mare-reset ang mga setting na ito pagkatapos ng 10 segundo."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Paggamit ng baterya"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Hindi available ang Pangtipid sa Baterya kapag nagcha-charge"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Pangtipid sa Baterya"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 49dfc95c2502..af9c277c3528 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"DiÄŸer ayarlar"</string>
<string name="notification_done" msgid="5279426047273930175">"Bitti"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> bildirim denetimleri"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Renk ve görünüm"</string>
- <string name="night_mode" msgid="3540405868248625488">"Gece modu"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Ekranı kalibre et"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Açık"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Kapalı"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Otomatik olarak aç"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Konuma ve günün saatine uygun şekilde Gece Modu\'na geç"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Gece Modu açık olduğunda"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android OS için koyu renk tema kullan"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Tonu ayarla"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Parlaklığı ayarla"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Koyu renk tema, Android OS\'nin normalde Ayarlar gibi açık renk bir temayla görüntülenen temel alanlarına uygulanır."</string>
- <string name="color_apply" msgid="9212602012641034283">"Uygula"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Ayarları onaylayın"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Bazı renkler bu cihazı kullanılmaz yapabilir. Bu renkleri onaylamak için Tamam\'ı tıklayın. Tıklamazsanız bu ayarlar 10 saniye sonra sıfırlanacaktır."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Pil kullanımı"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Şarj sırasında Pil Tasarrufu özelliği kullanılamaz"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Pil Tasarrufu"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 79333a966fac..12a3628f538a 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -36,14 +36,14 @@
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"СповіщеннÑ"</string>
<string name="battery_low_title" msgid="6456385927409742437">"Ðизький рівень зарÑду акумулÑтора"</string>
<string name="battery_low_percent_format" msgid="2900940511201380775">"ЗалишилоÑÑ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
- <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"ЗалишилоÑÑ <xliff:g id="PERCENTAGE">%s</xliff:g>. Режим Ð·Ð°Ð¾Ñ‰Ð°Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ñ€Ñду акумулÑтора ввімкнено."</string>
+ <string name="battery_low_percent_format_saver_started" msgid="6859235584035338833">"ЗалишилоÑÑ <xliff:g id="PERCENTAGE">%s</xliff:g>. Увімкнено режим енергозбереженнÑ."</string>
<string name="invalid_charger" msgid="4549105996740522523">"ЗарÑÐ´Ð¶Ð°Ð½Ð½Ñ USB не підтримуєтьÑÑ.\nВикориÑтовуйте лише наданий у комплекті зарÑдний приÑтрій."</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"ЗарÑÐ´Ð¶Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· USB не підтримуєтьÑÑ."</string>
<string name="invalid_charger_text" msgid="5474997287953892710">"ВикориÑтовуйте лише зарÑдний приÑтрій, Ñкий поÑтачаєтьÑÑ Ð² комплекті."</string>
<string name="battery_low_why" msgid="4553600287639198111">"ÐалаштуваннÑ"</string>
- <string name="battery_saver_confirmation_title" msgid="5299585433050361634">"Увімкнути режим Ð·Ð°Ð¾Ñ‰Ð°Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ñ€Ñду акумулÑтора?"</string>
+ <string name="battery_saver_confirmation_title" msgid="5299585433050361634">"Увімкнути режим енергозбереженнÑ?"</string>
<string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"Увімкнути"</string>
- <string name="battery_saver_start_action" msgid="5576697451677486320">"Увімкнути режим Ð·Ð°Ð¾Ñ‰Ð°Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ñ€Ñду акумулÑтора"</string>
+ <string name="battery_saver_start_action" msgid="5576697451677486320">"Увімкнути режим енергозбереженнÑ"</string>
<string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ÐалаштуваннÑ"</string>
<string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
<string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Повертати екран автоматично"</string>
@@ -393,9 +393,9 @@
<string name="user_remove_user_title" msgid="4681256956076895559">"Видалити кориÑтувача?"</string>
<string name="user_remove_user_message" msgid="1453218013959498039">"УÑÑ– додатки й дані цього кориÑтувача буде видалено."</string>
<string name="user_remove_user_remove" msgid="7479275741742178297">"Видалити"</string>
- <string name="battery_saver_notification_title" msgid="237918726750955859">"Режим Ð·Ð°Ð¾Ñ‰Ð°Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ñ€Ñду акумулÑтора ввімкнено"</string>
+ <string name="battery_saver_notification_title" msgid="237918726750955859">"Режим ÐµÐ½ÐµÑ€Ð³Ð¾Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾"</string>
<string name="battery_saver_notification_text" msgid="820318788126672692">"ЗнижуєтьÑÑ Ð¿Ñ€Ð¾Ð´ÑƒÐºÑ‚Ð¸Ð²Ð½Ñ–Ñть Ñ– обмежуютьÑÑ Ñ„Ð¾Ð½Ð¾Ð²Ñ– дані"</string>
- <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Вимкнути режим Ð·Ð°Ð¾Ñ‰Ð°Ð´Ð¶ÐµÐ½Ð½Ñ Ð·Ð°Ñ€Ñду акумулÑтора"</string>
+ <string name="battery_saver_notification_action_text" msgid="109158658238110382">"Вимкнути режим енергозбереженнÑ"</string>
<string name="media_projection_dialog_text" msgid="3071431025448218928">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> отримає доÑтуп до вÑÑ–Ñ… даних, Ñкі відображаютьÑÑ Ð½Ð° вашому екрані."</string>
<string name="media_projection_remember_text" msgid="3103510882172746752">"Більше не показувати"</string>
<string name="clear_all_notifications_text" msgid="814192889771462828">"ОчиÑтити вÑе"</string>
@@ -523,24 +523,9 @@
<string name="notification_more_settings" msgid="816306283396553571">"Більше налаштувань"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Елементи ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ ÑповіщеннÑми додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Колір Ñ– виглÑд"</string>
- <string name="night_mode" msgid="3540405868248625488">"Ðічний режим"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Калібрувати диÑплей"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Увімкнено"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Вимкнено"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Вмикати автоматично"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Переходити на нічний режим відповідно до міÑÑ†ÐµÐ·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° чаÑу доби"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Коли нічний режим увімкнено"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"ВикориÑтати нічну тему Ð´Ð»Ñ ÐžÐ¡ Android"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Ðалаштувати відтінок"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Регулювати ÑÑкравіÑть"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Темна тема заÑтоÑовуєтьÑÑ Ð² оÑновних облаÑÑ‚ÑÑ… ОС Android, Ñкі зазвичай відображаютьÑÑ Ñƒ Ñвітлій темі, Ñк-от у налаштуваннÑÑ…."</string>
- <string name="color_apply" msgid="9212602012641034283">"ЗаÑтоÑувати"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Підтвердити налаштуваннÑ"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"ДеÑкі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð»ÑŒÐ¾Ñ€Ñ–Ð² можуть зробити цей приÑтрій непридатним Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑтаннÑ. ÐатиÑніть OK, щоб підтвердити налаштуваннÑ, інакше Ñ—Ñ… буде Ñкинуто через 10 Ñекунд."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð·Ð°Ñ€Ñду"</string>
- <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Режим економії зарÑду акумулÑтора недоÑтупний під Ñ‡Ð°Ñ Ð·Ð°Ñ€ÑджаннÑ"</string>
- <string name="battery_detail_switch_title" msgid="6285872470260795421">"Режим економії зарÑду акумулÑтора"</string>
+ <string name="battery_detail_charging_summary" msgid="1279095653533044008">"Режим ÐµÐ½ÐµÑ€Ð³Ð¾Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð½Ðµ можна ввімкнути під Ñ‡Ð°Ñ Ð·Ð°Ñ€ÑджаннÑ"</string>
+ <string name="battery_detail_switch_title" msgid="6285872470260795421">"Режим енергозбереженнÑ"</string>
<string name="battery_detail_switch_summary" msgid="9049111149407626804">"ЗнижуєтьÑÑ Ð¿Ñ€Ð¾Ð´ÑƒÐºÑ‚Ð¸Ð²Ð½Ñ–Ñть Ñ– обмежуєтьÑÑ Ð¾Ð±Ð¼Ñ–Ð½ даними у фоновому режимі"</string>
<string name="keyboard_key_button_template" msgid="6230056639734377300">"Кнопка <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index e652aee6264e..69e196764a45 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string>
<string name="notification_done" msgid="5279426047273930175">"Ûوگیا"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> Ú©Û’ نوٹیÙکیشن کنٹرولز"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"رنگ اور ظÛور"</string>
- <string name="night_mode" msgid="3540405868248625488">"رات موڈ"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"نشان زد ڈسپلے"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"آن"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Ø¢Ù"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"خودکار طور پر آن کریں"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"مقام اور دن کے وقت کی مناسبت سے نائٹ موڈ میں سوئچ کریں"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"جب نائٹ موڈ آن ÛÙˆ"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"â€Android OS کیلئے ڈارک تھیم استعمال کریں"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"ٹنٹ ایڈجسٹ کریں"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"چمک کو ایڈجسٹ کریں"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"â€ÚˆØ§Ø±Ú© تھیم Android OS Ú©ÛŒ بنیادی جگÛÙˆÚº پر لاگو Ú©ÛŒ جاتی ÛÛ’ جو عام طور لائٹ تھیم میں ڈسپلے Ûوتے Ûیں، جیسے ترتیبات۔"</string>
- <string name="color_apply" msgid="9212602012641034283">"لاگو کریں"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"ترتیبات کی توثیق کریں"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"رنگوں Ú©ÛŒ Ú©Ú†Ú¾ ترتیبات اس آلے Ú©Ùˆ ناقابل استعمال بنا سکتی Ûیں۔ رنگوں Ú©ÛŒ ان ترتیبات Ú©ÛŒ توثیق کرنے کیلئے ٹھیک ÛÛ’ پر Ú©Ù„Ú© کریں، بصورت دیگر 10 سیکنڈ بعد ÛŒÛ ØªØ±ØªÛŒØ¨Ø§Øª ری سیٹ ÛÙˆ جائیں گی۔"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"بیٹری کا استعمال"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"چارجنگ Ú©Û’ دوران بیٹری سیور دستیاب Ù†Ûیں ÛÛ’"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"بیٹری سیور"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index a8923dc9de0f..0a8304546399 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Boshqa sozlamalar"</string>
<string name="notification_done" msgid="5279426047273930175">"Tayyor"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> bildirishnomalarini boshqarish"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Rang va ko‘rinishi"</string>
- <string name="night_mode" msgid="3540405868248625488">"Tungi rejim"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Ekranni kalibrlash"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Yoniq"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"O‘chiq"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Avtomatik yoqish"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Joylashuv va vaqtga mos ravishda tungi rejimga o‘tish"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Agar tungi rejim yoniq bo‘lsa"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Android uchun to‘q rangli mavzudan foydalanish"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Rang tusini o‘zgartirish"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Yorqinlikni o‘zgartirish"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"To‘q rangli mavzu Android tizimining odatda och rangda ko‘rsatiladigan o‘zak sahifalariga (masalan, Sozlamalar) nisbatan qo‘llaniladi."</string>
- <string name="color_apply" msgid="9212602012641034283">"Qo‘llash"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Sozlamalarni tasdiqlang"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Ba’zi rang sozlamalari qurilmadan foydalanishni qiyinlashtirish mumkin. Tanlgan parametrlarni tasdiqlash uchun “OK†tugmasini bosing. Aks holda, ular 10 soniyadan so‘ng qayta tiklanadi."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Batareya sarfi"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Quvvat tejash rejimi"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index edc8e48fd32c..d798be65ab2d 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Cài đặt khác"</string>
<string name="notification_done" msgid="5279426047273930175">"Xong"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"Äiá»u khiển thông báo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Màu sắc và giao diện"</string>
- <string name="night_mode" msgid="3540405868248625488">"Chế độ ban đêm"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Hiệu chỉnh hiển thị"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Bật"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Tắt"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Tự động bật"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Chuyển sang Chế bá»™ ban đêm khi thích hợp cho vị trí và thá»i gian trong ngày"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Khi Chế độ ban đêm đang bật"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Sử dụng chủ đỠsẫm màu cho Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Äiá»u chỉnh phá»§ màu"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Äiá»u chỉnh độ sáng"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Chá»§ đỠsẫm màu được áp dụng cho các vùng chính cá»§a Android OS được hiển thị bình thưá»ng trong chá»§ đỠsáng màu, chẳng hạn như Cài đặt."</string>
- <string name="color_apply" msgid="9212602012641034283">"Ãp dụng"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Xác nhận cài đặt"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Một số cài đặt màu có thể khiến thiết bị này không sử dụng được. Hãy nhấp vào OK để xác nhận các cài đặt màu này, nếu không những cài đặt này sẽ được đặt lại sau 10 giây."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Mức sử dụng pin"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Trình tiết kiệm pin không khả dụng trong khi sạc"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Trình tiết kiệm pin"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index beb08d1eccec..cfb4873a7bdf 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -253,10 +253,10 @@
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"通知设置"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g>设置"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"å±å¹•会自动旋转。"</string>
- <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"å±å¹•é”å®šä¸ºæ¨ªå‘æ¨¡å¼ã€‚"</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"å±å¹•é”å®šä¸ºæ¨ªå±æ¨¡å¼ã€‚"</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"å±å¹•é”å®šä¸ºçºµå‘æ¨¡å¼ã€‚"</string>
<string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"å±å¹•将会自动旋转。"</string>
- <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"å±å¹•现已é”å®šä¸ºæ¨ªå‘æ¨¡å¼ã€‚"</string>
+ <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"å±å¹•现已é”å®šä¸ºæ¨ªå±æ¨¡å¼ã€‚"</string>
<string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"å±å¹•现已é”å®šä¸ºçºµå‘æ¨¡å¼ã€‚"</string>
<string name="dessert_case" msgid="1295161776223959221">"甜å“ç›’"</string>
<string name="start_dreams" msgid="5640361424498338327">"å±ä¿"</string>
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"更多设置"</string>
<string name="notification_done" msgid="5279426047273930175">"完æˆ"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g>通知设置"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"颜色和外观"</string>
- <string name="night_mode" msgid="3540405868248625488">"夜间模å¼"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"校准显示å±"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"å¼€å¯"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"关闭"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"自动开å¯"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"æ ¹æ®åœ°ç‚¹å’Œæ—¶é—´é€‚时切æ¢åˆ°å¤œé—´æ¨¡å¼"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"夜间模å¼å¼€å¯æ—¶"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"对 Android æ“作系统使用深色主题背景"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"调整色调"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"调整亮度"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"系统会将深色主题背景应用于 Android æ“作系统的核心区域(通常以浅色主题背景显示),例如“设置â€éƒ¨åˆ†ã€‚"</string>
- <string name="color_apply" msgid="9212602012641034283">"应用"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"确认设置"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"部分颜色设置å¯èƒ½ä¼šå¯¼è‡´æ­¤è®¾å¤‡æ— æ³•使用。请点击“确定â€ç¡®è®¤è¿™äº›é¢œè‰²è®¾ç½®ï¼Œå¦åˆ™ï¼Œç³»ç»Ÿå°†åœ¨ 10 ç§’åŽé‡ç½®è¿™äº›è®¾ç½®ã€‚"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"电池使用情况"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"充电过程中无法使用çœç”µæ¨¡å¼"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"çœç”µæ¨¡å¼"</string>
@@ -555,7 +540,7 @@
<string name="keyboard_key_media_rewind" msgid="2654808213360820186">"快退"</string>
<string name="keyboard_key_media_fast_forward" msgid="3849417047738200605">"å¿«è¿›"</string>
<string name="keyboard_key_page_up" msgid="5654098530106845603">"å‘上翻页"</string>
- <string name="keyboard_key_page_down" msgid="8720502083731906136">"å‘下翻页"</string>
+ <string name="keyboard_key_page_down" msgid="8720502083731906136">"PgDn"</string>
<string name="keyboard_key_forward_del" msgid="1391451334716490176">"删除"</string>
<string name="keyboard_key_move_home" msgid="2765693292069487486">"Home"</string>
<string name="keyboard_key_move_end" msgid="5901174332047975247">"End"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 9d25d711d885..d1f2c922216f 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -519,21 +519,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完æˆ"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"「<xliff:g id="APP_NAME">%1$s</xliff:g>ã€é€šçŸ¥æŽ§åˆ¶é …"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"é¡è‰²å’Œå¤–è§€"</string>
- <string name="night_mode" msgid="3540405868248625488">"夜間模å¼"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"校準螢幕"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"已開啟"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"已關閉"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"自動開啟"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"在é©ç•¶çš„ä½ç½®å’Œæ™‚間切æ›è‡³ã€Œå¤œé–“模å¼ã€"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"「夜間模å¼ã€é–‹å•Ÿæ™‚"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"在 Android OS 中使用深色主題背景"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"調整色調"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"調整亮度"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"系統會將深色主題背景套用至 Android OS 核心å€åŸŸ (一般以淺色主題背景顯示),例如「設定ã€ã€‚"</string>
- <string name="color_apply" msgid="9212602012641034283">"套用"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"確èªè¨­å®š"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"部分é¡è‰²è¨­å®šæœƒä»¤æ­¤è£ç½®ç„¡æ³•使用。請按一下 [確定] 加以確èªï¼Œå¦å‰‡é€™äº›é¡è‰²è¨­å®šå°‡æ–¼ 10 秒後é‡è¨­ã€‚"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"電池用é‡"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"充電時無法使用「çœé›»æ¨¡å¼ã€"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"çœé›»æ¨¡å¼"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 8979b85c5cd9..d0288eb1f2ed 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完æˆ"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"「<xliff:g id="APP_NAME">%1$s</xliff:g>ã€é€šçŸ¥æŽ§åˆ¶é …"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"é¡è‰²å’Œå¤–è§€"</string>
- <string name="night_mode" msgid="3540405868248625488">"夜間模å¼"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"校正顯示畫é¢"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"開啟"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"關閉"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"自動開啟"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"æ ¹æ“šåœ°é»žå’Œæ™‚æ®µé©æ™‚切æ›åˆ°ã€Œå¤œé–“模å¼ã€"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"「夜間模å¼ã€é–‹å•Ÿæ™‚"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"é‡å° Android 作業系統使用深色主題"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"調整色調"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"調整亮度"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"深色主題會套用到 Android 作業系統的核心å€å¡Š (一般是以淺色主題顯示),例如「設定ã€å€å¡Šã€‚"</string>
- <string name="color_apply" msgid="9212602012641034283">"套用"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"確èªè¨­å®š"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"部分é¡è‰²è¨­å®šå¯èƒ½æœƒé€ æˆé€™éƒ¨è£ç½®ç„¡æ³•使用。請按一下 [確定] ä¾†ç¢ºèªæ‚¨è¦ä½¿ç”¨é€™é¡žé¡è‰²è¨­å®šï¼Œå¦å‰‡ç³»çµ±å°‡åœ¨ 10 秒後é‡è¨­é€™äº›è¨­å®šã€‚"</string>
<string name="battery_panel_title" msgid="7944156115535366613">"電池用é‡"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"å……é›»æ™‚ç„¡æ³•ä½¿ç”¨ç¯€ç´„è€—é›»é‡æ¨¡å¼"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"節約耗電é‡"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index b4526bd03156..5a562932e2c2 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -517,21 +517,6 @@
<string name="notification_more_settings" msgid="816306283396553571">"Izilungiselelo eziningi"</string>
<string name="notification_done" msgid="5279426047273930175">"Kwenziwe"</string>
<string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> izilawuli zasaziso"</string>
- <string name="color_and_appearance" msgid="1254323855964993144">"Umbala nokubonakala"</string>
- <string name="night_mode" msgid="3540405868248625488">"Imodi yasebusuku"</string>
- <string name="calibrate_display" msgid="5974642573432039217">"Sika isibonisi"</string>
- <string name="night_mode_on" msgid="5597545513026541108">"Vuliwe"</string>
- <string name="night_mode_off" msgid="8035605276956057508">"Valiwe"</string>
- <string name="turn_on_automatically" msgid="4167565356762016083">"Vula ngokuzenzakalela"</string>
- <string name="turn_on_auto_summary" msgid="2190994512406701520">"Shintshela kwimodi yasebusuku njengokuqondile ngendawo nesikhathi sosuku"</string>
- <string name="when_night_mode_on" msgid="2969436026899172821">"Uma imodi yasebusuku ivulekile"</string>
- <string name="use_dark_theme" msgid="2900938704964299312">"Sebenzisa ingqikithi emnyama ku-Android OS"</string>
- <string name="adjust_tint" msgid="3398569573231409878">"Lungisa i-tint"</string>
- <string name="adjust_brightness" msgid="980039329808178246">"Lungisa ukukhanya"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Itimu emnyama isetshenziswa ezindaweni eziqinile ze-Android OS ezivamise ukuoniswa ngetimu ekhanyayo, efana nezilungiselelo."</string>
- <string name="color_apply" msgid="9212602012641034283">"Sebenzisa"</string>
- <string name="color_revert_title" msgid="4746666545480534663">"Qinisekisa izilungiselelo"</string>
- <string name="color_revert_message" msgid="9116001069397996691">"Ezinye izilungiselelo zombala zingenza le divayisi ingasebenziseki. Chofoza ku-KULUNGILE ukuze uqinisekise lezi zilungiselelo zombala, uma kungenjalo lezi zilungiselelo zizosethwa kabusha ngemuva kwamasekhondi angu-10."</string>
<string name="battery_panel_title" msgid="7944156115535366613">"Ukusetshenziswa kwebhethri"</string>
<string name="battery_detail_charging_summary" msgid="1279095653533044008">"Isilondolozi sebhethri asitholakali ngesikhathi sokushaja"</string>
<string name="battery_detail_switch_title" msgid="6285872470260795421">"Isilondolozi sebhethri"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e1cbbc5c9c54..ae4f3cf37ce7 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -375,6 +375,8 @@
<!-- The font size of the date in QS -->
<dimen name="qs_date_collapsed_size">14sp</dimen>
+ <!-- Amount the date/time move when emergency calls only is present -->
+ <dimen name="qs_date_time_translation">8dp</dimen>
<!-- Battery level text padding end when in expanded QS and on Keyguard -->
<dimen name="battery_level_padding_end">2dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4f523f3f8138..a0cb61ab301e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -354,6 +354,9 @@
<!-- Content description of the data connection type LTE for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_data_connection_lte">LTE</string>
+ <!-- Content description of the data connection type LTE+ for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_data_connection_lte_plus">LTE+</string>
+
<!-- Content description of the data connection type CDMA for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_data_connection_cdma">CDMA</string>
@@ -752,6 +755,12 @@
<string name="quick_settings_cellular_detail_data_warning"><xliff:g id="data_limit" example="2.0 GB">%s</xliff:g> warning</string>
<!-- QuickSettings: Work mode [CHAR LIMIT=NONE] -->
<string name="quick_settings_work_mode_label">Work mode</string>
+ <!-- QuickSettings: Label for the toggle to activate Night display (renamed "Night Light" with title caps). [CHAR LIMIT=20] -->
+ <string name="quick_settings_night_display_label">Night Light</string>
+ <!-- QuickSettings: Summary for the toggle to deactivate Night display when it's on (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_night_display_summary_on">Night Light on, tap to turn off</string>
+ <!-- QuickSettings: Label for the toggle to activate Night display when it's off (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_night_display_summary_off">Night Light off, tap to turn on</string>
<!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
<string name="recents_empty_message">No recent items</string>
@@ -1336,59 +1345,6 @@
<!-- Notification: Gear: Content description for the gear. [CHAR LIMIT=NONE] -->
<string name="notification_gear_accessibility"><xliff:g id="app_name" example="YouTube">%1$s</xliff:g> notification controls</string>
- <!-- SysUI Tuner: Color and appearance screen title [CHAR LIMIT=50] -->
- <string name="color_and_appearance">Color and appearance</string>
-
- <!-- SysUI Tuner: Name of the night mode feature [CHAR LIMIT=30] -->
- <string name="night_mode">Night mode</string>
-
- <!-- SysUI Tuner: Name of calibrate display dialog [CHAR LIMIT=30] -->
- <string name="calibrate_display">Calibrate display</string>
-
- <!-- SysUI Tuner: Summary of night mode when its on [CHAR LIMIT=NONE] -->
- <string name="night_mode_on">On</string>
-
- <!-- SysUI Tuner: Summary of night mode when its off [CHAR LIMIT=NONE] -->
- <string name="night_mode_off">Off</string>
-
- <!-- SysUI Tuner: Label for switch to turn on night mode automatically [CHAR LIMIT=50] -->
- <string name="turn_on_automatically">Turn on automatically</string>
-
- <!-- SysUI Tuner: Summary for switch to turn on night mode automatically [CHAR LIMIT=NONE] -->
- <string name="turn_on_auto_summary">Switch into Night Mode as appropriate for location and time of day</string>
-
- <!-- SysUI Tuner: Label for section controlling what night mode does [CHAR LIMIT=60] -->
- <string name="when_night_mode_on">When Night Mode is on</string>
-
- <!-- SysUI Tuner: Switch controlling whether dark theme is turned on with night mode [CHAR LIMIT=45] -->
- <string name="use_dark_theme">Use dark theme for Android OS</string>
-
- <!-- SysUI Tuner: Switch controlling whether tint is changed with night mode [CHAR LIMIT=45] -->
- <string name="adjust_tint">Adjust tint</string>
-
- <!-- SysUI Tuner: Switch controlling whether brightness is changed with night mode [CHAR LIMIT=45] -->
- <string name="adjust_brightness">Adjust brightness</string>
-
- <!-- SysUI Tuner: Disclaimer about using dark theme with night mode [CHAR LIMIT=NONE] -->
- <string name="night_mode_disclaimer">The dark theme is applied to
- core areas of Android OS that are normally displayed in a light theme,
- such as Settings.</string>
-
- <!-- Button to apply settings [CHAR LIMIT=30] -->
- <string name="color_apply">Apply</string>
-
- <!-- Title of warning dialog about bad color settings. [CHAR LIMIT=30] -->
- <string name="color_revert_title">Confirm settings</string>
-
- <!-- Message warning user about custom color settings [CHAR LIMIT=NONE] -->
- <string name="color_revert_message">Some color settings can make this
- device unusable. Click OK to confirm these color settings,
- otherwise these settings will reset after 10 seconds.</string>
-
- <string name="color_modification_r" translatable="false">R</string>
- <string name="color_modification_g" translatable="false">G</string>
- <string name="color_modification_b" translatable="false">B</string>
-
<!-- Title of the battery settings detail panel [CHAR LIMIT=20] -->
<string name="battery_panel_title">Battery usage</string>
diff --git a/packages/SystemUI/res/xml/night_mode.xml b/packages/SystemUI/res/xml/night_mode.xml
deleted file mode 100644
index 34af8208076f..000000000000
--- a/packages/SystemUI/res/xml/night_mode.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?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.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:sysui="http://schemas.android.com/apk/res-auto"
- android:title="@string/night_mode">
-
- <SwitchPreference
- android:key="auto"
- android:title="@string/turn_on_automatically"
- android:summary="@string/turn_on_auto_summary" />
-
- <PreferenceCategory
- android:title="@string/when_night_mode_on">
-
- <SwitchPreference
- android:key="adjust_tint"
- android:title="@string/adjust_tint" />
-
- <SwitchPreference
- android:key="adjust_brightness"
- android:title="@string/adjust_brightness" />
-
- </PreferenceCategory>
-
-</PreferenceScreen>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 116bc69fd0d4..b46e862471f3 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -100,13 +100,6 @@
</PreferenceScreen>
- <!--
- <Preference
- android:key="color_transform"
- android:title="@string/color_and_appearance"
- android:fragment="com.android.systemui.tuner.ColorAndAppearanceFragment" />
- -->
-
<PreferenceScreen
android:key="volume_and_do_not_disturb"
android:title="@string/volume_and_do_not_disturb">
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 907616c62f29..19ae2954bb2a 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -47,7 +47,6 @@ public final class Prefs {
Key.QS_DATA_SAVER_DIALOG_SHOWN,
Key.QS_INVERT_COLORS_ADDED,
Key.QS_WORK_ADDED,
- Key.QS_NIGHT_ADDED,
})
public @interface Key {
String OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME = "OverviewLastStackTaskActiveTime";
@@ -67,7 +66,6 @@ public final class Prefs {
String QS_DATA_SAVER_DIALOG_SHOWN = "QsDataSaverDialogShown";
String QS_INVERT_COLORS_ADDED = "QsInvertColorsAdded";
String QS_WORK_ADDED = "QsWorkAdded";
- String QS_NIGHT_ADDED = "QsNightAdded";
}
public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 9a36aca97d75..06ce88cc4383 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -28,6 +28,7 @@ import com.android.systemui.assist.AssistManager;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.QSTileHost;
@@ -92,7 +93,7 @@ public class SystemUIFactory {
}
public ScrimController createScrimController(ScrimView scrimBehind, ScrimView scrimInFront,
- View headsUpScrim) {
+ View headsUpScrim, LockscreenWallpaper lockscreenWallpaper) {
return new ScrimController(scrimBehind, scrimInFront, headsUpScrim);
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index af2a2869bc30..9eceeacc3968 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -47,7 +47,7 @@ public class AssistManager {
private static final long TIMEOUT_SERVICE = 2500;
private static final long TIMEOUT_ACTIVITY = 1000;
- private final Context mContext;
+ protected final Context mContext;
private final WindowManager mWindowManager;
private final AssistDisclosure mAssistDisclosure;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index a40e5b7789c6..c63be9ce9760 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -63,7 +63,6 @@ public class QSDetail extends LinearLayout {
private boolean mScanState;
private boolean mClosingDetail;
private boolean mFullyExpanded;
- private View mQsDetailHeaderBack;
private BaseStatusBarHeader mHeader;
private boolean mTriggeredExpand;
private int mOpenX;
@@ -92,7 +91,6 @@ public class QSDetail extends LinearLayout {
mDetailDoneButton = (TextView) findViewById(android.R.id.button1);
mQsDetailHeader = findViewById(R.id.qs_detail_header);
- mQsDetailHeaderBack = mQsDetailHeader.findViewById(com.android.internal.R.id.up);
mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title);
mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle);
mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress);
@@ -109,7 +107,6 @@ public class QSDetail extends LinearLayout {
mQsPanel.closeDetail();
}
};
- mQsDetailHeaderBack.setOnClickListener(doneListener);
mDetailDoneButton.setOnClickListener(doneListener);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 27b079a06c99..ca853feb1a1f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -39,7 +39,6 @@ import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.NightModeController;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -447,7 +446,6 @@ public abstract class QSTile<TState extends State> {
UserInfoController getUserInfoController();
BatteryController getBatteryController();
TileServices getTileServices();
- NightModeController getNightModeController();
void removeTile(String tileSpec);
ManagedProfileController getManagedProfileController();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
new file mode 100644
index 000000000000..9a3549eb6a75
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.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.systemui.qs.tiles;
+
+import android.content.Intent;
+import android.provider.Settings;
+import android.widget.Switch;
+
+import com.android.internal.app.NightDisplayController;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+
+public class NightDisplayTile extends QSTile<QSTile.BooleanState>
+ implements NightDisplayController.Callback {
+
+ private final NightDisplayController mController;
+
+ public NightDisplayTile(Host host) {
+ super(host);
+ mController = new NightDisplayController(mContext);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return NightDisplayController.isAvailable(mContext);
+ }
+
+ @Override
+ public BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ final boolean activated = !mState.value;
+ MetricsLogger.action(mContext, getMetricsCategory(), activated);
+ mController.setActivated(activated);
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ final boolean isActivated = mController.isActivated();
+ state.value = isActivated;
+ state.label = mContext.getString(R.string.quick_settings_night_display_label);
+ state.icon = ResourceIcon.get(isActivated ? R.drawable.ic_qs_night_display_on
+ : R.drawable.ic_qs_night_display_off);
+ state.contentDescription = mContext.getString(isActivated
+ ? R.string.quick_settings_night_display_summary_on
+ : R.string.quick_settings_night_display_summary_off);
+ state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
+ = Switch.class.getName();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.QS_NIGHT_DISPLAY;
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return new Intent(Settings.ACTION_DISPLAY_SETTINGS);
+ }
+
+ @Override
+ protected void setListening(boolean listening) {
+ if (listening) {
+ mController.setListener(this);
+ refreshState();
+ } else {
+ mController.setListener(null);
+ }
+ }
+
+ @Override
+ public CharSequence getTileLabel() {
+ return mContext.getString(R.string.quick_settings_night_display_label);
+ }
+
+ @Override
+ public void onActivated(boolean activated) {
+ refreshState();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 58fbd4c954d2..b74247960fc7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -24,7 +24,6 @@ import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DataSaverController.Listener;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController.Callback;
-import com.android.systemui.statusbar.policy.NightModeController;
/**
* Manages which tiles should be automatically added to QS.
@@ -67,35 +66,12 @@ public class AutoTileManager {
if (!Prefs.getBoolean(context, Key.QS_WORK_ADDED, false)) {
host.getManagedProfileController().addCallback(mProfileCallback);
}
- if (!Prefs.getBoolean(context, Key.QS_NIGHT_ADDED, false)) {
- host.getNightModeController().addListener(mNightModeListener);
- }
}
public void destroy() {
// TODO: Remove any registered listeners.
}
- private final NightModeController.Listener mNightModeListener =
- new NightModeController.Listener() {
- @Override
- public void onNightModeChanged() {
- if (mHost.getNightModeController().isEnabled()) {
- mHost.addTile("night");
- Prefs.putBoolean(mContext, Key.QS_NIGHT_ADDED, true);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mHost.getNightModeController().removeListener(mNightModeListener);
- }
- });
- }
- }
-
- @Override
- public void onTwilightAutoChanged() { }
- };
-
private final ManagedProfileController.Callback mProfileCallback =
new ManagedProfileController.Callback() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index b53a99907146..63f726b545db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -49,6 +49,13 @@ public class ButtonDispatcher {
mViews.clear();
}
+ void addView(View view, boolean landscape) {
+ addView(view);
+ if (view instanceof ButtonInterface) {
+ ((ButtonInterface) view).setLandscape(landscape);
+ }
+ }
+
void addView(View view) {
mViews.add(view);
view.setOnClickListener(mClickListener);
@@ -178,5 +185,7 @@ public class ButtonDispatcher {
void setImageDrawable(@Nullable Drawable drawable);
void abortCurrentGesture();
+
+ void setLandscape(boolean landscape);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index ee88b0041b7d..b3e86b5dcdaa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -234,7 +234,6 @@ public class KeyguardBouncer {
mKeyguardView.setViewMediatorCallback(mCallback);
mContainer.addView(mRoot, mContainer.getChildCount());
mRoot.setVisibility(View.INVISIBLE);
- mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
}
protected void removeView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index dd46b085e005..06c8b685ff63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -28,7 +28,6 @@ import android.widget.LinearLayout;
import android.widget.Space;
import com.android.systemui.R;
-import com.android.systemui.SystemUIFactory;
import com.android.systemui.statusbar.policy.KeyButtonView;
import com.android.systemui.tuner.TunerService;
@@ -71,6 +70,8 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
private View mLastRot0;
private View mLastRot90;
+ private boolean mAlternativeOrder;
+
public NavigationBarInflaterView(Context context, AttributeSet attrs) {
super(context, attrs);
mDensity = context.getResources().getConfiguration().densityDpi;
@@ -114,6 +115,7 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
false);
mRot90.setId(R.id.rot90);
addView(mRot90);
+ updateAlternativeOrder();
if (getParent() instanceof NavigationBarView) {
((NavigationBarView) getParent()).updateRotatedViews();
}
@@ -152,6 +154,26 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
}
}
+ public void setAlternativeOrder(boolean alternativeOrder) {
+ if (alternativeOrder != mAlternativeOrder) {
+ mAlternativeOrder = alternativeOrder;
+ updateAlternativeOrder();
+ }
+ }
+
+ private void updateAlternativeOrder() {
+ updateAlternativeOrder(mRot0.findViewById(R.id.ends_group));
+ updateAlternativeOrder(mRot0.findViewById(R.id.center_group));
+ updateAlternativeOrder(mRot90.findViewById(R.id.ends_group));
+ updateAlternativeOrder(mRot90.findViewById(R.id.center_group));
+ }
+
+ private void updateAlternativeOrder(View v) {
+ if (v instanceof ReverseLinearLayout) {
+ ((ReverseLinearLayout) v).setAlternativeOrder(mAlternativeOrder);
+ }
+ }
+
private void initiallyFill(ButtonDispatcher buttonDispatcher) {
addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.ends_group));
addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.center_group));
@@ -258,7 +280,7 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
params.width = (int) (params.width * size);
}
parent.addView(v);
- addToDispatchers(v);
+ addToDispatchers(v, landscape);
View lastView = landscape ? mLastRot90 : mLastRot0;
if (lastView != null) {
v.setAccessibilityTraversalAfter(lastView.getId());
@@ -305,16 +327,16 @@ public class NavigationBarInflaterView extends FrameLayout implements TunerServi
return buttonSpec.substring(0, buttonSpec.indexOf(SIZE_MOD_START));
}
- private void addToDispatchers(View v) {
+ private void addToDispatchers(View v, boolean landscape) {
if (mButtonDispatchers != null) {
final int indexOfKey = mButtonDispatchers.indexOfKey(v.getId());
if (indexOfKey >= 0) {
- mButtonDispatchers.valueAt(indexOfKey).addView(v);
+ mButtonDispatchers.valueAt(indexOfKey).addView(v, landscape);
} else if (v instanceof ViewGroup) {
final ViewGroup viewGroup = (ViewGroup)v;
final int N = viewGroup.getChildCount();
for (int i = 0; i < N; i++) {
- addToDispatchers(viewGroup.getChildAt(i));
+ addToDispatchers(viewGroup.getChildAt(i), landscape);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 53fe6ce3efa9..23aeae8c5b33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -99,6 +99,8 @@ public class NavigationBarView extends LinearLayout {
private final SparseArray<ButtonDispatcher> mButtonDisatchers = new SparseArray<>();
private Configuration mConfiguration;
+ private NavigationBarInflaterView mNavigationInflaterView;
+
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
private boolean mHomeAppearing;
@@ -472,9 +474,10 @@ public class NavigationBarView extends LinearLayout {
@Override
public void onFinishInflate() {
+ mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
+ R.id.navigation_inflater);
updateRotatedViews();
- ((NavigationBarInflaterView) findViewById(R.id.navigation_inflater)).setButtonDispatchers(
- mButtonDisatchers);
+ mNavigationInflaterView.setButtonDispatchers(mButtonDisatchers);
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
@@ -530,6 +533,7 @@ public class NavigationBarView extends LinearLayout {
}
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
+ mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
for (int i = 0; i < mButtonDisatchers.size(); i++) {
mButtonDisatchers.valueAt(i).setCurrentView(mCurrentView);
}
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 cb3089a4b1df..fb7afc59b276 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -52,6 +52,7 @@ import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService;
import android.media.AudioAttributes;
import android.media.MediaMetadata;
@@ -200,7 +201,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
- HeadsUpManager.OnHeadsUpChangedListener {
+ HeadsUpManager.OnHeadsUpChangedListener, DisplayManager.DisplayListener {
static final String TAG = "PhoneStatusBar";
public static final boolean DEBUG = BaseStatusBar.DEBUG;
public static final boolean SPEW = false;
@@ -684,6 +685,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mUnlockMethodCache.addListener(this);
startKeyguard();
+ mContext.getSystemService(DisplayManager.class).registerDisplayListener(this, null);
+
mDozeServiceHost = new DozeServiceHost();
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mDozeServiceHost);
putComponent(DozeHost.class, mDozeServiceHost);
@@ -788,11 +791,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);
+ if (ENABLE_LOCKSCREEN_WALLPAPER) {
+ mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
+ }
+
ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
mScrimController = SystemUIFactory.getInstance().createScrimController(
- scrimBehind, scrimInFront, headsUpScrim);
+ scrimBehind, scrimInFront, headsUpScrim, mLockscreenWallpaper);
if (mScrimSrcModeEnabled) {
Runnable runnable = new Runnable() {
@Override
@@ -822,10 +829,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardBottomArea.getLockIcon());
mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
- if (ENABLE_LOCKSCREEN_WALLPAPER) {
- mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
- }
-
// set the initial view visibility
setAreThereNotifications();
@@ -880,9 +883,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mLightStatusBarController = new LightStatusBarController(mIconController,
mBatteryController);
mKeyguardMonitor = new KeyguardMonitor(mContext);
+ mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
+ mHandler, this);
if (UserManager.get(mContext).isUserSwitcherEnabled()) {
- mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
- mHandler, this);
createUserSwitcher();
}
@@ -3503,6 +3506,21 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
@Override
+ public void onDisplayAdded(int displayId) {
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ repositionNavigationBar();
+ }
+ }
+
+ @Override
public void userSwitched(int newUserId) {
super.userSwitched(newUserId);
if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
@@ -3513,6 +3531,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
setControllerUsers();
clearCurrentMediaNotification();
mLockscreenWallpaper.setCurrentUser(newUserId);
+ mScrimController.setCurrentUser(newUserId);
updateMediaMetaData(true, false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 011ec22d2b3b..15e235dd4d5f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -52,6 +52,7 @@ import com.android.systemui.qs.tiles.FlashlightTile;
import com.android.systemui.qs.tiles.HotspotTile;
import com.android.systemui.qs.tiles.IntentTile;
import com.android.systemui.qs.tiles.LocationTile;
+import com.android.systemui.qs.tiles.NightDisplayTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.qs.tiles.UserTile;
import com.android.systemui.qs.tiles.WifiTile;
@@ -60,7 +61,6 @@ import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.NightModeController;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -71,7 +71,6 @@ import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.tuner.NightModeTile;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -111,7 +110,6 @@ public class QSTileHost implements QSTile.Host, Tunable {
private final TileServices mServices;
private final List<Callback> mCallbacks = new ArrayList<>();
- private final NightModeController mNightModeController;
private final AutoTileManager mAutoTiles;
private final ManagedProfileController mProfileController;
private final NextAlarmController mNextAlarmController;
@@ -144,7 +142,6 @@ public class QSTileHost implements QSTile.Host, Tunable {
mBattery = battery;
mIconController = iconController;
mNextAlarmController = nextAlarmController;
- mNightModeController = new NightModeController(mContext, true);
mProfileController = new ManagedProfileController(this);
final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
@@ -308,10 +305,6 @@ public class QSTileHost implements QSTile.Host, Tunable {
return mIconController;
}
- public NightModeController getNightModeController() {
- return mNightModeController;
- }
-
public ManagedProfileController getManagedProfileController() {
return mProfileController;
}
@@ -448,8 +441,7 @@ public class QSTileHost implements QSTile.Host, Tunable {
else if (tileSpec.equals("user")) return new UserTile(this);
else if (tileSpec.equals("battery")) return new BatteryTile(this);
else if (tileSpec.equals("saver")) return new DataSaverTile(this);
- else if (tileSpec.equals(NightModeTile.NIGHT_MODE_SPEC))
- return new NightModeTile(this);
+ else if (tileSpec.equals("night")) return new NightDisplayTile(this);
// Intent tiles.
else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
else if (tileSpec.startsWith(CustomTile.PREFIX)) return CustomTile.create(this,tileSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 85303f422925..21db64febbe0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -37,11 +37,11 @@ import com.android.internal.logging.MetricsProto;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
-import com.android.systemui.qs.QSAnimator;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSPanel.Callback;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.TouchAnimator;
+import com.android.systemui.qs.TouchAnimator.Builder;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
@@ -84,13 +84,13 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
private ImageView mMultiUserAvatar;
- private TouchAnimator mSecondHalfAnimator;
- private TouchAnimator mFirstHalfAnimator;
+ private TouchAnimator mAnimator;
protected TouchAnimator mSettingsAlpha;
private float mExpansionAmount;
private QSTileHost mHost;
private View mEdit;
private boolean mShowFullAlarm;
+ private float mDateTimeTranslation;
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -111,6 +111,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
mDateTimeGroup = (ViewGroup) findViewById(R.id.date_time_group);
mDateTimeGroup.setPivotX(0);
mDateTimeGroup.setPivotY(0);
+ mDateTimeTranslation = getResources().getDimension(R.dimen.qs_date_time_translation);
mShowFullAlarm = getResources().getBoolean(R.bool.quick_settings_show_full_alarm);
mExpandIndicator = (ExpandableIndicator) findViewById(R.id.expand_indicator);
@@ -152,15 +153,13 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
FontSizeUtils.updateFontSize(mEmergencyOnly, R.dimen.qs_emergency_calls_only_text_size);
- mSecondHalfAnimator = new TouchAnimator.Builder()
+ Builder builder = new Builder()
.addFloat(mShowFullAlarm ? mAlarmStatus : findViewById(R.id.date), "alpha", 0, 1)
- .addFloat(mEmergencyOnly, "alpha", 0, 1)
- .build();
+ .addFloat(mEmergencyOnly, "alpha", 0, 1);
if (mShowFullAlarm) {
- mFirstHalfAnimator = new TouchAnimator.Builder()
- .addFloat(mAlarmStatusCollapsed, "alpha", 1, 0)
- .build();
+ builder.addFloat(mAlarmStatusCollapsed, "alpha", 1, 0);
}
+ mAnimator = builder.build();
updateSettingsAnimator();
}
@@ -223,10 +222,8 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
@Override
public void setExpansion(float headerExpansionFraction) {
mExpansionAmount = headerExpansionFraction;
- mSecondHalfAnimator.setPosition(headerExpansionFraction);
- if (mShowFullAlarm) {
- mFirstHalfAnimator.setPosition(headerExpansionFraction);
- }
+ updateDateTimePosition();
+ mAnimator.setPosition(headerExpansionFraction);
mSettingsAlpha.setPosition(headerExpansionFraction);
updateAlarmVisibilities();
@@ -264,6 +261,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
protected void updateVisibilities() {
updateAlarmVisibilities();
+ updateDateTimePosition();
mEmergencyOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly
? View.VISIBLE : View.INVISIBLE);
mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
@@ -274,6 +272,11 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
mEdit.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
}
+ private void updateDateTimePosition() {
+ mDateTimeAlarmGroup.setTranslationY(mShowEmergencyCallsOnly
+ ? mExpansionAmount * mDateTimeTranslation : 0);
+ }
+
private void updateListeners() {
if (mListening) {
mNextAlarmController.addStateChangedCallback(this);
@@ -315,7 +318,8 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
public void onClick(View v) {
if (v == mSettingsButton) {
MetricsLogger.action(mContext,
- MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH);
+ mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
+ : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
if (mSettingsButton.isTunerClick()) {
if (TunerService.isTunerEnabled(mContext)) {
TunerService.showResetRequest(mContext, new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
index 3682aa1b06f8..f45967a0a0a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ReverseLinearLayout.java
@@ -30,7 +30,11 @@ import java.util.ArrayList;
*/
public class ReverseLinearLayout extends LinearLayout {
- private boolean mIsLayoutRtl;
+ /** If true, the layout is reversed vs. a regular linear layout */
+ private boolean mIsLayoutReverse;
+
+ /** If true, the layout is opposite to it's natural reversity from the layout direction */
+ private boolean mIsAlternativeOrder;
public ReverseLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -39,45 +43,50 @@ public class ReverseLinearLayout extends LinearLayout {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mIsLayoutRtl = getResources().getConfiguration()
- .getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ updateOrder();
}
@Override
public void addView(View child) {
reversParams(child.getLayoutParams());
- if (mIsLayoutRtl) {
- super.addView(child);
- } else {
+ if (mIsLayoutReverse) {
super.addView(child, 0);
+ } else {
+ super.addView(child);
}
}
@Override
public void addView(View child, ViewGroup.LayoutParams params) {
reversParams(params);
- if (mIsLayoutRtl) {
- super.addView(child, params);
- } else {
+ if (mIsLayoutReverse) {
super.addView(child, 0, params);
+ } else {
+ super.addView(child, params);
}
}
@Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- updateRTLOrder();
+ public void onRtlPropertiesChanged(int layoutDirection) {
+ super.onRtlPropertiesChanged(layoutDirection);
+ updateOrder();
+ }
+
+ public void setAlternativeOrder(boolean alternative) {
+ mIsAlternativeOrder = alternative;
+ updateOrder();
}
/**
* In landscape, the LinearLayout is not auto mirrored since it is vertical. Therefore we
* have to do it manually
*/
- private void updateRTLOrder() {
- boolean isLayoutRtl = getResources().getConfiguration()
- .getLayoutDirection() == LAYOUT_DIRECTION_RTL;
- if (mIsLayoutRtl != isLayoutRtl) {
- // RTL changed, swap the order of all views.
+ private void updateOrder() {
+ boolean isLayoutRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ boolean isLayoutReverse = isLayoutRtl ^ mIsAlternativeOrder;
+
+ if (mIsLayoutReverse != isLayoutReverse) {
+ // reversity changed, swap the order of all views.
int childCount = getChildCount();
ArrayList<View> childList = new ArrayList<>(childCount);
for (int i = 0; i < childCount; i++) {
@@ -87,7 +96,7 @@ public class ReverseLinearLayout extends LinearLayout {
for (int i = childCount - 1; i >= 0; i--) {
super.addView(childList.get(i));
}
- mIsLayoutRtl = isLayoutRtl;
+ mIsLayoutReverse = isLayoutReverse;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 135c294987cf..8b87a7fa1596 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -30,6 +30,7 @@ import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationData;
@@ -46,10 +47,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
public static final long ANIMATION_DURATION = 220;
public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR
= new PathInterpolator(0f, 0, 0.7f, 1f);
+ public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR_LOCKED
+ = new PathInterpolator(0.3f, 0f, 0.8f, 1f);
private static final float SCRIM_BEHIND_ALPHA = 0.62f;
- private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.45f;
- private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
+ protected static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.45f;
+ protected static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
+ private static final float SCRIM_IN_FRONT_ALPHA_LOCKED = 0.85f;
private static final int TAG_KEY_ANIM = R.id.scrim;
private static final int TAG_KEY_ANIM_TARGET = R.id.scrim_target;
private static final int TAG_START_ALPHA = R.id.scrim_alpha_start;
@@ -59,6 +63,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
private final ScrimView mScrimInFront;
private final UnlockMethodCache mUnlockMethodCache;
private final View mHeadsUpScrim;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private float mScrimBehindAlpha = SCRIM_BEHIND_ALPHA;
private float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
@@ -99,6 +104,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mHeadsUpScrim = headsUpScrim;
final Context context = scrimBehind.getContext();
mUnlockMethodCache = UnlockMethodCache.getInstance(context);
+ mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
updateHeadsUpScrim(false);
}
@@ -120,6 +126,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
scheduleUpdate();
}
+ protected void setScrimBehindValues(float scrimBehindAlphaKeyguard,
+ float scrimBehindAlphaUnlocking) {
+ mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard;
+ mScrimBehindAlphaUnlocking = scrimBehindAlphaUnlocking;
+ scheduleUpdate();
+ }
+
public void onTrackingStarted() {
mExpanding = true;
mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer();
@@ -162,11 +175,19 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mAnimateChange = true;
mSkipFirstFrame = skipFirstFrame;
mOnAnimationFinished = onAnimationFinished;
- scheduleUpdate();
- // No need to wait for the next frame to be drawn for this case - onPreDraw will execute
- // the changes we just scheduled.
- onPreDraw();
+ if (mKeyguardUpdateMonitor.isUserUnlocked()) {
+ scheduleUpdate();
+
+ // No need to wait for the next frame to be drawn for this case - onPreDraw will execute
+ // the changes we just scheduled.
+ onPreDraw();
+ } else {
+
+ // In case the user isn't unlocked, make sure to delay a bit because the system is hosed
+ // with too many things in this case, in order to not skip the initial frames.
+ mScrimInFront.postOnAnimationDelayed(this::scheduleUpdate, 16);
+ }
}
public void abortKeyguardFadingOut() {
@@ -211,6 +232,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
return mDozeInFrontAlpha;
}
+ private float getScrimInFrontAlpha() {
+ return mKeyguardUpdateMonitor.isUserUnlocked()
+ ? SCRIM_IN_FRONT_ALPHA
+ : SCRIM_IN_FRONT_ALPHA_LOCKED;
+ }
private void scheduleUpdate() {
if (mUpdatePending) return;
@@ -250,10 +276,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
float fraction = 1 - behindFraction;
fraction = (float) Math.pow(fraction, 0.8f);
behindFraction = (float) Math.pow(behindFraction, 0.8f);
- setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA);
+ setScrimInFrontColor(fraction * getScrimInFrontAlpha());
setScrimBehindColor(behindFraction * mScrimBehindAlphaKeyguard);
} else if (mBouncerShowing) {
- setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA);
+ setScrimInFrontColor(getScrimInFrontAlpha());
setScrimBehindColor(0f);
} else {
float fraction = Math.max(0, Math.min(mFraction, 1));
@@ -371,7 +397,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
}
private Interpolator getInterpolator() {
- return mAnimateKeyguardFadingOut ? KEYGUARD_FADE_OUT_INTERPOLATOR : mInterpolator;
+ if (mAnimateKeyguardFadingOut && !mKeyguardUpdateMonitor.isUserUnlocked()) {
+ return KEYGUARD_FADE_OUT_INTERPOLATOR_LOCKED;
+ } else if (mAnimateKeyguardFadingOut) {
+ return KEYGUARD_FADE_OUT_INTERPOLATOR;
+ } else {
+ return mInterpolator;
+ }
}
@Override
@@ -542,4 +574,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
R.dimen.heads_up_scrim_height);
mHeadsUpScrim.setLayoutParams(layoutParams);
}
+
+ public void setCurrentUser(int currentUser) {
+ // Don't care in the base class.
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index f415ae588c4e..0c9bfab794d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -338,11 +338,12 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl
public void dump(PrintWriter pw) {
int N = mStatusIcons.getChildCount();
- pw.println(" system icons: " + N);
+ pw.println(" icon views: " + N);
for (int i=0; i<N; i++) {
StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i);
pw.println(" [" + i + "] icon=" + ic);
}
+ super.dump(pw);
}
public void dispatchDemoCommand(String command, Bundle args) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index 97b31f248fa1..682187926762 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -81,9 +81,9 @@ public class StatusBarIconList {
public void dump(PrintWriter pw) {
final int N = mSlots.size();
- pw.println("Icon list:");
+ pw.println(" icon slots: " + N);
for (int i=0; i<N; i++) {
- pw.printf(" %2d: (%s) %s\n", i, mSlots.get(i), mIcons.get(i));
+ pw.printf(" %2d: (%s) %s\n", i, mSlots.get(i), mIcons.get(i));
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 8d0d9cb27cea..3691a42447ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -53,6 +53,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private static final long WAKE_AND_UNLOCK_SCRIM_FADEOUT_DURATION_MS = 200;
+ // Duration of the Keyguard dismissal animation in case the user is currently locked. This is to
+ // make everything a bit slower to bridge a gap until the user is unlocked and home screen has
+ // dranw its first frame.
+ private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000;
+
private static String TAG = "StatusBarKeyguardViewManager";
protected final Context mContext;
@@ -274,9 +279,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
/**
* Hides the keyguard view
*/
- public void hide(long startTime, final long fadeoutDuration) {
+ public void hide(long startTime, long fadeoutDuration) {
mShowing = false;
+ if (!KeyguardUpdateMonitor.getInstance(mContext).isUserUnlocked()) {
+ fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
+ }
long uptimeMillis = SystemClock.uptimeMillis();
long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 5d734c682b49..b9c7a4b411ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -89,14 +89,18 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
@Override
public void addStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
- mChangeCallbacks.add(cb);
+ synchronized (mChangeCallbacks) {
+ mChangeCallbacks.add(cb);
+ }
cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
cb.onPowerSaveChanged(mPowerSave);
}
@Override
public void removeStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
- mChangeCallbacks.remove(cb);
+ synchronized (mChangeCallbacks) {
+ mChangeCallbacks.remove(cb);
+ }
}
@Override
@@ -171,16 +175,20 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
}
protected void fireBatteryLevelChanged() {
- final int N = mChangeCallbacks.size();
- for (int i = 0; i < N; i++) {
- mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ synchronized (mChangeCallbacks) {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
+ }
}
}
private void firePowerSaveChanged() {
- final int N = mChangeCallbacks.size();
- for (int i = 0; i < N; i++) {
- mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
+ synchronized (mChangeCallbacks) {
+ final int N = mChangeCallbacks.size();
+ for (int i = 0; i < N; i++) {
+ mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index d8b1a62f49b1..3df759068ae9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -265,6 +265,11 @@ public class KeyButtonView extends ImageView implements ButtonDispatcher.ButtonI
public void setImageDrawable(@Nullable Drawable drawable) {
super.setImageDrawable(drawable);
}
+
+ @Override
+ public void setLandscape(boolean landscape) {
+ //no op
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index ac3246d5ff6b..8178bdaded04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -201,7 +201,7 @@ public class MobileSignalController extends SignalController<
TelephonyIcons.FOUR_G_PLUS);
} else {
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
- mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, TelephonyIcons.LTE);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE_CA, TelephonyIcons.LTE_PLUS);
}
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_IWLAN, TelephonyIcons.WFC);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 7a042af7f42e..a31bc04d8318 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -786,6 +786,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
datatype.equals("g") ? TelephonyIcons.G :
datatype.equals("h") ? TelephonyIcons.H :
datatype.equals("lte") ? TelephonyIcons.LTE :
+ datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
datatype.equals("roam") ? TelephonyIcons.ROAMING :
TelephonyIcons.UNKNOWN;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java
deleted file mode 100644
index 4611ef9f31db..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NightModeController.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.statusbar.policy;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.opengl.Matrix;
-import android.provider.Settings.Secure;
-import android.util.MathUtils;
-import com.android.systemui.tuner.TunerService;
-
-import java.util.ArrayList;
-
-/**
- * Listens for changes to twilight from the TwilightService.
- *
- * Also pushes the current matrix to accessibility based on the current twilight
- * and various tuner settings.
- */
-public class NightModeController implements TunerService.Tunable {
-
- public static final String NIGHT_MODE_ADJUST_TINT = "tuner_night_mode_adjust_tint";
- private static final String COLOR_MATRIX_CUSTOM_VALUES = "tuner_color_custom_values";
-
- private static final String ACTION_TWILIGHT_CHANGED = "android.intent.action.TWILIGHT_CHANGED";
-
- private static final String EXTRA_IS_NIGHT = "isNight";
- private static final String EXTRA_AMOUNT = "amount";
-
- // Night mode ~= 3400 K
- private static final float[] NIGHT_VALUES = new float[] {
- 1, 0, 0, 0,
- 0, .754f, 0, 0,
- 0, 0, .516f, 0,
- 0, 0, 0, 1,
- };
- public static final float[] IDENTITY_MATRIX = new float[] {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
- };
-
- private final ArrayList<Listener> mListeners = new ArrayList<>();
-
- private final Context mContext;
-
- // This is whether or not this is the main NightMode controller in SysUI that should be
- // updating relevant color matrixes or if its in the tuner process getting current state
- // for UI.
- private final boolean mUpdateMatrix;
-
- private float[] mCustomMatrix;
- private boolean mListening;
- private boolean mAdjustTint;
-
- private boolean mIsNight;
- private float mAmount;
- private boolean mIsAuto;
-
- public NightModeController(Context context) {
- this(context, false);
- }
-
- public NightModeController(Context context, boolean updateMatrix) {
- mContext = context;
- mUpdateMatrix = updateMatrix;
- TunerService.get(mContext).addTunable(this, NIGHT_MODE_ADJUST_TINT,
- COLOR_MATRIX_CUSTOM_VALUES, Secure.TWILIGHT_MODE);
- }
-
- public void setNightMode(boolean isNight) {
- if (mIsAuto) {
- if (mIsNight != isNight) {
- TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, isNight
- ? Secure.TWILIGHT_MODE_AUTO_OVERRIDE_ON
- : Secure.TWILIGHT_MODE_AUTO_OVERRIDE_OFF);
- } else {
- TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE,
- Secure.TWILIGHT_MODE_AUTO);
- }
- } else {
- TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, isNight
- ? Secure.TWILIGHT_MODE_LOCKED_ON : Secure.TWILIGHT_MODE_LOCKED_OFF);
- }
- }
-
- public void setAuto(boolean auto) {
- mIsAuto = auto;
- if (auto) {
- TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_AUTO);
- } else {
- // Lock into the current state
- TunerService.get(mContext).setValue(Secure.TWILIGHT_MODE, mIsNight
- ? Secure.TWILIGHT_MODE_LOCKED_ON : Secure.TWILIGHT_MODE_LOCKED_OFF);
- }
- }
-
- public boolean isAuto() {
- return mIsAuto;
- }
-
- public void setAdjustTint(Boolean newValue) {
- TunerService.get(mContext).setValue(NIGHT_MODE_ADJUST_TINT, ((Boolean) newValue) ? 1 : 0);
- }
-
- public void addListener(Listener listener) {
- mListeners.add(listener);
- listener.onNightModeChanged();
- updateListening();
- }
-
- public void removeListener(Listener listener) {
- mListeners.remove(listener);
- updateListening();
- }
-
- private void updateListening() {
- boolean shouldListen = mListeners.size() != 0 || (mUpdateMatrix && mAdjustTint);
- if (shouldListen == mListening) return;
- mListening = shouldListen;
- if (mListening) {
- mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_TWILIGHT_CHANGED));
- } else {
- mContext.unregisterReceiver(mReceiver);
- }
- }
-
- public boolean isEnabled() {
- if (!mListening) {
- updateNightMode(mContext.registerReceiver(null,
- new IntentFilter(ACTION_TWILIGHT_CHANGED)));
- }
- return mIsNight;
- }
-
- public String getCustomValues() {
- return TunerService.get(mContext).getValue(COLOR_MATRIX_CUSTOM_VALUES);
- }
-
- public void setCustomValues(String values) {
- TunerService.get(mContext).setValue(COLOR_MATRIX_CUSTOM_VALUES, values);
- }
-
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (COLOR_MATRIX_CUSTOM_VALUES.equals(key)) {
- mCustomMatrix = newValue != null ? toValues(newValue) : null;
- updateCurrentMatrix();
- } else if (NIGHT_MODE_ADJUST_TINT.equals(key)) {
- mAdjustTint = newValue == null || Integer.parseInt(newValue) != 0;
- updateListening();
- updateCurrentMatrix();
- } else if (Secure.TWILIGHT_MODE.equals(key)) {
- mIsAuto = newValue != null && Integer.parseInt(newValue) >= Secure.TWILIGHT_MODE_AUTO;
- }
- }
-
- private void updateCurrentMatrix() {
- if (!mUpdateMatrix) return;
- if ((!mAdjustTint || mAmount == 0) && mCustomMatrix == null) {
- TunerService.get(mContext).setValue(Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
- return;
- }
- float[] values = scaleValues(IDENTITY_MATRIX, NIGHT_VALUES, mAdjustTint ? mAmount : 0);
- if (mCustomMatrix != null) {
- values = multiply(values, mCustomMatrix);
- }
- TunerService.get(mContext).setValue(Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
- toString(values));
- }
-
- private void updateNightMode(Intent intent) {
- mIsNight = intent != null && intent.getBooleanExtra(EXTRA_IS_NIGHT, false);
- mAmount = intent != null ? intent.getFloatExtra(EXTRA_AMOUNT, 0) : 0;
- }
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (ACTION_TWILIGHT_CHANGED.equals(intent.getAction())) {
- updateNightMode(intent);
- updateCurrentMatrix();
- for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onNightModeChanged();
- }
- }
- }
- };
-
- public interface Listener {
- void onNightModeChanged();
- void onTwilightAutoChanged();
- }
-
- private static float[] multiply(float[] matrix, float[] other) {
- if (matrix == null) {
- return other;
- }
- float[] result = new float[16];
- Matrix.multiplyMM(result, 0, matrix, 0, other, 0);
- return result;
- }
-
- private float[] scaleValues(float[] identityMatrix, float[] nightValues, float amount) {
- float[] values = new float[identityMatrix.length];
- for (int i = 0; i < values.length; i++) {
- values[i] = MathUtils.lerp(identityMatrix[i], nightValues[i], amount);
- }
- return values;
- }
-
- public static String toString(float[] values) {
- StringBuilder builder = new StringBuilder();
- for (int i = 0; i < values.length; i++) {
- if (builder.length() != 0) {
- builder.append(',');
- }
- builder.append(values[i]);
- }
- return builder.toString();
- }
-
- public static float[] toValues(String customValues) {
- String[] strValues = customValues.split(",");
- float[] values = new float[strValues.length];
- for (int i = 0; i < values.length; i++) {
- values[i] = Float.parseFloat(strValues[i]);
- }
- return values;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index d91b3329d1ac..ed8c7ff96aac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -208,10 +208,12 @@ class TelephonyIcons {
};
static final int QS_DATA_LTE = R.drawable.ic_qs_signal_lte;
+ static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus;
static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
+ static final int ICON_LTE_PLUS = R.drawable.stat_sys_data_fully_connected_lte_plus;
static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g;
static final int ICON_E = R.drawable.stat_sys_data_fully_connected_e;
static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h;
@@ -393,6 +395,21 @@ class TelephonyIcons {
TelephonyIcons.QS_DATA_LTE
);
+ static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
+ "LTE+",
+ TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+ TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ TelephonyIcons.TELEPHONY_NO_NETWORK,
+ TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.accessibility_data_connection_lte_plus,
+ TelephonyIcons.ICON_LTE_PLUS,
+ true,
+ TelephonyIcons.QS_DATA_LTE_PLUS
+ );
+
static final MobileIconGroup ROAMING = new MobileIconGroup(
"Roaming",
TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING,
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java b/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java
deleted file mode 100644
index ff7be1367388..000000000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/CalibratePreference.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.tuner;
-
-import android.content.Context;
-import android.support.v7.preference.DialogPreference;
-import android.util.AttributeSet;
-
-public class CalibratePreference extends DialogPreference {
- public CalibratePreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java
deleted file mode 100644
index af95cf9354bb..000000000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/ColorAndAppearanceFragment.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.tuner;
-
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.provider.Settings.Secure;
-import android.support.v14.preference.PreferenceFragment;
-import android.support.v7.preference.Preference;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.SeekBar;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.NightModeController;
-
-public class ColorAndAppearanceFragment extends PreferenceFragment {
-
- private static final String KEY_CALIBRATE = "calibrate";
-
- private static final long RESET_DELAY = 10000;
- private static final CharSequence KEY_NIGHT_MODE = "night_mode";
-
- private NightModeController mNightModeController;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mNightModeController = new NightModeController(getContext());
- }
-
- @Override
- public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
- addPreferencesFromResource(R.xml.color_and_appearance);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_COLOR_AND_APPEARANCE, true);
- // TODO: Figure out better title model for Tuner, to avoid any more of this.
- getActivity().setTitle(R.string.color_and_appearance);
-
- Preference nightMode = findPreference(KEY_NIGHT_MODE);
- nightMode.setSummary(mNightModeController.isEnabled()
- ? R.string.night_mode_on : R.string.night_mode_off);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_COLOR_AND_APPEARANCE, false);
- }
-
- @Override
- public void onDisplayPreferenceDialog(Preference preference) {
- if (preference instanceof CalibratePreference) {
- CalibrateDialog.show(this);
- } else {
- super.onDisplayPreferenceDialog(preference);
- }
- }
-
- private void startRevertTimer() {
- getView().postDelayed(mResetColorMatrix, RESET_DELAY);
- }
-
- private void onApply() {
- MetricsLogger.action(getContext(), MetricsEvent.ACTION_TUNER_CALIBRATE_DISPLAY_CHANGED);
- mNightModeController.setCustomValues(Settings.Secure.getString(
- getContext().getContentResolver(), Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX));
- getView().removeCallbacks(mResetColorMatrix);
- }
-
- private void onRevert() {
- getView().removeCallbacks(mResetColorMatrix);
- mResetColorMatrix.run();
- }
-
- private final Runnable mResetColorMatrix = new Runnable() {
- @Override
- public void run() {
- ((DialogFragment) getFragmentManager().findFragmentByTag("RevertWarning")).dismiss();
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, null);
- }
- };
-
- public static class CalibrateDialog extends DialogFragment implements
- DialogInterface.OnClickListener {
- private float[] mValues;
- private NightModeController mNightModeController;
-
- public static void show(ColorAndAppearanceFragment fragment) {
- CalibrateDialog dialog = new CalibrateDialog();
- dialog.setTargetFragment(fragment, 0);
- dialog.show(fragment.getFragmentManager(), "Calibrate");
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mNightModeController = new NightModeController(getContext());
- String customValues = mNightModeController.getCustomValues();
- if (customValues == null) {
- // Generate this as a string because its the easiest way to generate a copy of the
- // identity.
- customValues = NightModeController.toString(NightModeController.IDENTITY_MATRIX);
- }
- mValues = NightModeController.toValues(customValues);
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- View v = LayoutInflater.from(getContext()).inflate(R.layout.calibrate_sliders, null);
- bindView(v.findViewById(R.id.r_group), 0);
- bindView(v.findViewById(R.id.g_group), 5);
- bindView(v.findViewById(R.id.b_group), 10);
- MetricsLogger.visible(getContext(), MetricsEvent.TUNER_CALIBRATE_DISPLAY);
- return new AlertDialog.Builder(getContext())
- .setTitle(R.string.calibrate_display)
- .setView(v)
- .setPositiveButton(R.string.color_apply, this)
- .setNegativeButton(android.R.string.cancel, null)
- .create();
- }
-
- @Override
- public void onDismiss(DialogInterface dialog) {
- super.onDismiss(dialog);
- MetricsLogger.hidden(getContext(), MetricsEvent.TUNER_CALIBRATE_DISPLAY);
- }
-
- private void bindView(View view, final int index) {
- SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
- seekBar.setMax(1000);
- seekBar.setProgress((int) (1000 * mValues[index]));
- seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- mValues[index] = progress / 1000f;
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- }
- });
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (mValues[0] == 1 && mValues[5] == 1 && mValues[10] == 1) {
- // Allow removal of matrix by all values set to highest.
- mNightModeController.setCustomValues(null);
- return;
- }
- ((ColorAndAppearanceFragment) getTargetFragment()).startRevertTimer();
- Settings.Secure.putString(getContext().getContentResolver(),
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX,
- NightModeController.toString(mValues));
- RevertWarning.show((ColorAndAppearanceFragment) getTargetFragment());
- }
- }
-
- public static class RevertWarning extends DialogFragment
- implements DialogInterface.OnClickListener {
-
- public static void show(ColorAndAppearanceFragment fragment) {
- RevertWarning warning = new RevertWarning();
- warning.setTargetFragment(fragment, 0);
- warning.show(fragment.getFragmentManager(), "RevertWarning");
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- AlertDialog alertDialog = new AlertDialog.Builder(getContext())
- .setTitle(R.string.color_revert_title)
- .setMessage(R.string.color_revert_message)
- .setPositiveButton(R.string.ok, this)
- .create();
- alertDialog.setCanceledOnTouchOutside(true);
- return alertDialog;
- }
-
- @Override
- public void onCancel(DialogInterface dialog) {
- super.onCancel(dialog);
- ((ColorAndAppearanceFragment) getTargetFragment()).onRevert();
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- ((ColorAndAppearanceFragment) getTargetFragment()).onApply();
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java
deleted file mode 100644
index ae2856cef36f..000000000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/NightModeFragment.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.tuner;
-
-import android.annotation.Nullable;
-import android.app.UiModeManager;
-import android.content.Context;
-import android.os.Bundle;
-import android.provider.Settings.Secure;
-import android.support.v14.preference.PreferenceFragment;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Switch;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.NightModeController;
-import com.android.systemui.statusbar.policy.NightModeController.Listener;
-import com.android.systemui.tuner.TunerService.Tunable;
-
-public class NightModeFragment extends PreferenceFragment implements Tunable,
- Listener, OnPreferenceChangeListener {
-
- private static final String TAG = "NightModeFragment";
-
- public static final String EXTRA_SHOW_NIGHT_MODE = "show_night_mode";
-
- private static final CharSequence KEY_AUTO = "auto";
- private static final CharSequence KEY_ADJUST_TINT = "adjust_tint";
- private static final CharSequence KEY_ADJUST_BRIGHTNESS = "adjust_brightness";
-
- private Switch mSwitch;
-
- private NightModeController mNightModeController;
- private SwitchPreference mAutoSwitch;
- private SwitchPreference mAdjustTint;
- private SwitchPreference mAdjustBrightness;
- private UiModeManager mUiModeManager;
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mNightModeController = new NightModeController(getContext());
- mUiModeManager = getContext().getSystemService(UiModeManager.class);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- final View view = LayoutInflater.from(getContext()).inflate(
- R.layout.night_mode_settings, container, false);
- ((ViewGroup) view).addView(super.onCreateView(inflater, container, savedInstanceState));
- return view;
- }
-
- @Override
- public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
- final Context context = getPreferenceManager().getContext();
-
- addPreferencesFromResource(R.xml.night_mode);
- mAutoSwitch = (SwitchPreference) findPreference(KEY_AUTO);
- mAutoSwitch.setOnPreferenceChangeListener(this);
- mAdjustTint = (SwitchPreference) findPreference(KEY_ADJUST_TINT);
- mAdjustTint.setOnPreferenceChangeListener(this);
- mAdjustBrightness = (SwitchPreference) findPreference(KEY_ADJUST_BRIGHTNESS);
- mAdjustBrightness.setOnPreferenceChangeListener(this);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- View switchBar = view.findViewById(R.id.switch_bar);
- mSwitch = (Switch) switchBar.findViewById(android.R.id.switch_widget);
- mSwitch.setChecked(mNightModeController.isEnabled());
- switchBar.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- boolean newState = !mNightModeController.isEnabled();
- MetricsLogger.action(getContext(), MetricsEvent.ACTION_TUNER_NIGHT_MODE, newState);
- mNightModeController.setNightMode(newState);
- mSwitch.setChecked(newState);
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_NIGHT_MODE, true);
- mNightModeController.addListener(this);
- TunerService.get(getContext()).addTunable(this, Secure.BRIGHTNESS_USE_TWILIGHT,
- NightModeController.NIGHT_MODE_ADJUST_TINT);
- calculateDisabled();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- MetricsLogger.visibility(getContext(), MetricsEvent.TUNER_NIGHT_MODE, false);
- mNightModeController.removeListener(this);
- TunerService.get(getContext()).removeTunable(this);
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final Boolean value = (Boolean) newValue;
- if (mAutoSwitch == preference) {
- MetricsLogger.action(getContext(), MetricsEvent.ACTION_TUNER_NIGHT_MODE_AUTO, value);
- mNightModeController.setAuto(value);
- } else if (mAdjustTint == preference) {
- MetricsLogger.action(getContext(),
- MetricsEvent.ACTION_TUNER_NIGHT_MODE_ADJUST_TINT, value);
- mNightModeController.setAdjustTint(value);
- postCalculateDisabled();
- } else if (mAdjustBrightness == preference) {
- MetricsLogger.action(getContext(),
- MetricsEvent.ACTION_TUNER_NIGHT_MODE_ADJUST_BRIGHTNESS, value);
- TunerService.get(getContext()).setValue(Secure.BRIGHTNESS_USE_TWILIGHT,
- value ? 1 : 0);
- postCalculateDisabled();
- } else {
- return false;
- }
- return true;
- }
-
- private void postCalculateDisabled() {
- // Post this because its the easiest way to wait for all state to be calculated.
- getView().post(new Runnable() {
- @Override
- public void run() {
- calculateDisabled();
- }
- });
- }
-
- private void calculateDisabled() {
- int enabledCount = (mAdjustTint.isChecked() ? 1 : 0)
- + (mAdjustBrightness.isChecked() ? 1 : 0);
- if (enabledCount == 1) {
- if (mAdjustTint.isChecked()) {
- mAdjustTint.setEnabled(false);
- } else {
- mAdjustBrightness.setEnabled(false);
- }
- } else {
- mAdjustTint.setEnabled(true);
- mAdjustBrightness.setEnabled(true);
- }
- }
-
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (Secure.BRIGHTNESS_USE_TWILIGHT.equals(key)) {
- mAdjustBrightness.setChecked(newValue != null && Integer.parseInt(newValue) != 0);
- } else if (NightModeController.NIGHT_MODE_ADJUST_TINT.equals(key)) {
- // Default on.
- mAdjustTint.setChecked(newValue == null || Integer.parseInt(newValue) != 0);
- }
- }
-
- @Override
- public void onNightModeChanged() {
- mSwitch.setChecked(mNightModeController.isEnabled());
- }
-
- @Override
- public void onTwilightAutoChanged() {
- mAutoSwitch.setChecked(mNightModeController.isAuto());
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java b/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
deleted file mode 100644
index fe445025854c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Copyright (c) 2016, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.tuner;
-
-import android.content.Intent;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.Prefs;
-import com.android.systemui.Prefs.Key;
-import com.android.systemui.R;
-import com.android.systemui.qs.QSTile;
-import com.android.systemui.statusbar.policy.NightModeController;
-
-
-public class NightModeTile extends QSTile<QSTile.State> implements NightModeController.Listener {
-
- public static final String NIGHT_MODE_SPEC = "night";
-
- private final NightModeController mNightModeController;
-
- private int mIndex;
- private String mCurrentValue;
-
- private boolean mCustomEnabled;
- private String[] mValues;
- private CharSequence[] mValueTitles;
-
- public NightModeTile(Host host) {
- super(host);
- mNightModeController = host.getNightModeController();
- }
-
- @Override
- public boolean isAvailable() {
- return Prefs.getBoolean(mContext, Key.QS_NIGHT_ADDED, false)
- && TunerService.isTunerEnabled(mContext);
- }
-
- @Override
- public void setListening(boolean listening) {
- if (listening) {
- mNightModeController.addListener(this);
- refreshState();
- } else {
- mNightModeController.removeListener(this);
- }
- }
-
- @Override
- public State newTileState() {
- return new State();
- }
-
- @Override
- public Intent getLongClickIntent() {
- return new Intent(mContext, TunerActivity.class)
- .putExtra(NightModeFragment.EXTRA_SHOW_NIGHT_MODE, true);
- }
-
- @Override
- protected void handleClick() {
- mNightModeController.setNightMode(!mNightModeController.isEnabled());
- refreshState();
- }
-
- @Override
- public CharSequence getTileLabel() {
- return mContext.getString(R.string.night_mode);
- }
-
- @Override
- protected void handleUpdateState(State state, Object arg) {
- // TODO: Right now this is just a dropper, needs an actual night icon.
- boolean enabled = mNightModeController.isEnabled();
- state.icon = ResourceIcon.get(enabled ? R.drawable.ic_night_mode
- : R.drawable.ic_night_mode_disabled);
- state.label = mContext.getString(R.string.night_mode);
- state.contentDescription = mContext.getString(R.string.night_mode);
- }
-
- @Override
- public void onNightModeChanged() {
- refreshState();
- }
-
- @Override
- public void onTwilightAutoChanged() {
- // Don't care.
- }
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.QS_COLOR_MATRIX;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 5e5da7423cb6..5fe92967589e 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -39,10 +39,7 @@ public class TunerActivity extends SettingsDrawerActivity implements
final String action = getIntent().getAction();
boolean showDemoMode = action != null && action.equals(
"com.android.settings.action.DEMO_MODE");
- boolean showNightMode = getIntent().getBooleanExtra(
- NightModeFragment.EXTRA_SHOW_NIGHT_MODE, false);
- final PreferenceFragment fragment = showNightMode ? new NightModeFragment()
- : showDemoMode ? new DemoModeFragment()
+ final PreferenceFragment fragment = showDemoMode ? new DemoModeFragment()
: new TunerFragment();
getFragmentManager().beginTransaction().replace(R.id.content_frame,
fragment, TAG_TUNER).commit();
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java
index cc0ffb0e2653..1ea23bb65107 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java
@@ -54,7 +54,6 @@ public class TunerZenModePanel extends LinearLayout implements OnClickListener {
mHeaderSwitch = findViewById(R.id.tuner_zen_switch);
mHeaderSwitch.setVisibility(View.VISIBLE);
mHeaderSwitch.setOnClickListener(this);
- mHeaderSwitch.findViewById(com.android.internal.R.id.up).setVisibility(View.GONE);
((TextView) mHeaderSwitch.findViewById(android.R.id.title)).setText(
R.string.quick_settings_dnd_label);
mZenModePanel = (ZenModePanel) findViewById(R.id.zen_mode_panel);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index f01e95fa3873..995ecaed6ecf 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -124,12 +124,8 @@ public class ZenFooter extends LinearLayout {
: null;
Util.setText(mSummaryLine1, line1);
- final boolean isForever = mConfig != null && mConfig.manualRule != null
- && mConfig.manualRule.conditionId == null;
- final CharSequence line2 =
- isForever ? mContext.getString(com.android.internal.R.string.zen_mode_forever_dnd)
- : ZenModeConfig.getConditionSummary(mContext, mConfig, mController.getCurrentUser(),
- true /*shortVersion*/);
+ final CharSequence line2 = ZenModeConfig.getConditionSummary(mContext, mConfig,
+ mController.getCurrentUser(), true /*shortVersion*/);
Util.setText(mSummaryLine2, line2);
}
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 47d1493e1574..97efed0130be 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -40,22 +40,30 @@ import java.nio.charset.StandardCharsets;
public class WallpaperBackupAgent extends BackupAgent {
private static final String TAG = "WallpaperBackup";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
// NB: must be kept in sync with WallpaperManagerService but has no
// compile-time visibility.
// Target filenames within the system's wallpaper directory
static final String WALLPAPER = "wallpaper_orig";
+ static final String WALLPAPER_LOCK = "wallpaper_lock_orig";
static final String WALLPAPER_INFO = "wallpaper_info.xml";
// Names of our local-data stage files/links
static final String IMAGE_STAGE = "wallpaper-stage";
+ static final String LOCK_IMAGE_STAGE = "wallpaper-lock-stage";
static final String INFO_STAGE = "wallpaper-info-stage";
static final String EMPTY_SENTINEL = "empty";
+ static final String QUOTA_SENTINEL = "quota";
- private File mWallpaperInfo; // wallpaper metadata file
- private File mWallpaperFile; // primary wallpaper image file
+ private File mWallpaperInfo; // wallpaper metadata file
+ private File mWallpaperFile; // primary wallpaper image file
+ private File mLockWallpaperFile; // lock wallpaper image file
+
+ // If this file exists, it means we exceeded our quota last time
+ private File mQuotaFile;
+ private boolean mQuotaExceeded;
private WallpaperManager mWm;
@@ -68,7 +76,14 @@ public class WallpaperBackupAgent extends BackupAgent {
File wallpaperDir = Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM);
mWallpaperInfo = new File(wallpaperDir, WALLPAPER_INFO);
mWallpaperFile = new File(wallpaperDir, WALLPAPER);
+ mLockWallpaperFile = new File(wallpaperDir, WALLPAPER_LOCK);
mWm = (WallpaperManager) getSystemService(Context.WALLPAPER_SERVICE);
+
+ mQuotaFile = new File(getFilesDir(), QUOTA_SENTINEL);
+ mQuotaExceeded = mQuotaFile.exists();
+ if (DEBUG) {
+ Slog.v(TAG, "quota file " + mQuotaFile.getPath() + " exists=" + mQuotaExceeded);
+ }
}
@Override
@@ -77,6 +92,7 @@ public class WallpaperBackupAgent extends BackupAgent {
final File filesDir = getFilesDir();
final File infoStage = new File(filesDir, INFO_STAGE);
final File imageStage = new File (filesDir, IMAGE_STAGE);
+ final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
final File empty = new File (filesDir, EMPTY_SENTINEL);
try {
@@ -96,11 +112,18 @@ public class WallpaperBackupAgent extends BackupAgent {
// In case of prior muddled state
infoStage.delete();
imageStage.delete();
+ lockImageStage.delete();
Os.link(mWallpaperInfo.getCanonicalPath(), infoStage.getCanonicalPath());
fullBackupFile(infoStage, data);
Os.link(mWallpaperFile.getCanonicalPath(), imageStage.getCanonicalPath());
fullBackupFile(imageStage, data);
+
+ // Don't try to store the lock image if we overran our quota last time
+ if (!mQuotaExceeded) {
+ Os.link(mLockWallpaperFile.getCanonicalPath(), lockImageStage.getCanonicalPath());
+ fullBackupFile(lockImageStage, data);
+ }
} else {
if (DEBUG) {
Slog.v(TAG, "Wallpaper not backup-eligible; writing no data");
@@ -114,6 +137,26 @@ public class WallpaperBackupAgent extends BackupAgent {
}
infoStage.delete();
imageStage.delete();
+ lockImageStage.delete();
+
+ // Even if this time we had to back off on attempting to store the lock image
+ // due to exceeding the data quota, try again next time. This will alternate
+ // between "try both" and "only store the primary image" until either there
+ // is no lock image to store, or the quota is raised, or both fit under the
+ // quota.
+ mQuotaFile.delete();
+ }
+ }
+
+ @Override
+ public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
+ if (DEBUG) {
+ Slog.i(TAG, "Quota exceeded (" + backupDataBytes + " vs " + quotaBytes + ')');
+ }
+ try (FileOutputStream f = new FileOutputStream(mQuotaFile)) {
+ f.write(0);
+ } catch (Exception e) {
+ Slog.w(TAG, "Unable to record quota-exceeded: " + e.getMessage());
}
}
@@ -124,30 +167,17 @@ public class WallpaperBackupAgent extends BackupAgent {
if (DEBUG) {
Slog.v(TAG, "onRestoreFinished()");
}
- final File infoStage = new File(getFilesDir(), INFO_STAGE);
- final File imageStage = new File (getFilesDir(), IMAGE_STAGE);
+ final File filesDir = getFilesDir();
+ final File infoStage = new File(filesDir, INFO_STAGE);
+ final File imageStage = new File (filesDir, IMAGE_STAGE);
+ final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
try {
// It is valid for the imagery to be absent; it means that we were not permitted
- // to back up the original image on the source device.
- if (imageStage.exists()) {
- if (DEBUG) {
- Slog.v(TAG, "Got restored wallpaper; applying");
- }
-
- // Parse the restored info file to find the crop hint. Note that this currently
- // relies on a priori knowledge of the wallpaper info file schema.
- Rect cropHint = parseCropHint(infoStage);
- if (cropHint != null) {
- if (DEBUG) {
- Slog.v(TAG, "Restored crop hint " + cropHint + "; now writing data");
- }
- WallpaperManager wm = getSystemService(WallpaperManager.class);
- try (FileInputStream in = new FileInputStream(imageStage)) {
- wm.setStream(in, cropHint, true, WallpaperManager.FLAG_SYSTEM);
- } finally {} // auto-closes 'in'
- }
- }
+ // to back up the original image on the source device, or there was no user-supplied
+ // wallpaper image present.
+ restoreFromStage(imageStage, infoStage, "wp", WallpaperManager.FLAG_SYSTEM);
+ restoreFromStage(lockImageStage, infoStage, "kwp", WallpaperManager.FLAG_LOCK);
} catch (Exception e) {
Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage());
} finally {
@@ -156,10 +186,31 @@ public class WallpaperBackupAgent extends BackupAgent {
}
infoStage.delete();
imageStage.delete();
+ lockImageStage.delete();
+ }
+ }
+
+ private void restoreFromStage(File stage, File info, String hintTag, int which)
+ throws IOException {
+ if (stage.exists()) {
+ if (DEBUG) {
+ Slog.v(TAG, "Got restored wallpaper; applying which=" + which);
+ }
+ // Parse the restored info file to find the crop hint. Note that this currently
+ // relies on a priori knowledge of the wallpaper info file schema.
+ Rect cropHint = parseCropHint(info, hintTag);
+ if (cropHint != null) {
+ if (DEBUG) {
+ Slog.v(TAG, "Restored crop hint " + cropHint + "; now writing data");
+ }
+ try (FileInputStream in = new FileInputStream(stage)) {
+ mWm.setStream(in, cropHint, true, which);
+ } finally {} // auto-closes 'in'
+ }
}
}
- private Rect parseCropHint(File wallpaperInfo) {
+ private Rect parseCropHint(File wallpaperInfo, String sectionTag) {
Rect cropHint = new Rect();
try (FileInputStream stream = new FileInputStream(wallpaperInfo)) {
XmlPullParser parser = Xml.newPullParser();
@@ -170,7 +221,7 @@ public class WallpaperBackupAgent extends BackupAgent {
type = parser.next();
if (type == XmlPullParser.START_TAG) {
String tag = parser.getName();
- if ("wp".equals(tag)) {
+ if (sectionTag.equals(tag)) {
cropHint.left = getAttributeInt(parser, "cropLeft", 0);
cropHint.top = getAttributeInt(parser, "cropTop", 0);
cropHint.right = getAttributeInt(parser, "cropRight", 0);
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 1fb964201d96..ba59c2f0192a 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -33,73 +33,61 @@ message MetricsEvent {
// OPEN: Settings > Accessibility
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY = 2;
// OPEN: Settings > Accessibility > Captions
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY_CAPTION_PROPERTIES = 3;
// OPEN: Settings > Accessibility > [Service]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY_SERVICE = 4;
// OPEN: Settings > Accessibility > Color correction
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_DALTONIZER = 5;
// OPEN: Settings > Accessibility > Accessibility shortcut
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6;
// OPEN: Settings > Accessibility > Magnification gestures
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7;
// OPEN: Settings > Accounts
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCOUNT = 8;
// OPEN: Settings > Accounts > [Single Account Sync Settings]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCOUNTS_ACCOUNT_SYNC = 9;
// OPEN: Settings > Accounts > Add an account
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10;
// OPEN: Settings > Accounts > [List of accounts when more than one]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACCOUNTS_MANAGE_ACCOUNTS = 11;
// OPEN: Settings > Cellular network settings > APNs
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APN = 12;
// OPEN: Settings > More > Cellular network settings > APNs > [Edit APN]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APN_EDITOR = 13;
// OBSOLETE
@@ -114,7 +102,6 @@ message MetricsEvent {
// OPEN: Settings > Apps > Configure apps > App links > [App]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_APP_LAUNCH = 17;
// OBSOLETE
@@ -123,19 +110,16 @@ message MetricsEvent {
// OPEN: Settings > Internal storage > Apps storage > [App]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_APP_STORAGE = 19;
// OPEN: Settings > Apps > [App info]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_INSTALLED_APP_DETAILS = 20;
// OPEN: Settings > Memory > App usage > [App Memory usage]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_PROCESS_STATS_DETAIL = 21;
// OBSOLETE
@@ -144,19 +128,16 @@ message MetricsEvent {
// OPEN: Settings > Memory > App usage
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_PROCESS_STATS_UI = 23;
// OPEN: Settings > Bluetooth
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
BLUETOOTH = 24;
// OPEN: Choose Bluetooth device (ex: when sharing)
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
BLUETOOTH_DEVICE_PICKER = 25;
// OBSOLETE
@@ -165,55 +146,46 @@ message MetricsEvent {
// OPEN: Settings > Security > Choose screen lock
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CHOOSE_LOCK_GENERIC = 27;
// OPEN: Settings > Security > Choose screen lock > Choose your password
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CHOOSE_LOCK_PASSWORD = 28;
// OPEN: Settings > Security > Choose screen lock > Choose your pattern
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CHOOSE_LOCK_PATTERN = 29;
// OPEN: Settings > Security > Choose screen lock > Confirm your password
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CONFIRM_LOCK_PASSWORD = 30;
// OPEN: Settings > Security > Choose screen lock > Confirm your pattern
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CONFIRM_LOCK_PATTERN = 31;
// OPEN: Settings > Security > Encrypt phone
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CRYPT_KEEPER = 32;
// OPEN: Settings > Security > Encrypt phone > Confirm
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
CRYPT_KEEPER_CONFIRM = 33;
// OPEN: Settings > Search results
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DASHBOARD_SEARCH_RESULTS = 34;
// OPEN: Settings (Root page)
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DASHBOARD_SUMMARY = 35;
// OBSOLETE
@@ -222,49 +194,41 @@ message MetricsEvent {
// OPEN: Settings > Data usage
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DATA_USAGE_SUMMARY = 37;
// OPEN: Settings > Date & time
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DATE_TIME = 38;
// OPEN: Settings > Developer options
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVELOPMENT = 39;
// OPEN: Settings > About phone
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVICEINFO = 40;
// OPEN: Settings > About phone > Status > IMEI information
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVICEINFO_IMEI_INFORMATION = 41;
// OPEN: Settings > Internal storage
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVICEINFO_STORAGE = 42;
// OPEN: Settings > About phone > Status > SIM status
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVICEINFO_SIM_STATUS = 43;
// OPEN: Settings > About phone > Status
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DEVICEINFO_STATUS = 44;
// OBSOLETE
@@ -273,25 +237,21 @@ message MetricsEvent {
// OPEN: Settings > Display
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DISPLAY = 46;
// OPEN: Settings > Display > Daydream
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
DREAM = 47;
// OPEN: Settings > Security > Screen lock > Secure start-up
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ENCRYPTION = 48;
// OPEN: Settings > Security > Nexus Imprint
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FINGERPRINT = 49;
// OBSOLETE
@@ -300,55 +260,46 @@ message MetricsEvent {
// OPEN: Settings > Battery > History details
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FUELGAUGE_BATTERY_HISTORY_DETAIL = 51;
// OPEN: Settings > Battery > Battery saver
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FUELGAUGE_BATTERY_SAVER = 52;
// OPEN: Settings > Battery > [App Use details]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FUELGAUGE_POWER_USAGE_DETAIL = 53;
// OPEN: Settings > Battery
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FUELGAUGE_POWER_USAGE_SUMMARY = 54;
// OPEN: Settings > Home
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
HOME = 55;
// OPEN: Settings > Security > SIM card lock settings
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ICC_LOCK = 56;
// OPEN: Settings > Language & input
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
INPUTMETHOD_LANGUAGE = 57;
// OPEN: Settings > Language & input > Physical keyboard
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
INPUTMETHOD_KEYBOARD = 58;
// OPEN: Settings > Language & input > Spell checker
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
INPUTMETHOD_SPELL_CHECKERS = 59;
// OBSOLETE
@@ -357,79 +308,66 @@ message MetricsEvent {
// OPEN: Settings > Language & input > Personal dictionary
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
INPUTMETHOD_USER_DICTIONARY = 61;
// OPEN: Settings > Language & input > Add word
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62;
// OPEN: Settings > Location
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
LOCATION = 63;
// OPEN: Settings > Location > Location mode
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
LOCATION_MODE = 64;
// OPEN: Settings > Apps
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
MANAGE_APPLICATIONS = 65;
// OPEN: Settings > Backup & reset > Factory data reset
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
MASTER_CLEAR = 66;
// OPEN: Settings > Backup & reset > Factory data reset > Confirm
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
MASTER_CLEAR_CONFIRM = 67;
// OPEN: Settings > Data usage > Network restrictions
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NET_DATA_USAGE_METERED = 68;
// OPEN: Settings > More > Android Beam
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NFC_BEAM = 69;
// OPEN: Settings > Tap & pay
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NFC_PAYMENT = 70;
// OPEN: Settings > Sound & notification
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION = 71;
// OPEN: Settings > Sound & notification > App notifications > [App]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_APP_NOTIFICATION = 72;
// OPEN: Settings > Sound & notification > Other sounds
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_OTHER_SOUND = 73;
// OBSOLETE
@@ -438,13 +376,11 @@ message MetricsEvent {
// OPEN: Settings Widget > Notification log
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_STATION = 75;
// OPEN: Settings > Sound & notification > Do not disturb
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE = 76;
// OPEN: OBSOLETE
@@ -453,25 +389,21 @@ message MetricsEvent {
// OPEN: Print job notification > Print job settings
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
PRINT_JOB_SETTINGS = 78;
// OPEN: Settings > Printing > [Print Service]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
PRINT_SERVICE_SETTINGS = 79;
// OPEN: Settings > Printing
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
PRINT_SETTINGS = 80;
// OPEN: Settings > Backup & reset
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
PRIVACY = 81;
//OBSOLETE
@@ -480,37 +412,31 @@ message MetricsEvent {
// OPEN: Settings > Backup & reset > Network settings reset
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
RESET_NETWORK = 83;
// OPEN: Settings > Backup & reset > Network settings reset > Confirm
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
RESET_NETWORK_CONFIRM = 84;
// OPEN: Settings > Developer Options > Running Services
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
RUNNING_SERVICE_DETAILS = 85;
// OPEN: Settings > Security > Screen pinning
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
SCREEN_PINNING = 86;
// OPEN: Settings > Security
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
SECURITY = 87;
// OPEN: Settings > SIM cards
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
SIM = 88;
// OBSOLETE
@@ -519,55 +445,46 @@ message MetricsEvent {
// OPEN: Settings > More > Tethering & portable hotspot
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TETHER = 90;
// OPEN: Settings > Security > Trust agents
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TRUST_AGENT = 91;
// OPEN: Settings > Security > Trusted credentials
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TRUSTED_CREDENTIALS = 92;
// OPEN: Settings > Language & input > TTS output > [Engine] > Settings
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TTS_ENGINE_SETTINGS = 93;
// OPEN: Settings > Language & input > Text-to-speech output
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TTS_TEXT_TO_SPEECH = 94;
// OPEN: Settings > Security > Apps with usage access
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
USAGE_ACCESS = 95;
// OPEN: Settings > Users
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
USER = 96;
// OPEN: Settings > Users > [Restricted profile app & content access]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
USERS_APP_RESTRICTIONS = 97;
// OPEN: Settings > Users > [User settings]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
USER_DETAILS = 98;
// OBSOLETE
@@ -576,43 +493,36 @@ message MetricsEvent {
// OPEN: Settings > More > VPN
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
VPN = 100;
// OPEN: Settings > Display > Choose wallpaper from
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WALLPAPER_TYPE = 101;
// OPEN: Settings > Display > Cast
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WFD_WIFI_DISPLAY = 102;
// OPEN: Settings > Wi-Fi
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIFI = 103;
// OPEN: Settings > Wi-Fi > Advanced Wi-Fi
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIFI_ADVANCED = 104;
// OPEN: Settings > More > Wi-Fi Calling
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIFI_CALLING = 105;
// OPEN: Settings > Wi-Fi > Saved networks
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIFI_SAVED_ACCESS_POINTS = 106;
// OBSOLETE
@@ -624,19 +534,16 @@ message MetricsEvent {
// OPEN: Settings > Wi-Fi > Advanced Wi-Fi > Wi-Fi Direct
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIFI_P2P = 109;
// OPEN: Settings > More
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
WIRELESS = 110;
// OPEN: Quick Settings Panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_PANEL = 111;
// OPEN: QS Airplane mode tile shown
@@ -644,7 +551,6 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_AIRPLANEMODE = 112;
// OPEN: QS Bluetooth tile shown
@@ -652,21 +558,18 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_BLUETOOTH = 113;
// OPEN: QS Cast tile shown
// ACTION: QS Cast tile tapped
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_CAST = 114;
// OPEN: QS Cellular tile shown
// ACTION: QS Cellular tile tapped
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_CELLULAR = 115;
// OPEN: QS Color inversion tile shown
@@ -674,13 +577,11 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_COLORINVERSION = 116;
// OPEN: QS Cellular tile > Cellular detail panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_DATAUSAGEDETAIL = 117;
// OPEN: QS Do not disturb tile shown
@@ -688,7 +589,6 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_DND = 118;
// OPEN: QS Flashlight tile shown
@@ -696,7 +596,6 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_FLASHLIGHT = 119;
// OPEN: QS Hotspot tile shown
@@ -704,14 +603,12 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_HOTSPOT = 120;
// OPEN: QS 3P tile shown
// ACTION: QS 3P tile tapped
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_INTENT = 121;
// OPEN: QS Location tile shown
@@ -719,7 +616,6 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_LOCATION = 122;
// OPEN: QS Rotation tile shown
@@ -727,7 +623,6 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_ROTATIONLOCK = 123;
// OBSOLETE
@@ -736,7 +631,6 @@ message MetricsEvent {
// OPEN: QS User list panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_USERDETAIL = 125;
// OPEN: QS WiFi tile shown
@@ -744,13 +638,11 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.46
QS_WIFI = 126;
// OPEN: Notification Panel (including lockscreen)
// CATEGORY: NOTIFICATION
// OS: 5.1.1
- // GMS: 7.5.26
NOTIFICATION_PANEL = 127;
// OPEN: Notification in panel became visible.
@@ -764,7 +656,6 @@ message MetricsEvent {
// SUBTYPE: Dismiss reason from NotificationManagerService.java
// CATEGORY: NOTIFICATION
// OS: 5.1.1
- // GMS: 7.5.26
NOTIFICATION_ITEM = 128;
// ACTION: User tapped notification action
@@ -772,19 +663,16 @@ message MetricsEvent {
// SUBTYPE: Index of action on notification
// CATEGORY: NOTIFICATION
// OS: 5.0
- // GMS: 7.5.26
NOTIFICATION_ITEM_ACTION = 129;
// OPEN: Settings > Apps > Configure apps > App permissions
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_ADVANCED = 130;
// OPEN: Settings > Location > Scanning
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
LOCATION_SCANNING = 131;
// OBSOLETE
@@ -793,43 +681,36 @@ message MetricsEvent {
// OPEN: Settings > Sound & notification > App notifications
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
MANAGE_APPLICATIONS_NOTIFICATIONS = 133;
// ACTION: Settings > Wi-Fi > Overflow > Add Network
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_ADD_NETWORK = 134;
// ACTION: Settings > Wi-Fi > [Long press network] > Connect to network
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_CONNECT = 135;
// ACTION: Settings > Wi-Fi > Overflow > Refresh
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_FORCE_SCAN = 136;
// ACTION: Settings > Wi-Fi > [Long press network] > Forget network
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_FORGET = 137;
// ACTION: Settings > Wi-Fi > Toggle off
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_OFF = 138;
// ACTION: Settings > Wi-Fi > Toggle on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_WIFI_ON = 139;
// OBSOLETE
@@ -838,280 +719,236 @@ message MetricsEvent {
// OPEN: Settings > Sound & notification > DND > Priority only allows
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_PRIORITY = 141;
// OPEN: Settings > Sound & notification > DND > Automatic rules
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_AUTOMATION = 142;
// OPEN: Settings > Apps > Configure apps > App links
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
MANAGE_DOMAIN_URLS = 143;
// OPEN: Settings > Sound & notification > DND > [Time based rule]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144;
// OPEN: Settings > Sound & notification > DND > [External rule]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145;
// OPEN: Settings > Sound & notification > DND > [Event rule]
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_EVENT_RULE = 146;
// ACTION: App notification settings > Block Notifications
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BAN_APP_NOTES = 147;
// ACTION: Notification shade > Dismiss all button
// CATEGORY: NOTIFICATION
// OS: 6.0
- // GMS: 7.5.26
ACTION_DISMISS_ALL_NOTES = 148;
// OPEN: QS Do Not Disturb detail panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_DND_DETAILS = 149;
// OPEN: QS Bluetooth detail panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_BLUETOOTH_DETAILS = 150;
// OPEN: QS Cast detail panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_CAST_DETAILS = 151;
// OPEN: QS Wi-Fi detail panel
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_WIFI_DETAILS = 152;
// ACTION: QS Wi-Fi detail panel > Wi-Fi toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_WIFI_TOGGLE = 153;
// ACTION: QS Bluetooth detail panel > Bluetooth toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_BLUETOOTH_TOGGLE = 154;
// ACTION: QS Cellular detail panel > Cellular toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_CELLULAR_TOGGLE = 155;
// ACTION: QS User list panel > Select different user
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_SWITCH_USER = 156;
// ACTION: QS Cast detail panel > Select cast device
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_CAST_SELECT = 157;
// ACTION: QS Cast detail panel > Disconnect cast device
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_CAST_DISCONNECT = 158;
// ACTION: Settings > Bluetooth > Toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BLUETOOTH_TOGGLE = 159;
// ACTION: Settings > Bluetooth > Overflow > Refresh
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BLUETOOTH_SCAN = 160;
// ACTION: Settings > Bluetooth > Overflow > Rename this device
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BLUETOOTH_RENAME = 161;
// ACTION: Settings > Bluetooth > Overflow > Show received files
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BLUETOOTH_FILES = 162;
// ACTION: QS DND details panel > Increase / Decrease exit time
// SUBTYPE: true is increase, false is decrease
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_DND_TIME = 163;
// ACTION: QS DND details panel > [Exit condition]
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_DND_CONDITION_SELECT = 164;
// ACTION: QS DND details panel > [DND mode]
// SUBTYPE: 1 is priority, 2 is silence, 3 is alarms only
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_DND_ZEN_SELECT = 165;
// ACTION: QS DND detail panel > DND toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
QS_DND_TOGGLE = 166;
// ACTION: DND Settings > Priority only allows > Reminder toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ALLOW_REMINDERS = 167;
// ACTION: DND Settings > Priority only allows > Event toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ALLOW_EVENTS = 168;
// ACTION: DND Settings > Priority only allows > Messages
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ALLOW_MESSAGES = 169;
// ACTION: DND Settings > Priority only allows > Calls
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ALLOW_CALLS = 170;
// ACTION: DND Settings > Priority only allows > Repeat callers toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ALLOW_REPEAT_CALLS = 171;
// ACTION: DND Settings > Automatic rules > Add rule
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ADD_RULE = 172;
// ACTION: DND Settings > Automatic rules > Add rule > OK
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ADD_RULE_OK = 173;
// ACTION: DND Settings > Automatic rules > [Rule] > Delete rule
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_DELETE_RULE = 174;
// ACTION: DND Settings > Automatic rules > [Rule] > Delete rule > Delete
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_DELETE_RULE_OK = 175;
// ACTION: DND Settings > Automatic rules > [Rule] > Toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ZEN_ENABLE_RULE = 176;
// ACTION: Settings > More > Airplane mode toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_AIRPLANE_TOGGLE = 177;
// ACTION: Settings > Data usage > Cellular data toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_CELL_DATA_TOGGLE = 178;
// OPEN: Settings > Sound & notification > Notification access
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ACCESS = 179;
// OPEN: Settings > Sound & notification > Do Not Disturb access
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_ACCESS = 180;
// OPEN: Settings > Apps > Configure apps > Default Apps
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_DEFAULT_APPS = 181;
// OPEN: Settings > Internal storage > Apps storage
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_STORAGE_APPS = 182;
// OPEN: Settings > Security > Usage access
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_USAGE_ACCESS_DETAIL = 183;
// OPEN: Settings > Battery > Battery optimization
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_HIGH_POWER_APPS = 184;
// OBSOLETE
@@ -1120,448 +957,377 @@ message MetricsEvent {
// ACTION: Lockscreen > Unlock gesture
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_UNLOCK = 186;
// ACTION: Lockscreen > Pull shade open
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_SHADE = 187;
// ACTION: Lockscreen > Tap on lock, shows hint
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_HINT = 188;
// ACTION: Lockscreen > Camera
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_CAMERA = 189;
// ACTION: Lockscreen > Dialer
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_DIALER = 190;
// ACTION: Lockscreen > Tap on lock, locks phone
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_LOCK = 191;
// ACTION: Lockscreen > Tap on notification, false touch rejection
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
ACTION_LS_NOTE = 192;
// ACTION: Lockscreen > Swipe down to open quick settings
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.8.22
ACTION_LS_QS = 193;
// ACTION: Swipe down to open quick settings when unlocked
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.8.22
ACTION_SHADE_QS_PULL = 194;
// ACTION: Notification shade > Tap to open quick settings
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.8.22
ACTION_SHADE_QS_TAP = 195;
// OPEN: Lockscreen
// SUBTYPE: 0 is unsecure, 1 is secured by password / pattern / PIN
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
LOCKSCREEN = 196;
// OPEN: Lockscreen > Screen to enter password / pattern / PIN
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
BOUNCER = 197;
// OPEN: Screen turned on
// SUBTYPE: 2 is user action
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.8.22
SCREEN = 198;
// OPEN: Notification caused sound, vibration, and/or LED blink
// SUBTYPE: 1 is buzz, 2 is beep, blink is 4, or'd together
// CATEGORY: NOTIFICATION
// OS: 5.1.1
- // GMS: 7.8.53
NOTIFICATION_ALERT = 199;
// ACTION: Lockscreen > Emergency Call button
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 5.1.1
- // GMS: 7.5.26
ACTION_EMERGENCY_CALL = 200;
// OPEN: Settings > Apps > Configure > Default apps > Assist & voice input
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
APPLICATIONS_MANAGE_ASSIST = 201;
// OPEN: Settings > Memory
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
PROCESS_STATS_SUMMARY = 202;
// ACTION: Settings > Display > When device is rotated
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_ROTATION_LOCK = 203;
// ACTION: Long press on notification to view controls
// CATEGORY: NOTIFICATION
// OS: 6.0
- // GMS: 7.5.26
ACTION_NOTE_CONTROLS = 204;
// ACTION: Notificatoin controls > Info button
// CATEGORY: NOTIFICATION
// OS: 6.0
- // GMS: 7.5.26
ACTION_NOTE_INFO = 205;
// ACTION: Notification controls > Settings button
// CATEGORY: NOTIFICATION
// OS: 6.0
- // GMS: 7.5.26
ACTION_APP_NOTE_SETTINGS = 206;
// OPEN: Volume Dialog (with hardware buttons)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
VOLUME_DIALOG = 207;
// OPEN: Volume dialog > Expanded volume dialog (multiple sliders)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
VOLUME_DIALOG_DETAILS = 208;
// ACTION: Volume dialog > Adjust volume slider
// SUBTYPE: volume level (0-7)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_VOLUME_SLIDER = 209;
// ACTION: Volume dialog > Select non-active stream
// SUBTYPE: stream (defined in AudioSystem.java)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_VOLUME_STREAM = 210;
// ACTION: Adjust volume with hardware key
// SUBTYPE: volume level (0-7)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_VOLUME_KEY = 211;
// ACTION: Volume dialog > Mute a stream by tapping icon
// SUBTYPE: mute is 1, audible is 2
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_VOLUME_ICON = 212;
// ACTION: Volume dialog > Change ringer mode by tapping icon
// SUBTYPE: 2 is audible, 3 is vibrate
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_RINGER_MODE = 213;
// ACTION: Chooser shown (share target, file open, etc.)
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_SHOWN = 214;
// ACTION: Chooser > User taps an app target
// SUBTYPE: Index of target
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET = 215;
// ACTION: Chooser > User taps a service target
// SUBTYPE: Index of target
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET = 216;
// ACTION: Chooser > User taps a standard target
// SUBTYPE: Index of target
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET = 217;
// ACTION: QS Brightness Slider (with auto brightness disabled)
// SUBTYPE: slider value
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BRIGHTNESS = 218;
// ACTION: QS Brightness Slider (with auto brightness enabled)
// SUBTYPE: slider value
// CATEGORY: QUICK_SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_BRIGHTNESS_AUTO = 219;
// OPEN: Settings > Display > Brightness Slider
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
BRIGHTNESS_DIALOG = 220;
// OPEN: Settings > Apps > Configure Apps > Draw over other apps
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
SYSTEM_ALERT_WINDOW_APPS = 221;
// OPEN: Display has entered dream mode
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
DREAMING = 222;
// OPEN: Display has entered ambient notification mode
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
DOZING = 223;
// OPEN: Overview
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
OVERVIEW_ACTIVITY = 224;
// OPEN: Settings > About phone > Legal information
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ABOUT_LEGAL_SETTINGS = 225;
// OPEN: Settings > Search > Perform search
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
ACTION_SEARCH_RESULTS = 226;
// OPEN: Settings > System UI Tuner
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER = 227;
// OPEN: Settings > System UI Tuner > Quick Settings
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_QS = 228;
// OPEN: Settings > System UI Tuner > Demo mode
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_DEMO_MODE = 229;
// ACTION: Settings > System UI Tuner > Quick Settings > Move tile
// PACKAGE: Tile
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_QS_REORDER = 230;
// ACTION: Settings > System UI Tuner > Quick Settings > Add tile
// PACKAGE: Tile
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_QS_ADD = 231;
// ACTION: Settings > System UI Tuner > Quick Settings > Remove tile
// PACKAGE: Tile
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_QS_REMOVE = 232;
// ACTION: Settings > System UI Tuner > Status bar > Enable icon
// PACKAGE: Icon
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_STATUS_BAR_ENABLE = 233;
// ACTION: Settings > System UI Tuner > Status bar > Disable icon
// PACKAGE: Icon
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_STATUS_BAR_DISABLE = 234;
// ACTION: Settings > System UI Tuner > Demo mode > Enable demo mode
// SUBTYPE: false is disabled, true is enabled
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_DEMO_MODE_ENABLED = 235;
// ACTION: Settings > System UI Tuner > Demo mode > Show demo mode
// SUBTYPE: false is disabled, true is enabled
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_DEMO_MODE_ON = 236;
// ACTION: Settings > System UI Tuner > Show embedded battery percentage
// SUBTYPE: 0 is disabled, 1 is enabled
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
TUNER_BATTERY_PERCENTAGE = 237;
// OPEN: Settings > Developer options > Inactive apps
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.5.26
FUELGAUGE_INACTIVE_APPS = 238;
// ACTION: Long press home to bring up assistant
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.5.26
ACTION_ASSIST_LONG_PRESS = 239;
// OPEN: Settings > Security > Nexus Imprint > Add Fingerprint
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLLING = 240;
// OPEN: Fingerprint Enroll > Find Sensor
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_FIND_SENSOR = 241;
// OPEN: Fingerprint Enroll > Fingerprint Enrolled!
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_FINISH = 242;
// OPEN: Fingerprint Enroll introduction
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_INTRO = 243;
// OPEN: Fingerprint Enroll onboarding
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_ONBOARD = 244;
// OPEN: Fingerprint Enroll > Let's Start!
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_SIDECAR = 245;
// OPEN: Fingerprint Enroll SUW > Let's Start!
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLLING_SETUP = 246;
// OPEN: Fingerprint Enroll SUW > Find Sensor
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_FIND_SENSOR_SETUP = 247;
// OPEN: Fingerprint Enroll SUW > Fingerprint Enrolled!
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_FINISH_SETUP = 248;
// OPEN: Fingerprint Enroll SUW introduction
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_INTRO_SETUP = 249;
// OPEN: Fingerprint Enroll SUW onboarding
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
// ACTION: Add fingerprint > Enroll fingerprint
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
ACTION_FINGERPRINT_ENROLL = 251;
// ACTION: Authenticate using fingerprint
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
ACTION_FINGERPRINT_AUTH = 252;
// ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Delete
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
ACTION_FINGERPRINT_DELETE = 253;
// ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Rename
// CATEGORY: SETTINGS
// OS: 6.0
- // GMS: 7.8.99
ACTION_FINGERPRINT_RENAME = 254;
// ACTION: Double tap camera shortcut
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.8.99
ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
// ACTION: Double twist camera shortcut
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: 6.0
- // GMS: 7.8.99
ACTION_WIGGLE_CAMERA_GESTURE = 256;
// OPEN: QS Work Mode tile shown
@@ -1569,13 +1335,11 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_WORKMODE = 257;
// OPEN: Settings > Developer Options > Background Check
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
BACKGROUND_CHECK_SUMMARY = 258;
// OPEN: QS Lock tile shown
@@ -1583,52 +1347,44 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_LOCK_TILE = 259;
// OPEN: QS User Tile shown
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_USER_TILE = 260;
// OPEN: QS Battery tile shown
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_BATTERY_TILE = 261;
// OPEN: Settings > Sound > Do not disturb > Visual interruptions
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
NOTIFICATION_ZEN_MODE_VISUAL_INTERRUPTIONS = 262;
// ACTION: Visual interruptions > No screen interuptions toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_ZEN_ALLOW_WHEN_SCREEN_OFF = 263;
// ACTION: Visual interruptions > No notification light toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_ZEN_ALLOW_LIGHTS = 264;
// OPEN: Settings > Notifications > [App] > Topic Notifications
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
NOTIFICATION_TOPIC_NOTIFICATION = 265;
// ACTION: Settings > Apps > Default Apps > Select different SMS app
// PACKAGE: Selected SMS app
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_DEFAULT_SMS_APP_CHANGED = 266;
// OPEN: QS Color modification tile shown
@@ -1636,105 +1392,88 @@ message MetricsEvent {
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_COLOR_MATRIX = 267;
// OPEN: QS Custom tile shown
// ACTION: QS Work Mode tile tapped
// CATEGORY: QUICK_SETTINGS
// OS: N
- // GMS: 7.8.99
QS_CUSTOM = 268;
// ACTION: Visual interruptions > Never turn off the screen toggle
// SUBTYPE: 0 is off, 1 is on
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_ZEN_ALLOW_WHEN_SCREEN_ON = 269;
// ACTION: Overview > Long-press task, drag to enter split-screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_WINDOW_DOCK_DRAG_DROP = 270;
// ACTION: In App > Long-press Overview button to enter split-screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_WINDOW_DOCK_LONGPRESS = 271;
// ACTION: In App > Swipe Overview button to enter split-screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_WINDOW_DOCK_SWIPE = 272;
// ACTION: Launch profile-specific app > Confirm credentials
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
PROFILE_CHALLENGE = 273;
// OPEN: QS Battery detail panel
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
QS_BATTERY_DETAIL = 274;
// OPEN: Overview > History
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
OVERVIEW_HISTORY = 275;
// ACTION: Overview > Page by tapping Overview button
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_OVERVIEW_PAGE = 276;
// ACTION: Overview > Select app
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_OVERVIEW_SELECT = 277;
// ACTION: View emergency info
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_VIEW_EMERGENCY_INFO = 278;
// ACTION: Edit emergency info activity
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_EDIT_EMERGENCY_INFO = 279;
// ACTION: Edit emergency info field
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_EDIT_EMERGENCY_INFO_FIELD = 280;
// ACTION: Add emergency contact
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_ADD_EMERGENCY_CONTACT = 281;
// ACTION: Delete emergency contact
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_DELETE_EMERGENCY_CONTACT = 282;
// ACTION: Call emergency contact
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
ACTION_CALL_EMERGENCY_CONTACT = 283;
// OPEN: QS Data Saver tile shown
@@ -1745,13 +1484,11 @@ message MetricsEvent {
// OPEN: Settings > Security > User credentials
// CATEGORY: Settings
// OS: N
- // GMS: 7.8.99
USER_CREDENTIALS = 285;
// ACTION: In App (splitscreen) > Long-press Overview to exit split-screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_WINDOW_UNDOCK_LONGPRESS = 286;
// Logged when the user scrolls through overview manually
@@ -1773,81 +1510,68 @@ message MetricsEvent {
// ACTION: Long-press power button, then tap "Take bug report" option.
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_FROM_POWER_MENU_INTERACTIVE = 292;
// ACTION: Long-press power button, then long-press "Take bug report" option.
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_FROM_POWER_MENU_FULL = 293;
// ACTION: Settings -> Developer Options -> Take bug report -> Interactive report
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
// Interactive bug report initiated from Settings.
ACTION_BUGREPORT_FROM_SETTINGS_INTERACTIVE = 294;
// ACTION: Settings -> Developer Options -> Take bug report -> Full report
// CATEGORY: SETTINGS
// OS: N
- // GMS: 7.8.99
// Interactive bug report initiated from Settings.
ACTION_BUGREPORT_FROM_SETTINGS_FULL = 295;
// ACTION: User tapped notification action to cancel a bug report
// CATEGORY: NOTIFICATION
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_NOTIFICATION_ACTION_CANCEL = 296;
// ACTION: User tapped notification action to launch bug report details screen
// CATEGORY: NOTIFICATION
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_NOTIFICATION_ACTION_DETAILS = 297;
// ACTION: User tapped notification action to take adition screenshot on bug report
// CATEGORY: NOTIFICATION
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_NOTIFICATION_ACTION_SCREENSHOT = 298;
// ACTION: User tapped notification to share bug report
// CATEGORY: NOTIFICATION
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_NOTIFICATION_ACTION_SHARE = 299;
// ACTION: User changed bug report name using the details screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_DETAILS_NAME_CHANGED = 300;
// ACTION: User changed bug report title using the details screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_DETAILS_TITLE_CHANGED = 301;
// ACTION: User changed bug report description using the details screen
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_DETAILS_DESCRIPTION_CHANGED = 302;
// ACTION: User tapped Save in the bug report details screen.
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_DETAILS_SAVED = 303;
// ACTION: User tapped Cancel in the bug report details screen.
// CATEGORY: GLOBAL_SYSTEM_UI
// OS: N
- // GMS: 7.8.99
ACTION_BUGREPORT_DETAILS_CANCELED = 304;
// Tuner: Open/close calibrate dialog.
@@ -1920,79 +1644,140 @@ message MetricsEvent {
// the transition was executed.
APP_TRANSITION_DEVICE_UPTIME_SECONDS = 325;
- // User granted access to the request folder; action takes an integer
- // representing the folder's index on Environment.STANDARD_DIRECTORIES
- // (or -2 for root access, or -1 or unknown directory).
+ // ACTION: app requested access to a scoped directory, user granted it.
+ // SUBTYPE: directory's index on Environment.STANDARD_DIRECTORIES
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER = 326;
- // User denied access to the request folder; action takes an integer
- // representing the folder's index on Environment.STANDARD_DIRECTORIES
- // (or -2 for root access, or -1 or unknown directory).
+ // ACTION: app requested access to a scoped directory, user denied it.
+ // SUBTYPE: directory's index on Environment.STANDARD_DIRECTORIES
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER = 327;
- // User granted access to the request folder; action pass package name
- // of calling package.
+ // ACTION: app requested access to a scoped directory, user granted it.
+ // PACKAGE: app that requested access
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE = 328;
- // User denied access to the request folder; action pass package name
- // of calling package.
+ // ACTION: app requested access to a scoped directory, user denied it.
+ // PACKAGE: app that requested access.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE = 329;
- // App requested access to a directory it has already been granted
- // access before; action takes an integer representing the folder's
- // index on Environment.STANDARD_DIRECTORIES
- // (or -2 for root access, or -1 or unknown directory).
+ // ACTION: app requested access to a directory user has already been granted
+ // access before.
+ // SUBTYPE: directory's index on Environment.STANDARD_DIRECTORIES.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER = 330;
- // App requested access to a directory it has already been granted
- // access before; action pass package name of calling package.
+ // ACTION: app requested access to a directory user has already been granted
+ // access before.
+ // PACKAGE: app that requested access.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE = 331;
- // Logged when the user slides a notification and
- // reveals the gear beneath it.
+ // ACTION: Logged when the user slides a notification and reveals the gear
+ // beneath it.
+ // CATEGORY: NOTIFICATION
+ // OS: N
ACTION_REVEAL_GEAR = 332;
- // Logged when the user taps on the gear beneath
- // a notification.
+ // ACTION: Logged when the user taps on the gear beneath a notification.
+ // CATEGORY: NOTIFICATION
+ // OS: N
ACTION_TOUCH_GEAR = 333;
// Logs that the user has edited the enabled VR listeners.
+ // CATEGORY: SETTINGS
+ // OS: N
VR_MANAGE_LISTENERS = 334;
// Settings -> Accessibility -> Click after pointer stops moving
+ // CATEGORY: SETTINGS
+ // OS: N
ACCESSIBILITY_TOGGLE_AUTOCLICK = 335;
+
// Settings -> Sound
+ // CATEGORY: SETTINGS
+ // OS: N
SOUND = 336;
+
// Settings -> Notifications -> Gear
+ // CATEGORY: SETTINGS
+ // OS: N
CONFIGURE_NOTIFICATION = 337;
+
// Settings -> Wi-Fi -> Gear
+ // CATEGORY: SETTINGS
+ // OS: N
CONFIGURE_WIFI = 338;
+
// Settings -> Display -> Display size
+ // OS: N
DISPLAY_SCREEN_ZOOM = 339;
+
// Settings -> Display -> Font size
+ // CATEGORY: SETTINGS
+ // OS: N
ACCESSIBILITY_FONT_SIZE = 340;
+
// Settings -> Data usage -> Cellular/Wi-Fi data usage
+ // CATEGORY: SETTINGS
+ // OS: N
DATA_USAGE_LIST = 341;
+
// Settings -> Data usage -> Billing cycle or DATA_USAGE_LIST -> Gear
+ // CATEGORY: SETTINGS
+ // OS: N
BILLING_CYCLE = 342;
+
// DATA_USAGE_LIST -> Any item or App info -> Data usage
+ // CATEGORY: SETTINGS
+ // OS: N
APP_DATA_USAGE = 343;
+
// Settings -> Language & input -> Language
+ // CATEGORY: SETTINGS
+ // OS: N
USER_LOCALE_LIST = 344;
+
// Settings -> Language & input -> Virtual keyboard
+ // CATEGORY: SETTINGS
+ // OS: N
VIRTUAL_KEYBOARDS = 345;
+
// Settings -> Language & input -> Physical keyboard
+ // CATEGORY: SETTINGS
+ // OS: N
PHYSICAL_KEYBOARDS = 346;
+
// Settings -> Language & input -> Virtual keyboard -> Add a virtual keyboard
+ // CATEGORY: SETTINGS
+ // OS: N
ENABLE_VIRTUAL_KEYBOARDS = 347;
+
// Settings -> Data usage -> Data Saver
+ // CATEGORY: SETTINGS
+ // OS: N
DATA_SAVER_SUMMARY = 348;
+
// Settings -> Data usage -> Data Saver -> Unrestricted data access
+ // CATEGORY: SETTINGS
+ // OS: N
DATA_USAGE_UNRESTRICTED_ACCESS = 349;
// Used for generic logging of Settings Preference Persistence, should not be used
// outside SharedPreferencesLogger.
+ // CATEGORY: SETTINGS
+ // OS: N
ACTION_GENERIC_PACKAGE = 350;
+
// Settings -> Apps -> Gear -> Special access
SPECIAL_ACCESS = 351;
@@ -2158,15 +1943,28 @@ message MetricsEvent {
// System UI Tuner > Other > Power notification controls > Toggle on/off
ACTION_TUNER_POWER_NOTIFICATION_CONTROLS = 393;
- // Action: user enable / disabled data saver using Settings. Arguments:
- // 0: Data Saver mode is disabled.
- // 1: Data Saver mode is enabled.
+ // Action: user enable / disabled data saver using Settings
+ // OPEN: Settings -> Data Usage -> Data saver -> On/off toggle
+ // VALUE: 1 for enabled, 0 for disabled
+ // CATEGORY: SETTINGS
+ // OS: N
ACTION_DATA_SAVER_MODE = 394;
- // User whitelisted an app for Data Saver mode; action pass package name of app.
+ // User whitelisted an app for Data Saver mode; action pass package name of app
+ // Action: user enable / disabled data saver using Settings
+ // OPEN: Settings -> Data Usage -> Data saver -> Unrestricted data access > APP toggle turned on
+ // or
+ // Settings -> Apps -> APP -> Data usage -> Unrestricted data usage toggle turned on
+ // VALUE: package name of APP
+ // CATEGORY: SETTINGS
+ // OS: N
ACTION_DATA_SAVER_WHITELIST = 395;
- // User blacklisted an app for Data Saver mode; action pass package name of app.
+ // User blacklisted an app for Data Saver mode; action pass package name of app
+ // OPEN: Settings -> Apps -> APP -> Data usage -> Background data toggle turned off
+ // VALUE: package name of APP
+ // CATEGORY: SETTINGS
+ // OS: N
ACTION_DATA_SAVER_BLACKLIST = 396;
// User opened a remote input view associated with a notification. Passes package name of app
@@ -2332,41 +2130,70 @@ message MetricsEvent {
SUPPORT_FRAGMENT = 475;
// ACTION: Settings -> Select summary tab.
+ // CATEGORY: SETTINGS
ACTION_SELECT_SUMMARY=476;
// ACTION: Settings -> Select support tab.
+ // CATEGORY: SETTINGS
ACTION_SELECT_SUPPORT_FRAGMENT = 477;
// ACTION: Settings -> Support -> Tips & tricks
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_TIPS_AND_TRICKS = 478;
// ACTION: Settings -> Support -> Help & feedback
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_HELP_AND_FEEDBACK = 479;
// ACTION: Settings -> Support -> Sign in
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_SIGN_IN = 480;
// ACTION: Settings -> Support -> Phone
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_PHONE = 481;
// ACTION: Settings -> Support -> Chat
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_CHAT = 482;
// ACTION: Settings -> Support -> Phone/Chat -> Disclaimer Cancel
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_DISCLAIMER_CANCEL = 483;
// ACTION: Settings -> Support -> Phone/Chat -> Disclaimer OK
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_DISCLAIMER_OK = 484;
// ACTION: Settings -> Support -> Toll-Free Phone
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_DAIL_TOLLFREE = 485;
// ACTION: Settings -> Support -> "Travel Abroad" Button
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_VIEW_TRAVEL_ABROAD_DIALOG = 486;
// ACTION: Settings -> Support -> "Travel Abroad" Button -> Tolled Phone
+ // CATEGORY: SETTINGS
ACTION_SUPPORT_DIAL_TOLLED = 487;
+ // OPEN: Settings > Display > Night display
+ // CATEGORY: SETTINGS
+ NIGHT_DISPLAY_SETTINGS = 488;
+
+ // ACTION: Settings -> Storage -> Manage storage -> Click Storage Manager
+ // SUBTYPE: false is off, true is on
+ ACTION_TOGGLE_STORAGE_MANAGER = 489;
+
+ // Settings launched from collapsed quick settings.
+ ACTION_QS_COLLAPSED_SETTINGS_LAUNCH = 490;
+
+ // OPEN: QS Night mode tile shown
+ // ACTION: QS Night mode tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ QS_NIGHT_DISPLAY = 491;
+
// ---- End N-MR1 Constants, all N-MR1 constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 60d33397368d..7ebc150bb30b 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1422,7 +1422,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
updateTouchExplorationLocked(userState);
updatePerformGesturesLocked(userState);
updateEnhancedWebAccessibilityLocked(userState);
- updateDisplayColorAdjustmentSettingsLocked(userState);
+ updateDisplayDaltonizerLocked(userState);
+ updateDisplayInversionLocked(userState);
updateMagnificationLocked(userState);
updateSoftKeyboardShowModeLocked(userState);
scheduleUpdateInputFilter(userState);
@@ -1539,7 +1540,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
somethingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
somethingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
somethingChanged |= readAutoclickEnabledSettingLocked(userState);
- somethingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
return somethingChanged;
}
@@ -1602,18 +1602,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return false;
}
- private boolean readDisplayColorAdjustmentSettingsLocked(UserState userState) {
- final boolean displayAdjustmentsEnabled = DisplayAdjustmentUtils.hasAdjustments(mContext,
- userState.mUserId);
- if (displayAdjustmentsEnabled != userState.mHasDisplayColorAdjustment) {
- userState.mHasDisplayColorAdjustment = displayAdjustmentsEnabled;
- return true;
- }
- // If display adjustment is enabled, always assume there was a change in
- // the adjustment settings.
- return displayAdjustmentsEnabled;
- }
-
private boolean readHighTextContrastEnabledSettingLocked(UserState userState) {
final boolean highTextContrastEnabled = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
@@ -1730,8 +1718,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return false;
}
- private void updateDisplayColorAdjustmentSettingsLocked(UserState userState) {
- DisplayAdjustmentUtils.applyAdjustments(mContext, userState.mUserId);
+ private void updateDisplayDaltonizerLocked(UserState userState) {
+ DisplayAdjustmentUtils.applyDaltonizerSetting(mContext, userState.mUserId);
+ }
+
+ private void updateDisplayInversionLocked(UserState userState) {
+ DisplayAdjustmentUtils.applyInversionSetting(mContext, userState.mUserId);
}
private void updateMagnificationLocked(UserState userState) {
@@ -4184,7 +4176,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
public boolean mIsAutoclickEnabled;
public boolean mIsPerformGesturesEnabled;
public boolean mIsFilterKeyEventsEnabled;
- public boolean mHasDisplayColorAdjustment;
public boolean mAccessibilityFocusOnlyInActiveWindow;
private Service mUiAutomationService;
@@ -4300,9 +4291,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER);
- private final Uri mDisplayColorMatrixUri = Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX);
-
private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
@@ -4334,8 +4322,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
contentResolver.registerContentObserver(
mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(
- mDisplayColorMatrixUri, false, this, UserHandle.USER_ALL);
- contentResolver.registerContentObserver(
mHighTextContrastUri, false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(
mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
@@ -4377,14 +4363,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
onUserStateChangedLocked(userState);
}
- } else if (mDisplayInversionEnabledUri.equals(uri)
- || mDisplayDaltonizerEnabledUri.equals(uri)
+ } else if (mDisplayDaltonizerEnabledUri.equals(uri)
|| mDisplayDaltonizerUri.equals(uri)) {
- if (readDisplayColorAdjustmentSettingsLocked(userState)) {
- updateDisplayColorAdjustmentSettingsLocked(userState);
- }
- } else if (mDisplayColorMatrixUri.equals(uri)) {
- updateDisplayColorAdjustmentSettingsLocked(userState);
+ updateDisplayDaltonizerLocked(userState);
+ } else if (mDisplayInversionEnabledUri.equals(uri)) {
+ updateDisplayInversionLocked(userState);
} else if (mHighTextContrastUri.equals(uri)) {
if (readHighTextContrastEnabledSettingLocked(userState)) {
onUserStateChangedLocked(userState);
diff --git a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
index e1f3cd8dc40c..15329461a811 100644
--- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
+++ b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java
@@ -18,23 +18,23 @@ package com.android.server.accessibility;
import android.content.ContentResolver;
import android.content.Context;
-import android.opengl.Matrix;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.provider.Settings;
-import android.util.Slog;
+import android.provider.Settings.Secure;
import android.view.accessibility.AccessibilityManager;
+import com.android.server.LocalServices;
+import com.android.server.display.DisplayTransformManager;
+
/**
* Utility methods for performing accessibility display adjustments.
*/
class DisplayAdjustmentUtils {
- private static final String LOG_TAG = DisplayAdjustmentUtils.class.getSimpleName();
+
+ /** Default inversion mode for display color correction. */
+ private static final int DEFAULT_DISPLAY_DALTONIZER =
+ AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY;
/** Matrix and offset used for converting color to gray-scale. */
- private static final float[] GRAYSCALE_MATRIX = new float[] {
+ private static final float[] MATRIX_GRAYSCALE = new float[] {
.2126f, .2126f, .2126f, 0,
.7152f, .7152f, .7152f, 0,
.0722f, .0722f, .0722f, 0,
@@ -48,150 +48,44 @@ class DisplayAdjustmentUtils {
* represents a non-multiplied addition, see surfaceflinger's ProgramCache
* for full implementation details.
*/
- private static final float[] INVERSION_MATRIX_VALUE_ONLY = new float[] {
+ private static final float[] MATRIX_INVERT_COLOR = new float[] {
0.402f, -0.598f, -0.599f, 0,
-1.174f, -0.174f, -1.175f, 0,
-0.228f, -0.228f, 0.772f, 0,
1, 1, 1, 1
};
- /** Default inversion mode for display color correction. */
- private static final int DEFAULT_DISPLAY_DALTONIZER =
- AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY;
-
- /**
- * Returns whether the specified user with has any display color
- * adjustments.
- */
- public static boolean hasAdjustments(Context context, int userId) {
+ public static void applyDaltonizerSetting(Context context, int userId) {
final ContentResolver cr = context.getContentResolver();
+ final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
- if (Settings.Secure.getIntForUser(cr,
- Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0) {
- return true;
+ int daltonizerMode = AccessibilityManager.DALTONIZER_DISABLED;
+ if (Secure.getIntForUser(cr,
+ Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) {
+ daltonizerMode = Secure.getIntForUser(cr,
+ Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, DEFAULT_DISPLAY_DALTONIZER, userId);
}
- if (Settings.Secure.getIntForUser(cr,
- Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) {
- return true;
+ float[] grayscaleMatrix = null;
+ if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) {
+ // Monochromacy isn't supported by the native Daltonizer.
+ grayscaleMatrix = MATRIX_GRAYSCALE;
+ daltonizerMode = AccessibilityManager.DALTONIZER_DISABLED;
}
-
- return false;
+ dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE, grayscaleMatrix);
+ dtm.setDaltonizerMode(daltonizerMode);
}
/**
* Applies the specified user's display color adjustments.
*/
- public static void applyAdjustments(Context context, int userId) {
+ public static void applyInversionSetting(Context context, int userId) {
final ContentResolver cr = context.getContentResolver();
- float[] colorMatrix = null;
-
- if (Settings.Secure.getIntForUser(cr,
- Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0) {
- colorMatrix = multiply(colorMatrix, INVERSION_MATRIX_VALUE_ONLY);
- }
-
- if (Settings.Secure.getIntForUser(cr,
- Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) {
- final int daltonizerMode = Settings.Secure.getIntForUser(cr,
- Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, DEFAULT_DISPLAY_DALTONIZER,
- userId);
- // Monochromacy isn't supported by the native Daltonizer.
- if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) {
- colorMatrix = multiply(colorMatrix, GRAYSCALE_MATRIX);
- setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
- } else {
- setDaltonizerMode(daltonizerMode);
- }
- } else {
- setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED);
- }
-
- String matrix = Settings.Secure.getStringForUser(cr,
- Settings.Secure.ACCESSIBILITY_DISPLAY_COLOR_MATRIX, userId);
- if (matrix != null) {
- final float[] userMatrix = get4x4Matrix(matrix);
- if (userMatrix != null) {
- colorMatrix = multiply(colorMatrix, userMatrix);
- }
- }
-
- setColorTransform(colorMatrix);
- }
-
- private static float[] get4x4Matrix(String matrix) {
- String[] strValues = matrix.split(",");
- if (strValues.length != 16) {
- return null;
- }
- float[] values = new float[strValues.length];
- try {
- for (int i = 0; i < values.length; i++) {
- values[i] = Float.parseFloat(strValues[i]);
- }
- } catch (java.lang.NumberFormatException ex) {
- return null;
- }
- return values;
- }
+ final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
- private static float[] multiply(float[] matrix, float[] other) {
- if (matrix == null) {
- return other;
- }
- float[] result = new float[16];
- Matrix.multiplyMM(result, 0, matrix, 0, other, 0);
- return result;
+ final boolean invertColors = Secure.getIntForUser(cr,
+ Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0;
+ dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_INVERT_COLOR,
+ invertColors ? MATRIX_INVERT_COLOR : null);
}
-
- /**
- * Sets the surface flinger's Daltonization mode. This adjusts the color
- * space to correct for or simulate various types of color blindness.
- *
- * @param mode new Daltonization mode
- */
- private static void setDaltonizerMode(int mode) {
- try {
- final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
- if (flinger != null) {
- final Parcel data = Parcel.obtain();
- data.writeInterfaceToken("android.ui.ISurfaceComposer");
- data.writeInt(mode);
- flinger.transact(1014, data, null, 0);
- data.recycle();
- }
- } catch (RemoteException ex) {
- Slog.e(LOG_TAG, "Failed to set Daltonizer mode", ex);
- }
- }
-
- /**
- * Sets the surface flinger's color transformation as a 4x4 matrix. If the
- * matrix is null, color transformations are disabled.
- *
- * @param m the float array that holds the transformation matrix, or null to
- * disable transformation
- */
- private static void setColorTransform(float[] m) {
- try {
- final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
- if (flinger != null) {
- final Parcel data = Parcel.obtain();
- data.writeInterfaceToken("android.ui.ISurfaceComposer");
- if (m != null) {
- data.writeInt(1);
- for (int i = 0; i < 16; i++) {
- data.writeFloat(m[i]);
- }
- } else {
- data.writeInt(0);
- }
- flinger.transact(1015, data, null, 0);
- data.recycle();
- }
- } catch (RemoteException ex) {
- Slog.e(LOG_TAG, "Failed to set color transform", ex);
- }
- }
-
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 6defd0f5baef..9d3889b3bdf7 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1905,7 +1905,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
SomeArgs args = SomeArgs.obtain();
args.arg1 = widget.host;
args.arg2 = widget.host.callbacks;
- args.arg3 = updateViews.clone();
+ args.arg3 = (updateViews != null) ? updateViews.clone() : null;
args.arg4 = requestTime;
args.argi1 = widget.appWidgetId;
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index e6f99c15ab66..5ce8c9e6e4cb 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -234,6 +234,7 @@ public class BackupManagerService {
private static final int MSG_WIDGET_BROADCAST = 13;
private static final int MSG_RUN_FULL_TRANSPORT_BACKUP = 14;
private static final int MSG_REQUEST_BACKUP = 15;
+ private static final int MSG_SCHEDULE_BACKUP_PACKAGE = 16;
// backup task state machine tick
static final int MSG_BACKUP_RESTORE_STEP = 20;
@@ -796,7 +797,7 @@ public class BackupManagerService {
queue, oldJournal, null, null, false);
Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
sendMessage(pbtMessage);
- } catch (RemoteException e) {
+ } catch (Exception e) {
// unable to ask the transport its dir name -- transient failure, since
// the above check succeeded. Try again next time.
Slog.e(TAG, "Transport became unavailable attempting backup");
@@ -939,7 +940,7 @@ public class BackupManagerService {
}
if (sets == null) EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
} catch (Exception e) {
- Slog.e(TAG, "Error from transport getting set list");
+ Slog.e(TAG, "Error from transport getting set list: " + e.getMessage());
} finally {
if (params.observer != null) {
try {
@@ -947,7 +948,7 @@ public class BackupManagerService {
} catch (RemoteException re) {
Slog.e(TAG, "Unable to report listing to observer");
} catch (Exception e) {
- Slog.e(TAG, "Restore observer threw", e);
+ Slog.e(TAG, "Restore observer threw: " + e.getMessage());
}
}
@@ -1037,6 +1038,16 @@ public class BackupManagerService {
sendMessage(pbtMessage);
break;
}
+
+ case MSG_SCHEDULE_BACKUP_PACKAGE:
+ {
+ String pkgName = (String)msg.obj;
+ if (MORE_DEBUG) {
+ Slog.d(TAG, "MSG_SCHEDULE_BACKUP_PACKAGE " + pkgName);
+ }
+ dataChangedImpl(pkgName);
+ break;
+ }
}
}
}
@@ -1216,7 +1227,7 @@ public class BackupManagerService {
// Now that we know about valid backup participants, parse any
// leftover journal files into the pending backup set
- parseLeftoverJournals();
+ mBackupHandler.post(() -> parseLeftoverJournals());
// Power management
mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
@@ -1759,8 +1770,10 @@ public class BackupManagerService {
}
return; // done; don't fall through to the error case
}
- } catch (RemoteException e) {
+ } catch (Exception e) {
// transport threw when asked its name; fall through to the lookup-failed case
+ Slog.e(TAG, "Transport " + transportName + " failed to report name: "
+ + e.getMessage());
}
// The named transport doesn't exist or threw. This operation is
@@ -1848,7 +1861,7 @@ public class BackupManagerService {
System.currentTimeMillis() + delay, mRunInitIntent);
}
}
- } catch (RemoteException e) {
+ } catch (Exception e) {
// the transport threw when asked its file naming prefs; declare it invalid
Slog.e(TAG, "Unable to register transport as " + name);
mTransportNames.remove(component);
@@ -2054,8 +2067,9 @@ public class BackupManagerService {
IBackupTransport transport = IBackupTransport.Stub.asInterface(service);
registerTransport(transport.name(), name, transport);
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, name, 1);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to register transport " + component);
+ } catch (Exception e) {
+ Slog.e(TAG, "Unable to register transport " + component
+ + ": " + e.getMessage());
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, name, 0);
}
}
@@ -2161,7 +2175,7 @@ public class BackupManagerService {
int uid = pkg.applicationInfo.uid;
HashSet<String> set = mBackupParticipants.get(uid);
if (set == null) {
- set = new HashSet<String>();
+ set = new HashSet<>();
mBackupParticipants.put(uid, set);
}
set.add(pkg.packageName);
@@ -2169,7 +2183,9 @@ public class BackupManagerService {
// Schedule a backup for it on general principles
if (MORE_DEBUG) Slog.i(TAG, "Scheduling backup for new app " + pkg.packageName);
- dataChangedImpl(pkg.packageName);
+ Message msg = mBackupHandler
+ .obtainMessage(MSG_SCHEDULE_BACKUP_PACKAGE, pkg.packageName);
+ mBackupHandler.sendMessage(msg);
}
}
}
@@ -2516,8 +2532,8 @@ public class BackupManagerService {
String dirName;
try {
dirName = transport.transportDirName();
- } catch (RemoteException e) {
- Slog.e(TAG, "Transport became unavailable while attempting backup");
+ } catch (Exception e) {
+ Slog.e(TAG, "Transport unavailable while attempting backup: " + e.getMessage());
sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
return BackupManager.ERROR_TRANSPORT_ABORTED;
}
@@ -2961,9 +2977,10 @@ public class BackupManagerService {
try {
mCurrentToken = mTransport.getCurrentRestoreSet();
writeRestoreTokens();
- } catch (RemoteException e) {
+ } catch (Exception e) {
// nothing for it at this point, unfortunately, but this will be
// recorded the next time we fully succeed.
+ Slog.e(TAG, "Transport threw reporting restore set: " + e.getMessage());
addBackupTrace("transport threw returning token");
}
}
@@ -2988,7 +3005,7 @@ public class BackupManagerService {
}
}
} catch (Exception e) {
- Slog.w(TAG, "Failed to query transport name heading for init", e);
+ Slog.w(TAG, "Failed to query transport name for init: " + e.getMessage());
// swallow it and proceed; we don't rely on this
}
clearMetadata();
@@ -3354,8 +3371,8 @@ public class BackupManagerService {
try {
long quota = mTransport.getBackupQuota(mCurrentPackage.packageName, false);
mAgentBinder.doQuotaExceeded(size, quota);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to contact backup agent for quota exceeded");
+ } catch (Exception e) {
+ Slog.e(TAG, "Unable to notify about quota exceeded: " + e.getMessage());
}
}
nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE;
@@ -3393,7 +3410,7 @@ public class BackupManagerService {
try {
delay = mTransport.requestBackupTime();
} catch (Exception e) {
- Slog.w(TAG, "Unable to contact transport for recommended backoff");
+ Slog.w(TAG, "Unable to contact transport for recommended backoff: " + e.getMessage());
delay = 0; // use the scheduler's default
}
KeyValueBackupJob.schedule(mContext, delay);
@@ -4311,7 +4328,10 @@ public class BackupManagerService {
Slog.e(TAG, "Internal exception during full backup", e);
} finally {
try {
- if (out != null) out.close();
+ if (out != null) {
+ out.flush();
+ out.close();
+ }
mOutputFile.close();
} catch (IOException e) {
/* nothing we can do about this */
@@ -4649,6 +4669,13 @@ public class BackupManagerService {
}
cleanUpPipes(transportPipes);
cleanUpPipes(enginePipes);
+ if (currentPackage.applicationInfo != null) {
+ Slog.i(TAG, "Unbinding agent in " + packageName);
+ addBackupTrace("unbinding " + packageName);
+ try {
+ mActivityManager.unbindBackupAgent(currentPackage.applicationInfo);
+ } catch (RemoteException e) { /* can't happen; activity manager is local */ }
+ }
}
} catch (Exception e) {
backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
@@ -4984,7 +5011,7 @@ public class BackupManagerService {
return false;
}
} catch (Exception e) {
- Slog.w(TAG, "Unable to contact transport");
+ Slog.w(TAG, "Unable to get transport name: " + e.getMessage());
return false;
}
@@ -8208,9 +8235,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// Success; cache the metadata and continue as expected with the
// next state already enqueued
- } catch (RemoteException e) {
+ } catch (Exception e) {
// If we lost the transport at any time, halt
- Slog.e(TAG, "Unable to contact transport for restore");
+ Slog.e(TAG, "Unable to contact transport for restore: " + e.getMessage());
mStatus = BackupTransport.TRANSPORT_ERROR;
mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
executeNextState(UnifiedRestoreState.FINAL);
@@ -8307,8 +8334,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
nextState = UnifiedRestoreState.RUNNING_QUEUE;
return;
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Can't get next target from transport; ending restore");
+ } catch (Exception e) {
+ Slog.e(TAG, "Can't get next restore target from transport; halting: "
+ + e.getMessage());
EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
nextState = UnifiedRestoreState.FINAL;
return;
@@ -8618,11 +8646,11 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
mCurrentPackage.packageName, "I/O error on pipes");
status = BackupTransport.AGENT_ERROR;
- } catch (RemoteException e) {
- // The transport went away; terminate the whole operation. Closing
+ } catch (Exception e) {
+ // The transport threw; terminate the whole operation. Closing
// the sockets will wake up the engine and it will then tidy up the
// remote end.
- Slog.e(TAG, "Transport failed during restore");
+ Slog.e(TAG, "Transport failed during restore: " + e.getMessage());
EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
status = BackupTransport.TRANSPORT_ERROR;
} finally {
@@ -8660,9 +8688,10 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// level is immaterial; we need to tell the transport to bail
try {
mTransport.abortFullRestore();
- } catch (RemoteException e) {
+ } catch (Exception e) {
// transport itself is dead; make sure we handle this as a
// fatal error
+ Slog.e(TAG, "Transport threw from abortFullRestore: " + e.getMessage());
status = BackupTransport.TRANSPORT_ERROR;
}
@@ -9010,16 +9039,15 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// Tell the transport to remove all the persistent storage for the app
// TODO - need to handle failures
mTransport.clearBackupData(mPackage);
- } catch (RemoteException e) {
- // can't happen; the transport is local
} catch (Exception e) {
- Slog.e(TAG, "Transport threw attempting to clear data for " + mPackage);
+ Slog.e(TAG, "Transport threw clearing data for " + mPackage + ": " + e.getMessage());
} finally {
try {
// TODO - need to handle failures
mTransport.finishBackup();
- } catch (RemoteException e) {
- // can't happen; the transport is local
+ } catch (Exception e) {
+ // Nothing we can do here, alas
+ Slog.e(TAG, "Unable to mark clear operation finished: " + e.getMessage());
}
// Last but not least, release the cpu
@@ -9078,8 +9106,6 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
System.currentTimeMillis() + delay, mRunInitIntent);
}
}
- } catch (RemoteException e) {
- // can't happen; the transports are local
} catch (Exception e) {
Slog.e(TAG, "Unexpected error performing init", e);
} finally {
@@ -9767,8 +9793,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
if (MORE_DEBUG) Slog.d(TAG, "getConfigurationIntent() returning config intent "
+ intent);
return intent;
- } catch (RemoteException e) {
+ } catch (Exception e) {
/* fall through to return null */
+ Slog.e(TAG, "Unable to get configuration intent from transport: " + e.getMessage());
}
}
}
@@ -9792,8 +9819,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
final String text = transport.currentDestinationString();
if (MORE_DEBUG) Slog.d(TAG, "getDestinationString() returning " + text);
return text;
- } catch (RemoteException e) {
+ } catch (Exception e) {
/* fall through to return null */
+ Slog.e(TAG, "Unable to get string from transport: " + e.getMessage());
}
}
}
@@ -9814,8 +9842,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
if (MORE_DEBUG) Slog.d(TAG, "getDataManagementIntent() returning intent "
+ intent);
return intent;
- } catch (RemoteException e) {
+ } catch (Exception e) {
/* fall through to return null */
+ Slog.e(TAG, "Unable to get management intent from transport: " + e.getMessage());
}
}
}
@@ -9836,8 +9865,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
final String text = transport.dataManagementLabel();
if (MORE_DEBUG) Slog.d(TAG, "getDataManagementLabel() returning " + text);
return text;
- } catch (RemoteException e) {
+ } catch (Exception e) {
/* fall through to return null */
+ Slog.e(TAG, "Unable to get management label from transport: " + e.getMessage());
}
}
}
@@ -9930,9 +9960,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
msg.obj = new RestoreParams(transport, dirName, null,
restoreSet, packageName, token);
mBackupHandler.sendMessage(msg);
- } catch (RemoteException e) {
- // Binding to the transport broke; back off and proceed with the installation.
- Slog.e(TAG, "Unable to contact transport");
+ } catch (Exception e) {
+ // Calling into the transport broke; back off and proceed with the installation.
+ Slog.e(TAG, "Unable to contact transport: " + e.getMessage());
skip = true;
}
}
@@ -10053,8 +10083,8 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
try {
return transport.isAppEligibleForBackup(packageInfo,
appGetsFullBackup(packageInfo));
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to contact transport");
+ } catch (Exception e) {
+ Slog.e(TAG, "Unable to ask about eligibility: " + e.getMessage());
}
}
// If transport is not present we couldn't tell that the package is not eligible.
@@ -10156,9 +10186,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
String dirName;
try {
dirName = mRestoreTransport.transportDirName();
- } catch (RemoteException e) {
+ } catch (Exception e) {
// Transport went AWOL; fail.
- Slog.e(TAG, "Unable to contact transport for restore");
+ Slog.e(TAG, "Unable to get transport dir for restore: " + e.getMessage());
return -1;
}
@@ -10238,9 +10268,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
String dirName;
try {
dirName = mRestoreTransport.transportDirName();
- } catch (RemoteException e) {
+ } catch (Exception e) {
// Transport went AWOL; fail.
- Slog.e(TAG, "Unable to contact transport for restore");
+ Slog.e(TAG, "Unable to get transport name for restoreSome: " + e.getMessage());
return -1;
}
@@ -10328,9 +10358,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
String dirName;
try {
dirName = mRestoreTransport.transportDirName();
- } catch (RemoteException e) {
+ } catch (Exception e) {
// Transport went AWOL; fail.
- Slog.e(TAG, "Unable to contact transport for restore");
+ Slog.e(TAG, "Unable to get transport dir for restorePackage: " + e.getMessage());
return -1;
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 312553a980b2..4dd88b20fb7f 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -2547,7 +2547,9 @@ class AlarmManagerService extends SystemService {
} else {
// Just in case -- even though no wakeup flag was set, make sure
// we have updated the kernel to the next alarm time.
- rescheduleKernelAlarmsLocked();
+ synchronized (mLock) {
+ rescheduleKernelAlarmsLocked();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/AnyMotionDetector.java b/services/core/java/com/android/server/AnyMotionDetector.java
index a8ae914d0e9a..f93c716ae162 100644
--- a/services/core/java/com/android/server/AnyMotionDetector.java
+++ b/services/core/java/com/android/server/AnyMotionDetector.java
@@ -70,6 +70,9 @@ public class AnyMotionDetector {
/** The interval between accelerometer orientation measurements. */
private static final long ORIENTATION_MEASUREMENT_INTERVAL_MILLIS = 5000;
+ /** The maximum duration we will hold a wakelock to determine stationary status. */
+ private static final long WAKELOCK_TIMEOUT_MILLIS = 30000;
+
/**
* The duration in milliseconds after which an orientation measurement is considered
* too stale to be used.
@@ -141,25 +144,30 @@ public class AnyMotionDetector {
mCurrentGravityVector = null;
mPreviousGravityVector = null;
mWakeLock.acquire();
+ Message wakelockTimeoutMsg = Message.obtain(mHandler, mWakelockTimeout);
+ mHandler.sendMessageDelayed(wakelockTimeoutMsg, WAKELOCK_TIMEOUT_MILLIS);
startOrientationMeasurementLocked();
}
}
}
public void stop() {
- if (mState == STATE_ACTIVE) {
- synchronized (mLock) {
+ synchronized (mLock) {
+ if (mState == STATE_ACTIVE) {
mState = STATE_INACTIVE;
if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE.");
- if (mMeasurementInProgress) {
- mMeasurementInProgress = false;
- mSensorManager.unregisterListener(mListener);
- }
- mHandler.removeCallbacks(mMeasurementTimeout);
- mHandler.removeCallbacks(mSensorRestart);
- mCurrentGravityVector = null;
- mPreviousGravityVector = null;
+ }
+ if (mMeasurementInProgress) {
+ mMeasurementInProgress = false;
+ mSensorManager.unregisterListener(mListener);
+ }
+ mHandler.removeCallbacks(mMeasurementTimeout);
+ mHandler.removeCallbacks(mSensorRestart);
+ mCurrentGravityVector = null;
+ mPreviousGravityVector = null;
+ if (mWakeLock.isHeld()) {
mWakeLock.release();
+ mHandler.removeCallbacks(mWakelockTimeout);
}
}
}
@@ -173,9 +181,8 @@ public class AnyMotionDetector {
mMeasurementInProgress = true;
mRunningStats.reset();
}
- Message msg = Message.obtain(mHandler, mMeasurementTimeout);
- msg.setAsynchronous(true);
- mHandler.sendMessageDelayed(msg, ACCELEROMETER_DATA_TIMEOUT_MILLIS);
+ Message measurementTimeoutMsg = Message.obtain(mHandler, mMeasurementTimeout);
+ mHandler.sendMessageDelayed(measurementTimeoutMsg, ACCELEROMETER_DATA_TIMEOUT_MILLIS);
}
}
@@ -186,10 +193,12 @@ public class AnyMotionDetector {
if (mMeasurementInProgress) {
mSensorManager.unregisterListener(mListener);
mHandler.removeCallbacks(mMeasurementTimeout);
- long detectionEndTime = SystemClock.elapsedRealtime();
mMeasurementInProgress = false;
mPreviousGravityVector = mCurrentGravityVector;
mCurrentGravityVector = mRunningStats.getRunningAverage();
+ if (mRunningStats.getSampleCount() == 0) {
+ Slog.w(TAG, "No accelerometer data acquired for orientation measurement.");
+ }
if (DEBUG) {
Slog.d(TAG, "mRunningStats = " + mRunningStats.toString());
String currentGravityVectorString = (mCurrentGravityVector == null) ?
@@ -203,7 +212,10 @@ public class AnyMotionDetector {
status = getStationaryStatus();
if (DEBUG) Slog.d(TAG, "getStationaryStatus() returned " + status);
if (status != RESULT_UNKNOWN) {
- mWakeLock.release();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ mHandler.removeCallbacks(mWakelockTimeout);
+ }
if (DEBUG) {
Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE. status = " + status);
}
@@ -217,7 +229,6 @@ public class AnyMotionDetector {
" scheduled in " + ORIENTATION_MEASUREMENT_INTERVAL_MILLIS +
" milliseconds.");
Message msg = Message.obtain(mHandler, mSensorRestart);
- msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, ORIENTATION_MEASUREMENT_INTERVAL_MILLIS);
}
}
@@ -271,6 +282,7 @@ public class AnyMotionDetector {
}
}
if (status != RESULT_UNKNOWN) {
+ mHandler.removeCallbacks(mWakelockTimeout);
mCallback.onAnyMotionResult(status);
}
}
@@ -290,20 +302,30 @@ public class AnyMotionDetector {
};
private final Runnable mMeasurementTimeout = new Runnable() {
- @Override
- public void run() {
- int status = RESULT_UNKNOWN;
- synchronized (mLock) {
- if (DEBUG) Slog.i(TAG, "mMeasurementTimeout. Failed to collect sufficient accel " +
+ @Override
+ public void run() {
+ int status = RESULT_UNKNOWN;
+ synchronized (mLock) {
+ if (DEBUG) Slog.i(TAG, "mMeasurementTimeout. Failed to collect sufficient accel " +
"data within " + ACCELEROMETER_DATA_TIMEOUT_MILLIS + " ms. Stopping " +
"orientation measurement.");
- status = stopOrientationMeasurementLocked();
- }
- if (status != RESULT_UNKNOWN) {
- mCallback.onAnyMotionResult(status);
- }
- }
- };
+ status = stopOrientationMeasurementLocked();
+ }
+ if (status != RESULT_UNKNOWN) {
+ mHandler.removeCallbacks(mWakelockTimeout);
+ mCallback.onAnyMotionResult(status);
+ }
+ }
+ };
+
+ private final Runnable mWakelockTimeout = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mLock) {
+ stop();
+ }
+ }
+ };
/**
* A timestamped three dimensional vector and some vector operations.
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b12a9619e506..ef41f49a9d45 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -303,7 +303,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
/**
* indicates a timeout period is over - check if we had a network yet or not
- * and if not, call the timeout calback (but leave the request live until they
+ * and if not, call the timeout callback (but leave the request live until they
* cancel it.
* includes a NetworkRequestInfo
*/
@@ -380,6 +380,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
+ /**
+ * Indicates a caller has requested to have its callback invoked with
+ * the latest LinkProperties or NetworkCapabilities.
+ *
+ * arg1 = UID of caller
+ * obj = NetworkRequest
+ */
+ private static final int EVENT_REQUEST_LINKPROPERTIES = 32;
+ private static final int EVENT_REQUEST_NETCAPABILITIES = 33;
+
/** Handler thread used for both of the handlers below. */
@VisibleForTesting
protected final HandlerThread mHandlerThread;
@@ -439,6 +449,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
private static final int MAX_NETWORK_REQUEST_LOGS = 20;
private final LocalLog mNetworkRequestInfoLogs = new LocalLog(MAX_NETWORK_REQUEST_LOGS);
+ // NetworkInfo blocked and unblocked String log entries
+ // TODO: consider reducing memory usage. Each log line is ~40 2B chars, for a total of ~8kB.
+ private static final int MAX_NETWORK_INFO_LOGS = 100;
+ private final LocalLog mNetworkInfoBlockingLogs = new LocalLog(MAX_NETWORK_INFO_LOGS);
+
// Array of <Network,ReadOnlyLocalLogs> tracking network validation and results
private static final int MAX_VALIDATION_LOGS = 10;
private static class ValidationLog {
@@ -1003,7 +1018,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) {
- if (ni == null || !LOGD_BLOCKED_NETWORKINFO) return;
+ if (ni == null || !LOGD_BLOCKED_NETWORKINFO) {
+ return;
+ }
boolean removed = false;
boolean added = false;
synchronized (mBlockedAppUids) {
@@ -1013,8 +1030,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
removed = true;
}
}
- if (added) log("Returning blocked NetworkInfo to uid=" + uid);
- else if (removed) log("Returning unblocked NetworkInfo to uid=" + uid);
+ if (added) {
+ log("Returning blocked NetworkInfo to uid=" + uid);
+ mNetworkInfoBlockingLogs.log("BLOCKED " + uid);
+ } else if (removed) {
+ log("Returning unblocked NetworkInfo to uid=" + uid);
+ mNetworkInfoBlockingLogs.log("UNBLOCKED " + uid);
+ }
}
/**
@@ -2014,6 +2036,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.increaseIndent();
mNetworkRequestInfoLogs.reverseDump(fd, pw, args);
pw.decreaseIndent();
+
+ pw.println();
+ pw.println("mNetworkInfoBlockingLogs (most recent first):");
+ pw.increaseIndent();
+ mNetworkInfoBlockingLogs.reverseDump(fd, pw, args);
+ pw.decreaseIndent();
}
}
@@ -2447,106 +2475,146 @@ public class ConnectivityService extends IConnectivityManager.Stub
return true;
}
- private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
- NetworkRequestInfo nri = mNetworkRequests.get(request);
+ private NetworkRequestInfo getNriForAppRequest(
+ NetworkRequest request, int callingUid, String requestedOperation) {
+ final NetworkRequestInfo nri = mNetworkRequests.get(request);
+
if (nri != null) {
if (Process.SYSTEM_UID != callingUid && nri.mUid != callingUid) {
- if (DBG) log("Attempt to release unowned NetworkRequest " + request);
- return;
+ log(String.format("UID %d attempted to %s for unowned request %s",
+ callingUid, requestedOperation, nri));
+ return null;
}
- if (VDBG || (DBG && nri.request.isRequest())) log("releasing " + request);
- nri.unlinkDeathRecipient();
- mNetworkRequests.remove(request);
- synchronized (mUidToNetworkRequestCount) {
- int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
- if (requests < 1) {
- Slog.wtf(TAG, "BUG: too small request count " + requests + " for UID " +
- nri.mUid);
- } else if (requests == 1) {
- mUidToNetworkRequestCount.removeAt(
- mUidToNetworkRequestCount.indexOfKey(nri.mUid));
+ }
+
+ return nri;
+ }
+
+ private void handleRequestCallbackUpdate(NetworkRequest request, int callingUid,
+ String description, int callbackType) {
+ final NetworkRequestInfo nri = getNriForAppRequest(request, callingUid, description);
+ if (nri == null) return;
+
+ final NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
+ // The network that is satisfying this request may have changed since
+ // the application requested the update.
+ //
+ // - If the request is no longer satisfied, don't send any updates.
+ // - If the request is satisfied by a different network, it is the
+ // caller's responsibility to check that the Network object in the
+ // callback matches the network that was returned in the last
+ // onAvailable() callback for this request.
+ if (nai == null) return;
+ callCallbackForRequest(nri, nai, callbackType, 0);
+ }
+
+ private void handleRequestLinkProperties(NetworkRequest request, int callingUid) {
+ handleRequestCallbackUpdate(request, callingUid,
+ "request LinkProperties", ConnectivityManager.CALLBACK_IP_CHANGED);
+ }
+
+ private void handleRequestNetworkCapabilities(NetworkRequest request, int callingUid) {
+ handleRequestCallbackUpdate(request, callingUid,
+ "request NetworkCapabilities", ConnectivityManager.CALLBACK_CAP_CHANGED);
+ }
+
+ private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
+ final NetworkRequestInfo nri = getNriForAppRequest(
+ request, callingUid, "release NetworkRequest");
+ if (nri == null) return;
+
+ if (VDBG || (DBG && nri.request.isRequest())) log("releasing " + request);
+ nri.unlinkDeathRecipient();
+ mNetworkRequests.remove(request);
+ synchronized (mUidToNetworkRequestCount) {
+ int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
+ if (requests < 1) {
+ Slog.wtf(TAG, "BUG: too small request count " + requests + " for UID " +
+ nri.mUid);
+ } else if (requests == 1) {
+ mUidToNetworkRequestCount.removeAt(
+ mUidToNetworkRequestCount.indexOfKey(nri.mUid));
+ } else {
+ mUidToNetworkRequestCount.put(nri.mUid, requests - 1);
+ }
+ }
+ mNetworkRequestInfoLogs.log("RELEASE " + nri);
+ if (nri.request.isRequest()) {
+ boolean wasKept = false;
+ NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
+ if (nai != null) {
+ nai.removeRequest(nri.request.requestId);
+ if (VDBG) {
+ log(" Removing from current network " + nai.name() +
+ ", leaving " + nai.numNetworkRequests() + " requests.");
+ }
+ // If there are still lingered requests on this network, don't tear it down,
+ // but resume lingering instead.
+ updateLingerState(nai, SystemClock.elapsedRealtime());
+ if (unneeded(nai)) {
+ if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
+ teardownUnneededNetwork(nai);
} else {
- mUidToNetworkRequestCount.put(nri.mUid, requests - 1);
+ wasKept = true;
}
+ mNetworkForRequestId.remove(nri.request.requestId);
}
- mNetworkRequestInfoLogs.log("RELEASE " + nri);
- if (nri.request.isRequest()) {
- boolean wasKept = false;
- NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
- if (nai != null) {
- nai.removeRequest(nri.request.requestId);
- if (VDBG) {
- log(" Removing from current network " + nai.name() +
- ", leaving " + nai.numNetworkRequests() + " requests.");
- }
- // If there are still lingered requests on this network, don't tear it down,
- // but resume lingering instead.
- updateLingerState(nai, SystemClock.elapsedRealtime());
- if (unneeded(nai)) {
- if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
- teardownUnneededNetwork(nai);
- } else {
- wasKept = true;
- }
- mNetworkForRequestId.remove(nri.request.requestId);
- }
- // TODO: remove this code once we know that the Slog.wtf is never hit.
- //
- // Find all networks that are satisfying this request and remove the request
- // from their request lists.
- // TODO - it's my understanding that for a request there is only a single
- // network satisfying it, so this loop is wasteful
- for (NetworkAgentInfo otherNai : mNetworkAgentInfos.values()) {
- if (otherNai.isSatisfyingRequest(nri.request.requestId) && otherNai != nai) {
- Slog.wtf(TAG, "Request " + nri.request + " satisfied by " +
- otherNai.name() + ", but mNetworkAgentInfos says " +
- (nai != null ? nai.name() : "null"));
- }
+ // TODO: remove this code once we know that the Slog.wtf is never hit.
+ //
+ // Find all networks that are satisfying this request and remove the request
+ // from their request lists.
+ // TODO - it's my understanding that for a request there is only a single
+ // network satisfying it, so this loop is wasteful
+ for (NetworkAgentInfo otherNai : mNetworkAgentInfos.values()) {
+ if (otherNai.isSatisfyingRequest(nri.request.requestId) && otherNai != nai) {
+ Slog.wtf(TAG, "Request " + nri.request + " satisfied by " +
+ otherNai.name() + ", but mNetworkAgentInfos says " +
+ (nai != null ? nai.name() : "null"));
}
+ }
- // Maintain the illusion. When this request arrived, we might have pretended
- // that a network connected to serve it, even though the network was already
- // connected. Now that this request has gone away, we might have to pretend
- // that the network disconnected. LegacyTypeTracker will generate that
- // phantom disconnect for this type.
- if (nri.request.legacyType != TYPE_NONE && nai != null) {
- boolean doRemove = true;
- if (wasKept) {
- // check if any of the remaining requests for this network are for the
- // same legacy type - if so, don't remove the nai
- for (int i = 0; i < nai.numNetworkRequests(); i++) {
- NetworkRequest otherRequest = nai.requestAt(i);
- if (otherRequest.legacyType == nri.request.legacyType &&
- otherRequest.isRequest()) {
- if (DBG) log(" still have other legacy request - leaving");
- doRemove = false;
- }
+ // Maintain the illusion. When this request arrived, we might have pretended
+ // that a network connected to serve it, even though the network was already
+ // connected. Now that this request has gone away, we might have to pretend
+ // that the network disconnected. LegacyTypeTracker will generate that
+ // phantom disconnect for this type.
+ if (nri.request.legacyType != TYPE_NONE && nai != null) {
+ boolean doRemove = true;
+ if (wasKept) {
+ // check if any of the remaining requests for this network are for the
+ // same legacy type - if so, don't remove the nai
+ for (int i = 0; i < nai.numNetworkRequests(); i++) {
+ NetworkRequest otherRequest = nai.requestAt(i);
+ if (otherRequest.legacyType == nri.request.legacyType &&
+ otherRequest.isRequest()) {
+ if (DBG) log(" still have other legacy request - leaving");
+ doRemove = false;
}
}
-
- if (doRemove) {
- mLegacyTypeTracker.remove(nri.request.legacyType, nai, false);
- }
}
- for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
- nri.request);
+ if (doRemove) {
+ mLegacyTypeTracker.remove(nri.request.legacyType, nai, false);
}
- } else {
- // listens don't have a singular affectedNetwork. Check all networks to see
- // if this listen request applies and remove it.
- for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
- nai.removeRequest(nri.request.requestId);
- if (nri.request.networkCapabilities.hasSignalStrength() &&
- nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
- updateSignalStrengthThresholds(nai, "RELEASE", nri.request);
- }
+ }
+
+ for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+ nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
+ nri.request);
+ }
+ } else {
+ // listens don't have a singular affectedNetwork. Check all networks to see
+ // if this listen request applies and remove it.
+ for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+ nai.removeRequest(nri.request.requestId);
+ if (nri.request.networkCapabilities.hasSignalStrength() &&
+ nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
+ updateSignalStrengthThresholds(nai, "RELEASE", nri.request);
}
}
- callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED, 0);
}
+ callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED, 0);
}
@Override
@@ -2709,6 +2777,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
handleMobileDataAlwaysOn();
break;
}
+ case EVENT_REQUEST_LINKPROPERTIES:
+ handleRequestLinkProperties((NetworkRequest) msg.obj, msg.arg1);
+ break;
+ case EVENT_REQUEST_NETCAPABILITIES:
+ handleRequestNetworkCapabilities((NetworkRequest) msg.obj, msg.arg1);
+ break;
// Sent by KeepaliveTracker to process an app request on the state machine thread.
case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
mKeepaliveTracker.handleStartKeepalive(msg);
@@ -4170,10 +4244,26 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
@Override
+ public void requestLinkProperties(NetworkRequest networkRequest) {
+ ensureNetworkRequestHasType(networkRequest);
+ if (networkRequest.type == NetworkRequest.Type.LISTEN) return;
+ mHandler.sendMessage(mHandler.obtainMessage(
+ EVENT_REQUEST_LINKPROPERTIES, getCallingUid(), 0, networkRequest));
+ }
+
+ @Override
+ public void requestNetworkCapabilities(NetworkRequest networkRequest) {
+ ensureNetworkRequestHasType(networkRequest);
+ if (networkRequest.type == NetworkRequest.Type.LISTEN) return;
+ mHandler.sendMessage(mHandler.obtainMessage(
+ EVENT_REQUEST_NETCAPABILITIES, getCallingUid(), 0, networkRequest));
+ }
+
+ @Override
public void releaseNetworkRequest(NetworkRequest networkRequest) {
ensureNetworkRequestHasType(networkRequest);
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(),
- 0, networkRequest));
+ mHandler.sendMessage(mHandler.obtainMessage(
+ EVENT_RELEASE_NETWORK_REQUEST, getCallingUid(), 0, networkRequest));
}
@Override
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index afed5ef066ff..488f0e793c9a 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -973,13 +973,12 @@ public class DeviceIdleController extends SystemService
cancelSensingTimeoutAlarmLocked();
}
}
- if (result == AnyMotionDetector.RESULT_MOVED) {
- if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
+ if ((result == AnyMotionDetector.RESULT_MOVED) ||
+ (result == AnyMotionDetector.RESULT_UNKNOWN)) {
synchronized (this) {
- handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");
+ handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "non_stationary");
}
} else if (result == AnyMotionDetector.RESULT_STATIONARY) {
- if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
if (mState == STATE_SENSING) {
// If we are currently sensing, it is time to move to locating.
synchronized (this) {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 85eee2bb27e2..e28fa7370338 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -69,6 +69,7 @@ import android.util.Log;
import android.util.Slog;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.VerifyCredentialResponse;
@@ -348,7 +349,7 @@ public class LockSettingsService extends ILockSettings.Stub {
CharSequence detail = r.getText(
com.android.internal.R.string.user_encrypted_detail);
- PendingIntent intent = PendingIntent.getBroadcast(mContext, 0, ACTION_NULL,
+ PendingIntent intent = PendingIntent.getActivity(mContext, 0, ACTION_NULL,
PendingIntent.FLAG_UPDATE_CURRENT);
showEncryptionNotification(user, title, message, detail, intent);
@@ -760,7 +761,7 @@ public class LockSettingsService extends ILockSettings.Stub {
private void unlockChildProfile(int profileHandle) throws RemoteException {
try {
doVerifyPassword(getDecryptedPasswordForTiedProfile(profileHandle), false,
- 0 /* no challenge */, profileHandle);
+ 0 /* no challenge */, profileHandle, null /* progressCallback */);
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
| NoSuchAlgorithmException | NoSuchPaddingException
| InvalidAlgorithmParameterException | IllegalBlockSizeException
@@ -947,7 +948,7 @@ public class LockSettingsService extends ILockSettings.Stub {
CredentialHash willStore
= new CredentialHash(enrolledHandle, CredentialHash.VERSION_GATEKEEPER);
setUserKeyProtection(userId, pattern,
- doVerifyPattern(pattern, willStore, true, 0, userId));
+ doVerifyPattern(pattern, willStore, true, 0, userId, null /* progressCallback */));
mStorage.writePatternHash(enrolledHandle, userId);
fixateNewestUserKeyAuth(userId);
onUserLockChanged(userId);
@@ -1007,7 +1008,8 @@ public class LockSettingsService extends ILockSettings.Stub {
CredentialHash willStore
= new CredentialHash(enrolledHandle, CredentialHash.VERSION_GATEKEEPER);
setUserKeyProtection(userId, password,
- doVerifyPassword(password, willStore, true, 0, userId));
+ doVerifyPassword(password, willStore, true, 0, userId,
+ null /* progressCallback */));
mStorage.writePasswordHash(enrolledHandle, userId);
fixateNewestUserKeyAuth(userId);
onUserLockChanged(userId);
@@ -1205,25 +1207,29 @@ public class LockSettingsService extends ILockSettings.Stub {
}
@Override
- public VerifyCredentialResponse checkPattern(String pattern, int userId) throws RemoteException {
- return doVerifyPattern(pattern, false, 0, userId);
+ public VerifyCredentialResponse checkPattern(String pattern, int userId,
+ ICheckCredentialProgressCallback progressCallback) throws RemoteException {
+ return doVerifyPattern(pattern, false, 0, userId, progressCallback);
}
@Override
public VerifyCredentialResponse verifyPattern(String pattern, long challenge, int userId)
throws RemoteException {
- return doVerifyPattern(pattern, true, challenge, userId);
+ return doVerifyPattern(pattern, true, challenge, userId, null /* progressCallback */);
}
private VerifyCredentialResponse doVerifyPattern(String pattern, boolean hasChallenge,
- long challenge, int userId) throws RemoteException {
+ long challenge, int userId, ICheckCredentialProgressCallback progressCallback)
+ throws RemoteException {
checkPasswordReadPermission(userId);
CredentialHash storedHash = mStorage.readPatternHash(userId);
- return doVerifyPattern(pattern, storedHash, hasChallenge, challenge, userId);
+ return doVerifyPattern(pattern, storedHash, hasChallenge, challenge, userId,
+ progressCallback);
}
private VerifyCredentialResponse doVerifyPattern(String pattern, CredentialHash storedHash,
- boolean hasChallenge, long challenge, int userId) throws RemoteException {
+ boolean hasChallenge, long challenge, int userId,
+ ICheckCredentialProgressCallback progressCallback) throws RemoteException {
boolean shouldReEnrollBaseZero = storedHash != null && storedHash.isBaseZeroPattern;
String patternToVerify;
@@ -1252,7 +1258,8 @@ public class LockSettingsService extends ILockSettings.Stub {
public String adjustForKeystore(String pattern) {
return LockPatternUtils.patternStringToBaseZero(pattern);
}
- }
+ },
+ progressCallback
);
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK
@@ -1264,15 +1271,15 @@ public class LockSettingsService extends ILockSettings.Stub {
}
@Override
- public VerifyCredentialResponse checkPassword(String password, int userId)
- throws RemoteException {
- return doVerifyPassword(password, false, 0, userId);
+ public VerifyCredentialResponse checkPassword(String password, int userId,
+ ICheckCredentialProgressCallback progressCallback) throws RemoteException {
+ return doVerifyPassword(password, false, 0, userId, progressCallback);
}
@Override
public VerifyCredentialResponse verifyPassword(String password, long challenge, int userId)
throws RemoteException {
- return doVerifyPassword(password, true, challenge, userId);
+ return doVerifyPassword(password, true, challenge, userId, null /* progressCallback */);
}
@Override
@@ -1285,8 +1292,10 @@ public class LockSettingsService extends ILockSettings.Stub {
final int parentProfileId = mUserManager.getProfileParent(userId).id;
// Unlock parent by using parent's challenge
final VerifyCredentialResponse parentResponse = isPattern
- ? doVerifyPattern(password, true, challenge, parentProfileId)
- : doVerifyPassword(password, true, challenge, parentProfileId);
+ ? doVerifyPattern(password, true, challenge, parentProfileId,
+ null /* progressCallback */)
+ : doVerifyPassword(password, true, challenge, parentProfileId,
+ null /* progressCallback */);
if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
// Failed, just return parent's response
return parentResponse;
@@ -1296,7 +1305,7 @@ public class LockSettingsService extends ILockSettings.Stub {
// Unlock work profile, and work profile with unified lock must use password only
return doVerifyPassword(getDecryptedPasswordForTiedProfile(userId), true,
challenge,
- userId);
+ userId, null /* progressCallback */);
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
| NoSuchAlgorithmException | NoSuchPaddingException
| InvalidAlgorithmParameterException | IllegalBlockSizeException
@@ -1307,14 +1316,17 @@ public class LockSettingsService extends ILockSettings.Stub {
}
private VerifyCredentialResponse doVerifyPassword(String password, boolean hasChallenge,
- long challenge, int userId) throws RemoteException {
+ long challenge, int userId, ICheckCredentialProgressCallback progressCallback)
+ throws RemoteException {
checkPasswordReadPermission(userId);
CredentialHash storedHash = mStorage.readPasswordHash(userId);
- return doVerifyPassword(password, storedHash, hasChallenge, challenge, userId);
+ return doVerifyPassword(password, storedHash, hasChallenge, challenge, userId,
+ progressCallback);
}
private VerifyCredentialResponse doVerifyPassword(String password, CredentialHash storedHash,
- boolean hasChallenge, long challenge, int userId) throws RemoteException {
+ boolean hasChallenge, long challenge, int userId,
+ ICheckCredentialProgressCallback progressCallback) throws RemoteException {
return verifyCredential(userId, storedHash, password, hasChallenge, challenge,
new CredentialUtil() {
@Override
@@ -1332,12 +1344,12 @@ public class LockSettingsService extends ILockSettings.Stub {
public String adjustForKeystore(String password) {
return password;
}
- }
- );
+ }, progressCallback);
}
private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
- String credential, boolean hasChallenge, long challenge, CredentialUtil credentialUtil)
+ String credential, boolean hasChallenge, long challenge, CredentialUtil credentialUtil,
+ ICheckCredentialProgressCallback progressCallback)
throws RemoteException {
if ((storedHash == null || storedHash.hash.length == 0) && TextUtils.isEmpty(credential)) {
// don't need to pass empty credentials to GateKeeper
@@ -1394,7 +1406,13 @@ public class LockSettingsService extends ILockSettings.Stub {
}
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+
+
// credential has matched
+
+ if (progressCallback != null) {
+ progressCallback.onCredentialVerified();
+ }
unlockKeystore(credential, userId);
Slog.i(TAG, "Unlocking user " + userId +
@@ -1450,7 +1468,7 @@ public class LockSettingsService extends ILockSettings.Stub {
try {
if (mLockPatternUtils.isLockPatternEnabled(userId)) {
- if (checkPattern(password, userId).getResponseCode()
+ if (checkPattern(password, userId, null /* progressCallback */).getResponseCode()
== GateKeeperResponse.RESPONSE_OK) {
return true;
}
@@ -1460,7 +1478,7 @@ public class LockSettingsService extends ILockSettings.Stub {
try {
if (mLockPatternUtils.isLockPasswordEnabled(userId)) {
- if (checkPassword(password, userId).getResponseCode()
+ if (checkPassword(password, userId, null /* progressCallback */).getResponseCode()
== GateKeeperResponse.RESPONSE_OK) {
return true;
}
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index e233b1c84bc6..080b46c24a2f 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -157,11 +157,10 @@ public class PersistentDataBlockService extends SystemService {
}
}
- private void enforceFactoryResetAllowed() {
- final boolean isOemUnlockRestricted = UserManager.get(mContext)
- .hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET);
- if (isOemUnlockRestricted) {
- throw new SecurityException("OEM unlock is disallowed by DISALLOW_FACTORY_RESET");
+ private void enforceUserRestriction(String userRestriction) {
+ if (UserManager.get(mContext).hasUserRestriction(userRestriction)) {
+ throw new SecurityException(
+ "OEM unlock is disallowed by user restriction: " + userRestriction);
}
}
@@ -467,13 +466,9 @@ public class PersistentDataBlockService extends SystemService {
enforceIsAdmin();
if (enabled) {
- // Do not allow oem unlock to be enabled if it has been disallowed.
- if (Settings.Global.getInt(getContext().getContentResolver(),
- Settings.Global.OEM_UNLOCK_DISALLOWED, 0) == 1) {
- throw new SecurityException(
- "OEM unlock has been disallowed by OEM_UNLOCK_DISALLOWED.");
- }
- enforceFactoryResetAllowed();
+ // Do not allow oem unlock to be enabled if it's disallowed by a user restriction.
+ enforceUserRestriction(UserManager.DISALLOW_OEM_UNLOCK);
+ enforceUserRestriction(UserManager.DISALLOW_FACTORY_RESET);
}
synchronized (mLock) {
doSetOemUnlockEnabledLocked(enabled);
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index eaf317a46bc1..7ea8f1f4924d 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -41,6 +41,7 @@ import android.system.StructStat;
import com.android.internal.app.ResolverActivity;
import com.android.internal.os.BackgroundThread;
+import dalvik.system.DexFile;
import dalvik.system.VMRuntime;
import java.util.ArrayList;
@@ -240,12 +241,6 @@ public final class PinnerService extends SystemService {
}
mPinnedCameraFiles.add(pf);
- //find the location of the odex based on the location of the APK
- int lastPeriod = camAPK.lastIndexOf('.');
- int lastSlash = camAPK.lastIndexOf('/', lastPeriod);
- String base = camAPK.substring(0, lastSlash);
- String appName = camAPK.substring(lastSlash + 1, lastPeriod);
-
// determine the ABI from either ApplicationInfo or Build
String arch = "arm";
if (cameraInfo.primaryCpuAbi != null
@@ -256,8 +251,18 @@ public final class PinnerService extends SystemService {
arch = arch + "64";
}
}
- String odex = base + "/oat/" + arch + "/" + appName + ".odex";
- //not all apps have odex files, so not pinning the odex is not a fatal error
+
+ // get the path to the odex or oat file
+ String baseCodePath = cameraInfo.getBaseCodePath();
+ String odex = null;
+ try {
+ odex = DexFile.getDexFileOutputPath(baseCodePath, arch);
+ } catch (IOException ioe) {}
+ if (odex == null) {
+ return true;
+ }
+
+ //not pinning the oat/odex is not a fatal error
pf = pinFile(odex, 0, 0, MAX_CAMERA_PIN_SIZE);
if (pf != null) {
mPinnedCameraFiles.add(pf);
@@ -265,6 +270,7 @@ public final class PinnerService extends SystemService {
Slog.i(TAG, "Pinned " + pf.mFilename);
}
}
+
return true;
}
diff --git a/services/core/java/com/android/server/UiThread.java b/services/core/java/com/android/server/UiThread.java
index c06afc2505ee..1bc6250d699a 100644
--- a/services/core/java/com/android/server/UiThread.java
+++ b/services/core/java/com/android/server/UiThread.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.os.Handler;
+import android.os.Process;
import android.os.Trace;
/**
@@ -29,7 +30,9 @@ public final class UiThread extends ServiceThread {
private static Handler sHandler;
private UiThread() {
- super("android.ui", android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
+ super("android.ui", Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
+ // Make sure UiThread is in the fg stune boost group
+ Process.setThreadGroup(Process.myTid(), Process.THREAD_GROUP_TOP_APP);
}
private static void ensureThreadLocked() {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index f7bd04b08ede..577cada36c3e 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1225,11 +1225,13 @@ public class AccountManagerService
} finally {
db.endTransaction();
}
- sendAccountsChangedBroadcast(accounts.userId);
}
if (getUserManager().getUserInfo(accounts.userId).canHaveProfile()) {
addAccountToLinkedRestrictedUsers(account, accounts.userId);
}
+
+ // Only send LOGIN_ACCOUNTS_CHANGED when the database changed.
+ sendAccountsChangedBroadcast(accounts.userId);
return true;
}
@@ -1412,7 +1414,6 @@ public class AccountManagerService
synchronized (accounts.cacheLock) {
final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
db.beginTransaction();
- boolean isSuccessful = false;
Account renamedAccount = new Account(newName, accountToRename.type);
try {
final long accountId = getAccountIdLocked(db, accountToRename);
@@ -1425,54 +1426,51 @@ public class AccountManagerService
values.put(ACCOUNTS_PREVIOUS_NAME, accountToRename.name);
db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
db.setTransactionSuccessful();
- isSuccessful = true;
logRecord(db, DebugDbHelper.ACTION_ACCOUNT_RENAME, TABLE_ACCOUNTS, accountId,
accounts);
}
} finally {
db.endTransaction();
- if (isSuccessful) {
- /*
- * Database transaction was successful. Clean up cached
- * data associated with the account in the user profile.
- */
- insertAccountIntoCacheLocked(accounts, renamedAccount);
- /*
- * Extract the data and token caches before removing the
- * old account to preserve the user data associated with
- * the account.
- */
- HashMap<String, String> tmpData = accounts.userDataCache.get(accountToRename);
- HashMap<String, String> tmpTokens = accounts.authTokenCache.get(accountToRename);
- removeAccountFromCacheLocked(accounts, accountToRename);
- /*
- * Update the cached data associated with the renamed
- * account.
- */
- accounts.userDataCache.put(renamedAccount, tmpData);
- accounts.authTokenCache.put(renamedAccount, tmpTokens);
- accounts.previousNameCache.put(
- renamedAccount,
- new AtomicReference<String>(accountToRename.name));
- resultAccount = renamedAccount;
-
- int parentUserId = accounts.userId;
- if (canHaveProfile(parentUserId)) {
- /*
- * Owner or system user account was renamed, rename the account for
- * those users with which the account was shared.
- */
- List<UserInfo> users = getUserManager().getUsers(true);
- for (UserInfo user : users) {
- if (user.isRestricted()
- && (user.restrictedProfileParentId == parentUserId)) {
- renameSharedAccountAsUser(accountToRename, newName, user.id);
- }
- }
+ }
+ /*
+ * Database transaction was successful. Clean up cached
+ * data associated with the account in the user profile.
+ */
+ insertAccountIntoCacheLocked(accounts, renamedAccount);
+ /*
+ * Extract the data and token caches before removing the
+ * old account to preserve the user data associated with
+ * the account.
+ */
+ HashMap<String, String> tmpData = accounts.userDataCache.get(accountToRename);
+ HashMap<String, String> tmpTokens = accounts.authTokenCache.get(accountToRename);
+ removeAccountFromCacheLocked(accounts, accountToRename);
+ /*
+ * Update the cached data associated with the renamed
+ * account.
+ */
+ accounts.userDataCache.put(renamedAccount, tmpData);
+ accounts.authTokenCache.put(renamedAccount, tmpTokens);
+ accounts.previousNameCache.put(
+ renamedAccount,
+ new AtomicReference<String>(accountToRename.name));
+ resultAccount = renamedAccount;
+
+ int parentUserId = accounts.userId;
+ if (canHaveProfile(parentUserId)) {
+ /*
+ * Owner or system user account was renamed, rename the account for
+ * those users with which the account was shared.
+ */
+ List<UserInfo> users = getUserManager().getUsers(true);
+ for (UserInfo user : users) {
+ if (user.isRestricted()
+ && (user.restrictedProfileParentId == parentUserId)) {
+ renameSharedAccountAsUser(accountToRename, newName, user.id);
}
- sendAccountsChangedBroadcast(accounts.userId);
}
}
+ sendAccountsChangedBroadcast(accounts.userId);
}
return resultAccount;
}
@@ -1653,7 +1651,7 @@ public class AccountManagerService
}
private boolean removeAccountInternal(UserAccounts accounts, Account account, int callingUid) {
- int deleted;
+ boolean isChanged = false;
boolean userUnlocked = isLocalUnlockedUser(accounts.userId);
if (!userUnlocked) {
Slog.i(TAG, "Removing account " + account + " while user "+ accounts.userId
@@ -1663,25 +1661,38 @@ public class AccountManagerService
final SQLiteDatabase db = userUnlocked
? accounts.openHelper.getWritableDatabaseUserIsUnlocked()
: accounts.openHelper.getWritableDatabase();
- final long accountId = getAccountIdLocked(db, account);
db.beginTransaction();
+ // Set to a dummy value, this will only be used if the database
+ // transaction succeeds.
+ long accountId = -1;
try {
- deleted = db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
- + "=?", new String[]{account.name, account.type});
- if (userUnlocked) {
- // Delete from CE table
- deleted = db.delete(CE_TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
- + "=?", new String[]{account.name, account.type});
+ accountId = getAccountIdLocked(db, account);
+ if (accountId >= 0) {
+ db.delete(
+ TABLE_ACCOUNTS,
+ ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
+ new String[]{ account.name, account.type });
+ if (userUnlocked) {
+ // Delete from CE table
+ db.delete(
+ CE_TABLE_ACCOUNTS,
+ ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?",
+ new String[]{ account.name, account.type });
+ }
+ db.setTransactionSuccessful();
+ isChanged = true;
}
- db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
- removeAccountFromCacheLocked(accounts, account);
- sendAccountsChangedBroadcast(accounts.userId);
- String action = userUnlocked ? DebugDbHelper.ACTION_ACCOUNT_REMOVE
- : DebugDbHelper.ACTION_ACCOUNT_REMOVE_DE;
- logRecord(db, action, TABLE_ACCOUNTS, accountId, accounts);
+ if (isChanged) {
+ removeAccountFromCacheLocked(accounts, account);
+ // Only broadcast LOGIN_ACCOUNTS_CHANGED if a change occured.
+ sendAccountsChangedBroadcast(accounts.userId);
+ String action = userUnlocked ? DebugDbHelper.ACTION_ACCOUNT_REMOVE
+ : DebugDbHelper.ACTION_ACCOUNT_REMOVE_DE;
+ logRecord(db, action, TABLE_ACCOUNTS, accountId, accounts);
+ }
}
long id = Binder.clearCallingIdentity();
try {
@@ -1698,7 +1709,7 @@ public class AccountManagerService
} finally {
Binder.restoreCallingIdentity(id);
}
- return (deleted > 0);
+ return isChanged;
}
@Override
@@ -1922,6 +1933,7 @@ public class AccountManagerService
if (account == null) {
return;
}
+ boolean isChanged = false;
synchronized (accounts.cacheLock) {
final SQLiteDatabase db = accounts.openHelper.getWritableDatabaseUserIsUnlocked();
db.beginTransaction();
@@ -1931,12 +1943,17 @@ public class AccountManagerService
final long accountId = getAccountIdLocked(db, account);
if (accountId >= 0) {
final String[] argsAccountId = {String.valueOf(accountId)};
- db.update(CE_TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
- db.delete(CE_TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
+ db.update(
+ CE_TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
+ db.delete(
+ CE_TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
accounts.authTokenCache.remove(account);
accounts.accountTokenCaches.remove(account);
db.setTransactionSuccessful();
-
+ // If there is an account whose password will be updated and the database
+ // transactions succeed, then we say that a change has occured. Even if the
+ // new password is the same as the old and there were no authtokens to delete.
+ isChanged = true;
String action = (password == null || password.length() == 0) ?
DebugDbHelper.ACTION_CLEAR_PASSWORD
: DebugDbHelper.ACTION_SET_PASSWORD;
@@ -1944,8 +1961,11 @@ public class AccountManagerService
}
} finally {
db.endTransaction();
+ if (isChanged) {
+ // Send LOGIN_ACCOUNTS_CHANGED only if the something changed.
+ sendAccountsChangedBroadcast(accounts.userId);
+ }
}
- sendAccountsChangedBroadcast(accounts.userId);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5bfb90f9bb57..1f0dbfe361f7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12042,6 +12042,9 @@ public final class ActivityManagerService extends ActivityManagerNative
case ActivityManager.BUGREPORT_OPTION_REMOTE:
service = "bugreportremote";
break;
+ case ActivityManager.BUGREPORT_OPTION_WEAR:
+ service = "bugreportwear";
+ break;
}
if (service == null) {
throw new IllegalArgumentException("Provided bugreport type is not correct, value: "
@@ -18669,7 +18672,7 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized(this) {
final long origId = Binder.clearCallingIdentity();
- updateConfigurationLocked(values, null, false, true, userId);
+ updateConfigurationLocked(values, null, false, true, userId, false /* deferResume */);
Binder.restoreCallingIdentity(origId);
}
}
@@ -18737,11 +18740,16 @@ public final class ActivityManagerService extends ActivityManagerNative
updateConfigurationLocked(configuration, null, false);
}
- boolean updateConfigurationLocked(Configuration values,
- ActivityRecord starting, boolean initLocale) {
+ boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean initLocale) {
+ return updateConfigurationLocked(values, starting, initLocale, false /* deferResume */);
+ }
+
+ boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean initLocale, boolean deferResume) {
// pass UserHandle.USER_NULL as userId because we don't persist configuration for any user
- return updateConfigurationLocked(values, starting, initLocale, false,
- UserHandle.USER_NULL);
+ return updateConfigurationLocked(values, starting, initLocale, false /* persistent */,
+ UserHandle.USER_NULL, deferResume);
}
// To cache the list of supported system locales
@@ -18757,8 +18765,8 @@ public final class ActivityManagerService extends ActivityManagerNative
* @param userId is only used when persistent parameter is set to true to persist configuration
* for that particular user
*/
- private boolean updateConfigurationLocked(Configuration values,
- ActivityRecord starting, boolean initLocale, boolean persistent, int userId) {
+ private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean initLocale, boolean persistent, int userId, boolean deferResume) {
int changes = 0;
if (mWindowManager != null) {
@@ -18886,7 +18894,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int stackId : resizedStacks) {
final Rect newBounds = mWindowManager.getBoundsForNewConfiguration(stackId);
mStackSupervisor.resizeStackLocked(
- stackId, newBounds, null, null, false, false, !DEFER_RESUME);
+ stackId, newBounds, null, null, false, false, deferResume);
}
}
}
@@ -21783,16 +21791,16 @@ public final class ActivityManagerService extends ActivityManagerNative
Preconditions.checkNotNull(values, "Configuration must not be null");
Preconditions.checkArgumentNonnegative(userId, "userId " + userId + " not supported");
synchronized (ActivityManagerService.this) {
- updateConfigurationLocked(values, null, false, true, userId);
+ updateConfigurationLocked(values, null, false, true, userId,
+ false /* deferResume */);
}
}
@Override
- public IIntentSender getActivityIntentSenderAsPackage(
- String packageName, int userId, int requestCode, Intent intent,
- int flags, Bundle bOptions) {
- String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
- mContext.getContentResolver()) : null;
+ public int startActivityAsPackage(String packageName, int userId, Intent intent,
+ Bundle bOptions) {
+ Preconditions.checkNotNull(intent, "intent");
+ final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
// UID of the package on user userId.
// "= 0" is needed because otherwise catch(RemoteException) would make it look like
@@ -21806,11 +21814,9 @@ public final class ActivityManagerService extends ActivityManagerNative
}
synchronized (ActivityManagerService.this) {
- return getIntentSenderLocked(
- ActivityManager.INTENT_SENDER_ACTIVITY, packageName, packageUid,
- UserHandle.getUserId(packageUid), /*token*/ null, /*resultWho*/ null,
- requestCode, new Intent[] {intent}, new String[]{resolvedType},
- flags, bOptions);
+ return startActivityInPackage(packageUid, packageName, intent, resolvedType,
+ /*resultTo*/ null, /*resultWho*/ null, /*requestCode*/ 0, /*startFlags*/ 0,
+ bOptions, userId, /*container*/ null, /*inTask*/ null);
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a10266483834..eb02dc34e1a2 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2051,6 +2051,14 @@ final class ActivityStack {
// We don't want to clear starting window for activities that aren't behind fullscreen
// activities as we need to display their starting window until they are done initializing.
boolean behindFullscreenActivity = false;
+
+ if (getStackVisibilityLocked(null) == STACK_INVISIBLE) {
+ // The stack is not visible, so no activity in it should be displaying a starting
+ // window. Mark all activities below top and behind fullscreen.
+ aboveTop = false;
+ behindFullscreenActivity = true;
+ }
+
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 82668e45812f..c16fc62d1177 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1189,7 +1189,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
r.mayFreezeScreenLocked(app) ? r.appToken : null);
- mService.updateConfigurationLocked(config, r, false);
+ // Deferring resume here because we're going to launch new activity shortly.
+ // We don't want to perform a redundant launch of the same record while ensuring
+ // configurations and trying to resume top activity of focused stack.
+ mService.updateConfigurationLocked(config, r, false, true /* deferResume */);
}
r.app = app;
@@ -2004,7 +2007,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
boolean preserveWindows, boolean allowResizeInDockedMode, boolean deferResume) {
if (stackId == DOCKED_STACK_ID) {
resizeDockedStackLocked(bounds, tempTaskBounds, tempTaskInsetBounds, null, null,
- preserveWindows);
+ preserveWindows, deferResume);
return;
}
final ActivityStack stack = getStack(stackId);
@@ -2154,8 +2157,16 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds,
- Rect tempDockedTaskInsetBounds,
- Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds, boolean preserveWindows) {
+ Rect tempDockedTaskInsetBounds, Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds,
+ boolean preserveWindows) {
+ resizeDockedStackLocked(dockedBounds, tempDockedTaskBounds, tempDockedTaskInsetBounds,
+ tempOtherTaskBounds, tempOtherTaskInsetBounds, preserveWindows,
+ false /* deferResume */);
+ }
+
+ void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds,
+ Rect tempDockedTaskInsetBounds, Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds,
+ boolean preserveWindows, boolean deferResume) {
if (!mAllowDockedStackResize) {
// Docked stack resize currently disabled.
@@ -2198,11 +2209,13 @@ public final class ActivityStackSupervisor implements DisplayListener {
if (StackId.isResizeableByDockedStack(i) && getStack(i) != null) {
resizeStackLocked(i, tempRect, tempOtherTaskBounds,
tempOtherTaskInsetBounds, preserveWindows,
- true /* allowResizeInDockedMode */, !DEFER_RESUME);
+ true /* allowResizeInDockedMode */, deferResume);
}
}
}
- stack.ensureVisibleActivitiesConfigurationLocked(r, preserveWindows);
+ if (!deferResume) {
+ stack.ensureVisibleActivitiesConfigurationLocked(r, preserveWindows);
+ }
} finally {
mAllowDockedStackResize = true;
mWindowManager.continueSurfaceLayout();
@@ -3061,7 +3074,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
final boolean nowVisible = allResumedActivitiesVisible();
for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord s = mStoppingActivities.get(activityNdx);
- final boolean waitingVisible = mWaitingVisibleActivities.contains(s);
+ boolean waitingVisible = mWaitingVisibleActivities.contains(s);
if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
+ " waitingVisible=" + waitingVisible + " finishing=" + s.finishing);
if (waitingVisible && nowVisible) {
@@ -3074,6 +3087,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
// hidden by the activities in front of it.
if (DEBUG_STATES) Slog.v(TAG, "Before stopping, can hide: " + s);
mWindowManager.setAppVisibility(s.appToken, false);
+ waitingVisible = false;
}
}
if ((!waitingVisible || mService.isSleepingOrShuttingDownLocked()) && remove) {
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 49106f42044e..5807502ef791 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -58,6 +58,7 @@ import java.io.PrintWriter;
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;
@@ -386,8 +387,8 @@ class AppErrors {
} catch (IllegalArgumentException e) {
// Hmm, that didn't work, app might have crashed before creating a
// recents entry. Let's see if we have a safe-to-restart intent.
- if (task.intent.getCategories().contains(
- Intent.CATEGORY_LAUNCHER)) {
+ final Set<String> cats = task.intent.getCategories();
+ if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
mService.startActivityInPackage(task.mCallingUid,
task.mCallingPackage, task.intent,
null, null, null, 0, 0,
@@ -742,6 +743,12 @@ class AppErrors {
mService.updateCpuStatsNow();
}
+ // Unless configured otherwise, swallow ANRs in background processes & kill the process.
+ boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
+
+ boolean isSilentANR;
+
synchronized (mService) {
// PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
if (mService.mShuttingDown) {
@@ -766,25 +773,29 @@ class AppErrors {
// Dump thread traces as quickly as we can, starting with "interesting" processes.
firstPids.add(app.pid);
- int parentPid = app.pid;
- if (parent != null && parent.app != null && parent.app.pid > 0) {
- parentPid = parent.app.pid;
- }
- if (parentPid != app.pid) firstPids.add(parentPid);
-
- if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
-
- for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
- ProcessRecord r = mService.mLruProcesses.get(i);
- if (r != null && r.thread != null) {
- int pid = r.pid;
- if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
- if (r.persistent) {
- firstPids.add(pid);
- if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
- } else {
- lastPids.put(pid, Boolean.TRUE);
- if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
+ // Don't dump other PIDs if it's a background ANR
+ isSilentANR = !showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID;
+ if (!isSilentANR) {
+ int parentPid = app.pid;
+ if (parent != null && parent.app != null && parent.app.pid > 0) {
+ parentPid = parent.app.pid;
+ }
+ if (parentPid != app.pid) firstPids.add(parentPid);
+
+ if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
+
+ for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord r = mService.mLruProcesses.get(i);
+ if (r != null && r.thread != null) {
+ int pid = r.pid;
+ if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
+ if (r.persistent) {
+ firstPids.add(pid);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
+ } else {
+ lastPids.put(pid, Boolean.TRUE);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
+ }
}
}
}
@@ -807,10 +818,18 @@ class AppErrors {
info.append("Parent: ").append(parent.shortComponentName).append("\n");
}
- final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
+ ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
- File tracesFile = mService.dumpStackTraces(true, firstPids, processCpuTracker, lastPids,
- NATIVE_STACKS_OF_INTEREST);
+ String[] nativeProcs = NATIVE_STACKS_OF_INTEREST;
+ // don't dump native PIDs for background ANRs
+ File tracesFile = null;
+ if (isSilentANR) {
+ tracesFile = mService.dumpStackTraces(true, firstPids, null, lastPids,
+ null);
+ } else {
+ tracesFile = mService.dumpStackTraces(true, firstPids, processCpuTracker, lastPids,
+ nativeProcs);
+ }
String cpuInfo = null;
if (ActivityManagerService.MONITOR_CPU_USAGE) {
@@ -854,14 +873,10 @@ class AppErrors {
}
}
- // Unless configured otherwise, swallow ANRs in background processes & kill the process.
- boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
-
synchronized (mService) {
mService.mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
- if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
+ if (isSilentANR) {
app.kill("bg anr", true);
return;
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index bef48d6734fa..12310e390061 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -69,6 +69,7 @@ import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.server.IoThread;
import com.android.server.connectivity.tethering.IControlsTethering;
+import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
import com.android.server.net.BaseNetworkObserver;
@@ -270,14 +271,16 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
trackNewTetherableInterface(iface, interfaceType);
}
} else {
- if (interfaceType == ConnectivityManager.TETHERING_USB) {
- // ignore usb0 down after enabling RNDIS
- // we will handle disconnect in interfaceRemoved instead
- if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
- } else if (tetherState != null) {
+ if (interfaceType == ConnectivityManager.TETHERING_BLUETOOTH) {
tetherState.mStateMachine.sendMessage(
TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
mTetherStates.remove(iface);
+ } else {
+ // Ignore usb0 down after enabling RNDIS.
+ // We will handle disconnect in interfaceRemoved.
+ // Similarly, ignore interface down for WiFi. We monitor WiFi AP status
+ // through the WifiManager.WIFI_AP_STATE_CHANGED_ACTION intent.
+ if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
}
}
}
@@ -588,13 +591,13 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
synchronized (mPublicSync) {
TetherState tetherState = mTetherStates.get(iface);
if (tetherState == null) {
- Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
+ Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring");
return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
}
// Ignore the error status of the interface. If the interface is available,
// the errors are referring to past tethering attempts anyway.
if (tetherState.mLastState != IControlsTethering.STATE_AVAILABLE) {
- Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
+ Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
}
tetherState.mStateMachine.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED);
@@ -1015,15 +1018,29 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
*/
class UpstreamNetworkCallback extends NetworkCallback {
@Override
+ public void onAvailable(Network network) {
+ mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
+ UpstreamNetworkMonitor.EVENT_ON_AVAILABLE, 0, network);
+ }
+
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
+ mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
+ UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES, 0,
+ new NetworkState(null, null, newNc, network, null, null));
+ }
+
+ @Override
public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
- mTetherMasterSM.sendMessage(
- TetherMasterSM.EVENT_UPSTREAM_LINKPROPERTIES_CHANGED,
+ mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
+ UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES, 0,
new NetworkState(null, newLp, null, network, null, null));
}
@Override
public void onLost(Network network) {
- mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_LOST, network);
+ mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
+ UpstreamNetworkMonitor.EVENT_ON_LOST, 0, network);
}
}
@@ -1042,6 +1059,11 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
* could/should be moved here.
*/
class UpstreamNetworkMonitor {
+ static final int EVENT_ON_AVAILABLE = 1;
+ static final int EVENT_ON_CAPABILITIES = 2;
+ static final int EVENT_ON_LINKPROPERTIES = 3;
+ static final int EVENT_ON_LOST = 4;
+
final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
NetworkCallback mDefaultNetworkCallback;
NetworkCallback mDunTetheringCallback;
@@ -1076,33 +1098,107 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
mNetworkMap.clear();
}
- // Returns true if these updated LinkProperties pertain to the current
- // upstream network interface, false otherwise (or if there is not
- // currently any upstream tethering interface).
- boolean processLinkPropertiesChanged(NetworkState networkState) {
- if (networkState == null ||
- networkState.network == null ||
- networkState.linkProperties == null) {
- return false;
- }
+ NetworkState lookup(Network network) {
+ return (network != null) ? mNetworkMap.get(network) : null;
+ }
+
+ NetworkState processCallback(int arg1, Object obj) {
+ switch (arg1) {
+ case EVENT_ON_AVAILABLE: {
+ final Network network = (Network) obj;
+ if (VDBG) {
+ Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
+ }
+ if (!mNetworkMap.containsKey(network)) {
+ mNetworkMap.put(network,
+ new NetworkState(null, null, null, network, null, null));
+ }
+
+ final ConnectivityManager cm = getConnectivityManager();
+
+ if (mDefaultNetworkCallback != null) {
+ cm.requestNetworkCapabilities(mDefaultNetworkCallback);
+ cm.requestLinkProperties(mDefaultNetworkCallback);
+ }
+
+ // Requesting updates for mDunTetheringCallback is not
+ // necessary. Because it's a listen, it will already have
+ // heard all NetworkCapabilities and LinkProperties updates
+ // since UpstreamNetworkMonitor was started. Because we
+ // start UpstreamNetworkMonitor before chooseUpstreamType()
+ // is ever invoked (it can register a DUN request) this is
+ // mostly safe. However, if a DUN network is already up for
+ // some reason (unlikely, because DUN is restricted and,
+ // unless the DUN network is shared with another APN, only
+ // the system can request it and this is the only part of
+ // the system that requests it) we won't know its
+ // LinkProperties or NetworkCapabilities.
+
+ return mNetworkMap.get(network);
+ }
+ case EVENT_ON_CAPABILITIES: {
+ final NetworkState ns = (NetworkState) obj;
+ if (!mNetworkMap.containsKey(ns.network)) {
+ // Ignore updates for networks for which we have not yet
+ // received onAvailable() - which should never happen -
+ // or for which we have already received onLost().
+ return null;
+ }
+ if (VDBG) {
+ Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s",
+ ns.network, ns.networkCapabilities));
+ }
- mNetworkMap.put(networkState.network, networkState);
+ final NetworkState prev = mNetworkMap.get(ns.network);
+ mNetworkMap.put(ns.network,
+ new NetworkState(null, prev.linkProperties, ns.networkCapabilities,
+ ns.network, null, null));
+ return mNetworkMap.get(ns.network);
+ }
+ case EVENT_ON_LINKPROPERTIES: {
+ final NetworkState ns = (NetworkState) obj;
+ if (!mNetworkMap.containsKey(ns.network)) {
+ // Ignore updates for networks for which we have not yet
+ // received onAvailable() - which should never happen -
+ // or for which we have already received onLost().
+ return null;
+ }
+ if (VDBG) {
+ Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s",
+ ns.network, ns.linkProperties));
+ }
- if (mCurrentUpstreamIface != null) {
- for (String ifname : networkState.linkProperties.getAllInterfaceNames()) {
- if (mCurrentUpstreamIface.equals(ifname)) {
- return true;
+ final NetworkState prev = mNetworkMap.get(ns.network);
+ mNetworkMap.put(ns.network,
+ new NetworkState(null, ns.linkProperties, prev.networkCapabilities,
+ ns.network, null, null));
+ return mNetworkMap.get(ns.network);
+ }
+ case EVENT_ON_LOST: {
+ final Network network = (Network) obj;
+ if (VDBG) {
+ Log.d(TAG, "EVENT_ON_LOST for " + network);
}
+ return mNetworkMap.remove(network);
}
+ default:
+ return null;
}
- return false;
}
+ }
- void processNetworkLost(Network network) {
- if (network != null) {
- mNetworkMap.remove(network);
+ // Needed because the canonical source of upstream truth is just the
+ // upstream interface name, |mCurrentUpstreamIface|. This is ripe for
+ // future simplification, once the upstream Network is canonical.
+ boolean pertainsToCurrentUpstream(NetworkState ns) {
+ if (ns != null && ns.linkProperties != null && mCurrentUpstreamIface != null) {
+ for (String ifname : ns.linkProperties.getAllInterfaceNames()) {
+ if (mCurrentUpstreamIface.equals(ifname)) {
+ return true;
+ }
}
}
+ return false;
}
class TetherMasterSM extends StateMachine {
@@ -1117,8 +1213,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4;
// Events from NetworkCallbacks that we process on the master state
// machine thread on behalf of the UpstreamNetworkMonitor.
- static final int EVENT_UPSTREAM_LINKPROPERTIES_CHANGED = BASE_MASTER + 5;
- static final int EVENT_UPSTREAM_LOST = BASE_MASTER + 6;
+ static final int EVENT_UPSTREAM_CALLBACK = BASE_MASTER + 5;
private State mInitialState;
private State mTetherModeAliveState;
@@ -1141,7 +1236,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
// Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList
// so that the garbage collector does not clean up the state machine before it has a chance
// to tear itself down.
- private ArrayList<TetherInterfaceStateMachine> mNotifyList;
+ private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
+ private final IPv6TetheringCoordinator mIPv6TetheringCoordinator;
private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
private NetworkCallback mMobileUpstreamCallback;
@@ -1169,6 +1265,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
addState(mSetDnsForwardersErrorState);
mNotifyList = new ArrayList<>();
+ mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList);
setInitialState(mInitialState);
}
@@ -1273,6 +1370,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
}
protected void chooseUpstreamType(boolean tryCell) {
+ final ConnectivityManager cm = getConnectivityManager();
int upType = ConnectivityManager.TYPE_NONE;
String iface = null;
@@ -1287,8 +1385,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
}
for (Integer netType : mUpstreamIfaceTypes) {
- NetworkInfo info =
- getConnectivityManager().getNetworkInfo(netType.intValue());
+ NetworkInfo info = cm.getNetworkInfo(netType.intValue());
if ((info != null) && info.isConnected()) {
upType = netType.intValue();
break;
@@ -1329,9 +1426,9 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
break;
}
+ Network network = null;
if (upType != ConnectivityManager.TYPE_NONE) {
- LinkProperties linkProperties =
- getConnectivityManager().getLinkProperties(upType);
+ LinkProperties linkProperties = cm.getLinkProperties(upType);
if (linkProperties != null) {
// Find the interface with the default IPv4 route. It may be the
// interface described by linkProperties, or one of the interfaces
@@ -1348,7 +1445,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
}
if (iface != null) {
- Network network = getConnectivityManager().getNetworkForType(upType);
+ network = cm.getNetworkForType(upType);
if (network == null) {
Log.e(TAG, "No Network for upstream type " + upType + "!");
}
@@ -1356,6 +1453,13 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
}
}
notifyTetheredOfNewUpstreamIface(iface);
+ NetworkState ns = mUpstreamNetworkMonitor.lookup(network);
+ if (ns != null && pertainsToCurrentUpstream(ns)) {
+ // If we already have NetworkState for this network examine
+ // it immediately, because there likely will be no second
+ // EVENT_ON_AVAILABLE (it was already received).
+ handleNewUpstreamNetworkState(ns);
+ }
}
protected void setDnsForwarders(final Network network, final LinkProperties lp) {
@@ -1388,6 +1492,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
ifaceName);
}
}
+
+ protected void handleNewUpstreamNetworkState(NetworkState ns) {
+ mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns);
+ }
}
private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0);
@@ -1577,24 +1685,55 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
chooseUpstreamType(mTryCell);
mTryCell = !mTryCell;
break;
- case EVENT_UPSTREAM_LINKPROPERTIES_CHANGED:
- NetworkState state = (NetworkState) message.obj;
- if (mUpstreamNetworkMonitor.processLinkPropertiesChanged(state)) {
- setDnsForwarders(state.network, state.linkProperties);
- } else if (mCurrentUpstreamIface == null) {
- // If we have no upstream interface, try to run through upstream
- // selection again. If, for example, IPv4 connectivity has shown up
- // after IPv6 (e.g., 464xlat became available) we want the chance to
- // notice and act accordingly.
- chooseUpstreamType(false);
+ case EVENT_UPSTREAM_CALLBACK: {
+ // First: always update local state about every network.
+ final NetworkState ns = mUpstreamNetworkMonitor.processCallback(
+ message.arg1, message.obj);
+
+ if (ns == null || !pertainsToCurrentUpstream(ns)) {
+ // TODO: In future, this is where upstream evaluation and selection
+ // could be handled for notifications which include sufficient data.
+ // For example, after CONNECTIVITY_ACTION listening is removed, here
+ // is where we could observe a Wi-Fi network becoming available and
+ // passing validation.
+ if (mCurrentUpstreamIface == null) {
+ // If we have no upstream interface, try to run through upstream
+ // selection again. If, for example, IPv4 connectivity has shown up
+ // after IPv6 (e.g., 464xlat became available) we want the chance to
+ // notice and act accordingly.
+ chooseUpstreamType(false);
+ }
+ break;
+ }
+
+ switch (message.arg1) {
+ case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE:
+ // The default network changed, or DUN connected
+ // before this callback was processed. Updates
+ // for the current NetworkCapabilities and
+ // LinkProperties have been requested (default
+ // request) or are being sent shortly (DUN). Do
+ // nothing until they arrive; if no updates
+ // arrive there's nothing to do.
+ break;
+ case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES:
+ handleNewUpstreamNetworkState(ns);
+ break;
+ case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES:
+ setDnsForwarders(ns.network, ns.linkProperties);
+ handleNewUpstreamNetworkState(ns);
+ break;
+ case UpstreamNetworkMonitor.EVENT_ON_LOST:
+ // TODO: Re-evaluate possible upstreams. Currently upstream
+ // reevaluation is triggered via received CONNECTIVITY_ACTION
+ // broadcasts that result in being passed a
+ // TetherMasterSM.CMD_UPSTREAM_CHANGED.
+ break;
+ default:
+ break;
}
break;
- case EVENT_UPSTREAM_LOST:
- // TODO: Re-evaluate possible upstreams. Currently upstream reevaluation
- // is triggered via received CONNECTIVITY_ACTION broadcasts that result
- // in being passed a TetherMasterSM.CMD_UPSTREAM_CHANGED.
- mUpstreamNetworkMonitor.processNetworkLost((Network) message.obj);
- break;
+ }
default:
retValue = false;
break;
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
new file mode 100644
index 000000000000..825439786360
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.tethering;
+
+import android.net.ConnectivityManager;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkState;
+import android.net.RouteInfo;
+import android.util.Log;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+
+
+/**
+ * IPv6 tethering is rather different from IPv4 owing to the absence of NAT.
+ * This coordinator is responsible for evaluating the dedicated prefixes
+ * assigned to the device and deciding how to divvy them up among downstream
+ * interfaces.
+ *
+ * @hide
+ */
+public class IPv6TetheringCoordinator {
+ private static final String TAG = IPv6TetheringCoordinator.class.getSimpleName();
+ private static final boolean DBG = false;
+ private static final boolean VDBG = false;
+
+ private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
+ private NetworkState mUpstreamNetworkState;
+
+ public IPv6TetheringCoordinator(ArrayList<TetherInterfaceStateMachine> notifyList) {
+ mNotifyList = notifyList;
+ }
+
+ public void updateUpstreamNetworkState(NetworkState ns) {
+ if (VDBG) {
+ Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns));
+ }
+ if (ns == null || ns.network == null) {
+ stopIPv6TetheringOnAllInterfaces();
+ setUpstreamNetworkState(null);
+ return;
+ }
+
+ if (mUpstreamNetworkState != null &&
+ !ns.network.equals(mUpstreamNetworkState.network)) {
+ stopIPv6TetheringOnAllInterfaces();
+ }
+ setUpstreamNetworkState(ns);
+ maybeUpdateIPv6TetheringInterfaces();
+ }
+
+ private void stopIPv6TetheringOnAllInterfaces() {
+ for (TetherInterfaceStateMachine sm : mNotifyList) {
+ sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE,
+ 0, 0, null);
+ }
+ }
+
+ private void setUpstreamNetworkState(NetworkState ns) {
+ if (!canTetherIPv6(ns)) {
+ mUpstreamNetworkState = null;
+ } else {
+ mUpstreamNetworkState = new NetworkState(
+ null,
+ new LinkProperties(ns.linkProperties),
+ new NetworkCapabilities(ns.networkCapabilities),
+ new Network(ns.network),
+ null,
+ null);
+ }
+
+ if (DBG) {
+ Log.d(TAG, "setUpstreamNetworkState: " + toDebugString(mUpstreamNetworkState));
+ }
+ }
+
+ private void maybeUpdateIPv6TetheringInterfaces() {
+ if (mUpstreamNetworkState == null) return;
+
+ for (TetherInterfaceStateMachine sm : mNotifyList) {
+ final LinkProperties lp = getInterfaceIPv6LinkProperties(sm.interfaceType());
+ if (lp != null) {
+ sm.sendMessage(TetherInterfaceStateMachine.CMD_IPV6_TETHER_UPDATE, 0, 0, lp);
+ }
+ break;
+ }
+ }
+
+ private LinkProperties getInterfaceIPv6LinkProperties(int interfaceType) {
+ // NOTE: Here, in future, we would have policies to decide how to divvy
+ // up the available dedicated prefixes among downstream interfaces.
+ // At this time we have no such mechanism--we only support tethering
+ // IPv6 toward Wi-Fi interfaces.
+
+ switch (interfaceType) {
+ case ConnectivityManager.TETHERING_WIFI:
+ final LinkProperties lp = getIPv6OnlyLinkProperties(
+ mUpstreamNetworkState.linkProperties);
+ if (lp.hasIPv6DefaultRoute() && lp.hasGlobalIPv6Address()) {
+ return lp;
+ }
+ break;
+ }
+
+ return null;
+ }
+
+ private static boolean canTetherIPv6(NetworkState ns) {
+ // Broadly speaking:
+ //
+ // [1] does the upstream have an IPv6 default route?
+ //
+ // and
+ //
+ // [2] does the upstream have one or more global IPv6 /64s
+ // dedicated to this device?
+ //
+ // In lieu of Prefix Delegation and other evaluation of whether a
+ // prefix may or may not be dedicated to this device, for now just
+ // check whether the upstream is TRANSPORT_CELLULAR. This works
+ // because "[t]he 3GPP network allocates each default bearer a unique
+ // /64 prefix", per RFC 6459, Section 5.2.
+
+ final boolean canTether =
+ (ns != null) && (ns.network != null) &&
+ (ns.linkProperties != null) && (ns.networkCapabilities != null) &&
+ // At least one upstream DNS server:
+ ns.linkProperties.isProvisioned() &&
+ // Minimal amount of IPv6 provisioning:
+ ns.linkProperties.hasIPv6DefaultRoute() &&
+ ns.linkProperties.hasGlobalIPv6Address() &&
+ // Temporary approximation of "dedicated prefix":
+ ns.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
+
+ // For now, we do not support separate IPv4 and IPv6 upstreams (e.g.
+ // tethering with 464xlat involved). TODO: Rectify this shortcoming,
+ // likely by calling NetworkManagementService#startInterfaceForwarding()
+ // for all upstream interfaces.
+ RouteInfo v4default = null;
+ RouteInfo v6default = null;
+ if (canTether) {
+ for (RouteInfo r : ns.linkProperties.getAllRoutes()) {
+ if (r.isIPv4Default()) {
+ v4default = r;
+ } else if (r.isIPv6Default()) {
+ v6default = r;
+ }
+
+ if (v4default != null && v6default != null) {
+ break;
+ }
+ }
+ }
+
+ final boolean supportedConfiguration =
+ (v4default != null) && (v6default != null) &&
+ (v4default.getInterface() != null) &&
+ v4default.getInterface().equals(v6default.getInterface());
+
+ final boolean outcome = canTether && supportedConfiguration;
+
+ if (VDBG) {
+ if (ns == null) {
+ Log.d(TAG, "No available upstream.");
+ } else {
+ Log.d(TAG, String.format("IPv6 tethering is %s for upstream: %s",
+ (outcome ? "available" : "not available"), toDebugString(ns)));
+ }
+ }
+
+ return outcome;
+ }
+
+ private static LinkProperties getIPv6OnlyLinkProperties(LinkProperties lp) {
+ final LinkProperties v6only = new LinkProperties();
+ if (lp == null) {
+ return v6only;
+ }
+
+ // NOTE: At this time we don't copy over any information about any
+ // stacked links. No current stacked link configuration has IPv6.
+
+ v6only.setInterfaceName(lp.getInterfaceName());
+
+ v6only.setMtu(lp.getMtu());
+
+ for (LinkAddress linkAddr : lp.getLinkAddresses()) {
+ if (linkAddr.isGlobalPreferred() && linkAddr.getPrefixLength() == 64) {
+ v6only.addLinkAddress(linkAddr);
+ }
+ }
+
+ for (RouteInfo routeInfo : lp.getRoutes()) {
+ final IpPrefix destination = routeInfo.getDestination();
+ if ((destination.getAddress() instanceof Inet6Address) &&
+ (destination.getPrefixLength() <= 64)) {
+ v6only.addRoute(routeInfo);
+ }
+ }
+
+ for (InetAddress dnsServer : lp.getDnsServers()) {
+ if (isIPv6GlobalAddress(dnsServer)) {
+ // For now we include ULAs.
+ v6only.addDnsServer(dnsServer);
+ }
+ }
+
+ v6only.setDomains(lp.getDomains());
+
+ return v6only;
+ }
+
+ // TODO: Delete this and switch to LinkAddress#isGlobalPreferred once we
+ // announce our own IPv6 address as DNS server.
+ private static boolean isIPv6GlobalAddress(InetAddress ip) {
+ return (ip instanceof Inet6Address) &&
+ !ip.isAnyLocalAddress() &&
+ !ip.isLoopbackAddress() &&
+ !ip.isLinkLocalAddress() &&
+ !ip.isSiteLocalAddress() &&
+ !ip.isMulticastAddress();
+ }
+
+ private static String toDebugString(NetworkState ns) {
+ if (ns == null) {
+ return "NetworkState{null}";
+ }
+ return String.format("NetworkState{%s, %s, %s}",
+ ns.network,
+ ns.networkCapabilities,
+ ns.linkProperties);
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
new file mode 100644
index 000000000000..b74283853726
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.tethering;
+
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
+import android.net.NetworkState;
+import android.net.RouteInfo;
+import android.net.ip.RouterAdvertisementDaemon;
+import android.net.ip.RouterAdvertisementDaemon.RaParams;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.HashSet;
+
+
+/**
+ * @hide
+ */
+class IPv6TetheringInterfaceServices {
+ private static final String TAG = IPv6TetheringInterfaceServices.class.getSimpleName();
+
+ private final String mIfName;
+ private final INetworkManagementService mNMService;
+
+ private NetworkInterface mNetworkInterface;
+ private byte[] mHwAddr;
+ private ArrayList<RouteInfo> mLastLocalRoutes;
+ private RouterAdvertisementDaemon mRaDaemon;
+ private RaParams mLastRaParams;
+
+ IPv6TetheringInterfaceServices(String ifname, INetworkManagementService nms) {
+ mIfName = ifname;
+ mNMService = nms;
+ }
+
+ public boolean start() {
+ try {
+ mNetworkInterface = NetworkInterface.getByName(mIfName);
+ } catch (SocketException e) {
+ Log.e(TAG, "Failed to find NetworkInterface for " + mIfName, e);
+ stop();
+ return false;
+ }
+
+ try {
+ mHwAddr = mNetworkInterface.getHardwareAddress();
+ } catch (SocketException e) {
+ Log.e(TAG, "Failed to find hardware address for " + mIfName, e);
+ stop();
+ return false;
+ }
+
+ final int ifindex = mNetworkInterface.getIndex();
+ mRaDaemon = new RouterAdvertisementDaemon(mIfName, ifindex, mHwAddr);
+ if (!mRaDaemon.start()) {
+ stop();
+ return false;
+ }
+
+ return true;
+ }
+
+ public void stop() {
+ mNetworkInterface = null;
+ mHwAddr = null;
+ updateLocalRoutes(null);
+ updateRaParams(null);
+
+ if (mRaDaemon != null) {
+ mRaDaemon.stop();
+ mRaDaemon = null;
+ }
+ }
+
+ // IPv6TetheringCoordinator sends updates with carefully curated IPv6-only
+ // LinkProperties. These have extraneous data filtered out and only the
+ // necessary prefixes included (per its prefix distribution policy).
+ //
+ // TODO: Evaluate using a data structure than is more directly suited to
+ // communicating only the relevant information.
+ public void updateUpstreamIPv6LinkProperties(LinkProperties v6only) {
+ if (mRaDaemon == null) return;
+
+ if (v6only == null) {
+ updateLocalRoutes(null);
+ updateRaParams(null);
+ return;
+ }
+
+ RaParams params = new RaParams();
+ params.mtu = v6only.getMtu();
+ params.hasDefaultRoute = v6only.hasIPv6DefaultRoute();
+
+ ArrayList<RouteInfo> localRoutes = new ArrayList<RouteInfo>();
+ for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
+ final IpPrefix prefix = new IpPrefix(linkAddr.getAddress(),
+ linkAddr.getPrefixLength());
+
+ // Accumulate routes representing "prefixes to be assigned to the
+ // local interface", for subsequent addition to the local network
+ // in the routing rules.
+ localRoutes.add(new RouteInfo(prefix, null, mIfName));
+
+ params.prefixes.add(prefix);
+ }
+
+ // We need to be able to send unicast RAs, and clients might like to
+ // ping the default router's link-local address, so add that as well.
+ localRoutes.add(new RouteInfo(new IpPrefix("fe80::/64"), null, mIfName));
+
+ // TODO: Add a local interface address, update dnsmasq to listen on the
+ // new address, and use only that address as a DNS server.
+ for (InetAddress dnsServer : v6only.getDnsServers()) {
+ if (dnsServer instanceof Inet6Address) {
+ params.dnses.add((Inet6Address) dnsServer);
+ }
+ }
+
+ updateLocalRoutes(localRoutes);
+ updateRaParams(params);
+ }
+
+ private void updateLocalRoutes(ArrayList<RouteInfo> localRoutes) {
+ if (localRoutes != null) {
+ // TODO: Compare with mLastLocalRoutes and take appropriate
+ // appropriate action on the difference between the two.
+
+ if (!localRoutes.isEmpty()) {
+ try {
+ mNMService.addInterfaceToLocalNetwork(mIfName, localRoutes);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to add IPv6 routes to local table: ", e);
+ }
+ }
+ } else {
+ if (mLastLocalRoutes != null && !mLastLocalRoutes.isEmpty()) {
+ // TODO: Remove only locally added network routes.
+ // mNMSwervice.removeInterfaceFromLocalNetwork(mIfName);
+ }
+ }
+
+ mLastLocalRoutes = localRoutes;
+ }
+
+ private void updateRaParams(RaParams params) {
+ if (mRaDaemon != null) {
+ // Currently, we send spurious RAs (5) whenever there's any update.
+ // TODO: Compare params with mLastParams to avoid spurious updates.
+ mRaDaemon.buildNewRa(params);
+ }
+
+ mLastRaParams = params;
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index aebeb690d770..9e7cb939cdf0 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -20,6 +20,7 @@ import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
+import android.net.LinkProperties;
import android.net.NetworkUtils;
import android.os.INetworkManagementService;
import android.os.Looper;
@@ -73,6 +74,8 @@ public class TetherInterfaceStateMachine extends StateMachine {
public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IFACE + 11;
// the upstream connection has changed
public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IFACE + 12;
+ // new IPv6 tethering parameters need to be processed
+ public static final int CMD_IPV6_TETHER_UPDATE = BASE_IFACE + 13;
private final State mInitialState;
private final State mTetheredState;
@@ -84,6 +87,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
private final String mIfaceName;
private final int mInterfaceType;
+ private final IPv6TetheringInterfaceServices mIPv6TetherSvc;
private int mLastError;
private String mMyUpstreamIfaceName; // may change over time
@@ -97,6 +101,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
mTetherController = tetherController;
mIfaceName = ifaceName;
mInterfaceType = interfaceType;
+ mIPv6TetherSvc = new IPv6TetheringInterfaceServices(mIfaceName, mNMService);
mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
mInitialState = new InitialState();
@@ -109,6 +114,10 @@ public class TetherInterfaceStateMachine extends StateMachine {
setInitialState(mInitialState);
}
+ public int interfaceType() {
+ return mInterfaceType;
+ }
+
// configured when we start tethering and unconfig'd on error or conclusion
private boolean configureIfaceIp(boolean enabled) {
if (VDBG) Log.d(TAG, "configureIfaceIp(" + enabled + ")");
@@ -175,6 +184,10 @@ public class TetherInterfaceStateMachine extends StateMachine {
case CMD_INTERFACE_DOWN:
transitionTo(mUnavailableState);
break;
+ case CMD_IPV6_TETHER_UPDATE:
+ mIPv6TetherSvc.updateUpstreamIPv6LinkProperties(
+ (LinkProperties) message.obj);
+ break;
default:
retValue = false;
break;
@@ -200,6 +213,11 @@ public class TetherInterfaceStateMachine extends StateMachine {
transitionTo(mInitialState);
return;
}
+
+ if (!mIPv6TetherSvc.start()) {
+ Log.e(TAG, "Failed to start IPv6TetheringInterfaceServices");
+ }
+
if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
mTetherController.notifyInterfaceStateChange(
mIfaceName, TetherInterfaceStateMachine.this,
@@ -211,6 +229,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
// Note that at this point, we're leaving the tethered state. We can fail any
// of these operations, but it doesn't really change that we have to try them
// all in sequence.
+ mIPv6TetherSvc.stop();
cleanupUpstream();
try {
@@ -287,6 +306,10 @@ public class TetherInterfaceStateMachine extends StateMachine {
}
mMyUpstreamIfaceName = newUpstreamIfaceName;
break;
+ case CMD_IPV6_TETHER_UPDATE:
+ mIPv6TetherSvc.updateUpstreamIPv6LinkProperties(
+ (LinkProperties) message.obj);
+ break;
case CMD_IP_FORWARDING_ENABLE_ERROR:
case CMD_IP_FORWARDING_DISABLE_ERROR:
case CMD_START_TETHERING_ERROR:
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6a6570b97205..fec7ed1ff998 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -244,6 +244,7 @@ public final class DisplayManagerService extends SystemService {
publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
true /*allowIsolated*/);
publishLocalService(DisplayManagerInternal.class, new LocalService());
+ publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
}
@Override
diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/DisplayTransformManager.java
new file mode 100644
index 000000000000..cfeae7bd6bd7
--- /dev/null
+++ b/services/core/java/com/android/server/display/DisplayTransformManager.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import android.opengl.Matrix;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.util.SparseArray;
+
+/**
+ * Manager for applying color transformations to the display.
+ */
+public class DisplayTransformManager {
+
+ private static final String TAG = "DisplayTransformManager";
+
+ /**
+ * Color transform level used by Night display to tint the display red.
+ */
+ public static final int LEVEL_COLOR_MATRIX_NIGHT_DISPLAY = 100;
+ /**
+ * Color transform level used by A11y services to make the display monochromatic.
+ */
+ public static final int LEVEL_COLOR_MATRIX_GRAYSCALE = 200;
+ /**
+ * Color transform level used by A11y services to invert the display colors.
+ */
+ public static final int LEVEL_COLOR_MATRIX_INVERT_COLOR = 300;
+
+ private final SparseArray<float[]> mColorMatrix = new SparseArray<>(3);
+
+ private int mDaltonizerMode = -1;
+
+ /* package */ DisplayTransformManager() {
+ }
+
+ /**
+ * Returns the color transform matrix set for a given level.
+ */
+ public float[] getColorMatrix(int key) {
+ synchronized (mColorMatrix) {
+ return mColorMatrix.get(key);
+ }
+ }
+
+ /**
+ * Sets and applies a current color transform matrix for a given level.
+ * <p>
+ * Note: all color transforms are first composed to a single matrix in ascending order based
+ * on level before being applied to the display.
+ *
+ * @param key the level used to identify and compose the color transform (low -> high)
+ * @param value the 4x4 color transform matrix (in column-major order), or {@code null} to
+ * remove the color transform matrix associated with the provided level
+ */
+ public void setColorMatrix(int key, float[] value) {
+ if (value != null && value.length != 16) {
+ throw new IllegalArgumentException("Expected length: 16 (4x4 matrix)"
+ + ", actual length: " + value.length);
+ }
+
+ synchronized (mColorMatrix) {
+ if (value != null) {
+ mColorMatrix.put(key, value);
+ } else {
+ mColorMatrix.remove(key);
+ }
+
+ // Update the current color transform.
+ applyColorMatrix(computeColorMatrix());
+ }
+ }
+
+ /**
+ * Returns the composition of all current color matrices, or {@code null} if there are none.
+ */
+ private float[] computeColorMatrix() {
+ synchronized (mColorMatrix) {
+ final int count = mColorMatrix.size();
+ if (count == 0) {
+ return null;
+ }
+
+ final float[][] result = new float[2][16];
+ Matrix.setIdentityM(result[0], 0);
+ for (int i = 0; i < count; i++) {
+ float[] rhs = mColorMatrix.valueAt(i);
+ Matrix.multiplyMM(result[(i + 1) % 2], 0, result[i % 2], 0, rhs, 0);
+ }
+ return result[count % 2];
+ }
+ }
+
+ /**
+ * Returns the current Daltonization mode.
+ */
+ public int getDaltonizerMode() {
+ return mDaltonizerMode;
+ }
+
+ /**
+ * Sets the current Daltonization mode. This adjusts the color space to correct for or simulate
+ * various types of color blindness.
+ *
+ * @param mode the new Daltonization mode, or -1 to disable
+ */
+ public void setDaltonizerMode(int mode) {
+ if (mDaltonizerMode != mode) {
+ mDaltonizerMode = mode;
+ applyDaltonizerMode(mode);
+ }
+ }
+
+ /**
+ * Propagates the provided color transformation matrix to the SurfaceFlinger.
+ */
+ private static void applyColorMatrix(float[] m) {
+ final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
+ if (flinger != null) {
+ final Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ if (m != null) {
+ data.writeInt(1);
+ for (int i = 0; i < 16; i++) {
+ data.writeFloat(m[i]);
+ }
+ } else {
+ data.writeInt(0);
+ }
+ try {
+ flinger.transact(1015, data, null, 0);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to set color transform", ex);
+ } finally {
+ data.recycle();
+ }
+ }
+ }
+
+ /**
+ * Propagates the provided Daltonization mode to the SurfaceFlinger.
+ */
+ private static void applyDaltonizerMode(int mode) {
+ final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
+ if (flinger != null) {
+ final Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ data.writeInt(mode);
+ try {
+ flinger.transact(1014, data, null, 0);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to set Daltonizer mode", ex);
+ } finally {
+ data.recycle();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
new file mode 100644
index 000000000000..006747bdfca2
--- /dev/null
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import android.app.AlarmManager;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings.Secure;
+import android.util.Slog;
+
+import com.android.internal.app.NightDisplayController;
+import com.android.server.SystemService;
+import com.android.server.twilight.TwilightListener;
+import com.android.server.twilight.TwilightManager;
+import com.android.server.twilight.TwilightState;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * Tints the display at night.
+ */
+public final class NightDisplayService extends SystemService
+ implements NightDisplayController.Callback {
+
+ private static final String TAG = "NightDisplayService";
+ private static final boolean DEBUG = false;
+
+ /**
+ * Night display ~= 3400 K.
+ */
+ private static final float[] MATRIX_NIGHT = new float[] {
+ 1, 0, 0, 0,
+ 0, 0.754f, 0, 0,
+ 0, 0, 0.516f, 0,
+ 0, 0, 0, 1
+ };
+
+ private int mCurrentUser = UserHandle.USER_NULL;
+ private boolean mBootCompleted;
+
+ private NightDisplayController mController;
+ private Boolean mIsActivated;
+ private AutoMode mAutoMode;
+
+ public NightDisplayService(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ // Nothing to publish.
+ }
+
+ @Override
+ public void onStartUser(int userHandle) {
+ super.onStartUser(userHandle);
+
+ // Register listeners for the new user.
+ if (mCurrentUser == UserHandle.USER_NULL) {
+ mCurrentUser = userHandle;
+ if (mBootCompleted) {
+ setUpNightMode();
+ }
+ }
+ }
+
+ @Override
+ public void onSwitchUser(int userHandle) {
+ super.onSwitchUser(userHandle);
+
+ // Unregister listeners for the old user.
+ if (mBootCompleted && mCurrentUser != UserHandle.USER_NULL) {
+ tearDownNightMode();
+ }
+
+ // Register listeners for the new user.
+ mCurrentUser = userHandle;
+ if (mBootCompleted) {
+ setUpNightMode();
+ }
+ }
+
+ @Override
+ public void onStopUser(int userHandle) {
+ super.onStopUser(userHandle);
+
+ // Unregister listeners for the old user.
+ if (mCurrentUser == userHandle) {
+ if (mBootCompleted) {
+ tearDownNightMode();
+ }
+ mCurrentUser = UserHandle.USER_NULL;
+ }
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_BOOT_COMPLETED) {
+ mBootCompleted = true;
+
+ // Register listeners now that boot is complete.
+ if (mCurrentUser != UserHandle.USER_NULL) {
+ setUpNightMode();
+ }
+ }
+ }
+
+ private void setUpNightMode() {
+ // Create a new controller for the current user and start listening for changes.
+ mController = new NightDisplayController(getContext(), mCurrentUser);
+ mController.setListener(this);
+
+ // Initialize the current auto mode.
+ onAutoModeChanged(mController.getAutoMode());
+
+ // Force the initialization current activated state.
+ if (mIsActivated == null) {
+ onActivated(mController.isActivated());
+ }
+ }
+
+ private void tearDownNightMode() {
+ mController.setListener(null);
+
+ if (mAutoMode != null) {
+ mAutoMode.onStop();
+ mAutoMode = null;
+ }
+
+ mIsActivated = null;
+ mController = null;
+ }
+
+ @Override
+ public void onActivated(boolean activated) {
+ if (mIsActivated == null || mIsActivated != activated) {
+ Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
+
+ mIsActivated = activated;
+
+ if (mAutoMode != null) {
+ mAutoMode.onActivated(activated);
+ }
+
+ // Update the current color matrix.
+ final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
+ dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY,
+ activated ? MATRIX_NIGHT : null);
+ }
+ }
+
+ @Override
+ public void onAutoModeChanged(int autoMode) {
+ if (mAutoMode != null) {
+ mAutoMode.onStop();
+ mAutoMode = null;
+ }
+
+ if (autoMode == NightDisplayController.AUTO_MODE_CUSTOM) {
+ mAutoMode = new CustomAutoMode();
+ } else if (autoMode == NightDisplayController.AUTO_MODE_TWILIGHT) {
+ mAutoMode = new TwilightAutoMode();
+ }
+
+ if (mAutoMode != null) {
+ mAutoMode.onStart();
+ }
+ }
+
+ @Override
+ public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
+ if (mAutoMode != null) {
+ mAutoMode.onCustomStartTimeChanged(startTime);
+ }
+ }
+
+ @Override
+ public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
+ if (mAutoMode != null) {
+ mAutoMode.onCustomEndTimeChanged(endTime);
+ }
+ }
+
+ private abstract class AutoMode implements NightDisplayController.Callback {
+ public abstract void onStart();
+ public abstract void onStop();
+ }
+
+ private class CustomAutoMode extends AutoMode implements AlarmManager.OnAlarmListener {
+
+ private final AlarmManager mAlarmManager;
+ private final BroadcastReceiver mTimeChangedReceiver;
+
+ private NightDisplayController.LocalTime mStartTime;
+ private NightDisplayController.LocalTime mEndTime;
+
+ private Calendar mLastActivatedTime;
+
+ public CustomAutoMode() {
+ mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
+ mTimeChangedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ updateActivated();
+ }
+ };
+ }
+
+ private void updateActivated() {
+ final Calendar now = Calendar.getInstance();
+ final Calendar startTime = mStartTime.getDateTimeBefore(now);
+ final Calendar endTime = mEndTime.getDateTimeAfter(startTime);
+ final boolean activated = now.before(endTime);
+
+ boolean setActivated = mIsActivated == null || mLastActivatedTime == null;
+ if (!setActivated && mIsActivated != activated) {
+ final TimeZone currentTimeZone = now.getTimeZone();
+ if (!currentTimeZone.equals(mLastActivatedTime.getTimeZone())) {
+ final int year = mLastActivatedTime.get(Calendar.YEAR);
+ final int dayOfYear = mLastActivatedTime.get(Calendar.DAY_OF_YEAR);
+ final int hourOfDay = mLastActivatedTime.get(Calendar.HOUR_OF_DAY);
+ final int minute = mLastActivatedTime.get(Calendar.MINUTE);
+
+ mLastActivatedTime.setTimeZone(currentTimeZone);
+ mLastActivatedTime.set(Calendar.YEAR, year);
+ mLastActivatedTime.set(Calendar.DAY_OF_YEAR, dayOfYear);
+ mLastActivatedTime.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ mLastActivatedTime.set(Calendar.MINUTE, minute);
+ }
+
+ if (mIsActivated) {
+ setActivated = now.before(mStartTime.getDateTimeBefore(mLastActivatedTime))
+ || now.after(mEndTime.getDateTimeAfter(mLastActivatedTime));
+ } else {
+ setActivated = now.before(mEndTime.getDateTimeBefore(mLastActivatedTime))
+ || now.after(mStartTime.getDateTimeAfter(mLastActivatedTime));
+ }
+ }
+
+ if (setActivated) {
+ mController.setActivated(activated);
+ }
+ updateNextAlarm();
+ }
+
+ private void updateNextAlarm() {
+ if (mIsActivated != null) {
+ final Calendar now = Calendar.getInstance();
+ final Calendar next = mIsActivated ? mEndTime.getDateTimeAfter(now)
+ : mStartTime.getDateTimeAfter(now);
+ mAlarmManager.setExact(AlarmManager.RTC, next.getTimeInMillis(), TAG, this, null);
+ }
+ }
+
+ @Override
+ public void onStart() {
+ final IntentFilter intentFilter = new IntentFilter(Intent.ACTION_TIME_CHANGED);
+ intentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+ getContext().registerReceiver(mTimeChangedReceiver, intentFilter);
+
+ mStartTime = mController.getCustomStartTime();
+ mEndTime = mController.getCustomEndTime();
+
+ // Force an update to initialize state.
+ updateActivated();
+ }
+
+ @Override
+ public void onStop() {
+ getContext().unregisterReceiver(mTimeChangedReceiver);
+
+ mAlarmManager.cancel(this);
+ mLastActivatedTime = null;
+ }
+
+ @Override
+ public void onActivated(boolean activated) {
+ mLastActivatedTime = Calendar.getInstance();
+ updateNextAlarm();
+ }
+
+ @Override
+ public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
+ mStartTime = startTime;
+ mLastActivatedTime = null;
+ updateActivated();
+ }
+
+ @Override
+ public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
+ mEndTime = endTime;
+ mLastActivatedTime = null;
+ updateActivated();
+ }
+
+ @Override
+ public void onAlarm() {
+ if (DEBUG) Slog.d(TAG, "onAlarm");
+ updateActivated();
+ }
+ }
+
+ private class TwilightAutoMode extends AutoMode implements TwilightListener {
+
+ private final TwilightManager mTwilightManager;
+ private final Handler mHandler;
+
+ private boolean mIsNight;
+
+ public TwilightAutoMode() {
+ mTwilightManager = getLocalService(TwilightManager.class);
+ mHandler = new Handler(Looper.getMainLooper());
+ }
+
+ private void updateActivated() {
+ final TwilightState state = mTwilightManager.getCurrentState();
+ final boolean isNight = state != null && state.isNight();
+ if (mIsNight != isNight) {
+ mIsNight = isNight;
+
+ if (mIsActivated == null || mIsActivated != isNight) {
+ mController.setActivated(isNight);
+ }
+ }
+ }
+
+ @Override
+ public void onStart() {
+ mTwilightManager.registerListener(this, mHandler);
+
+ // Force an update to initialize state.
+ updateActivated();
+ }
+
+ @Override
+ public void onStop() {
+ mTwilightManager.unregisterListener(this);
+ }
+
+ @Override
+ public void onTwilightStateChanged() {
+ if (DEBUG) Slog.d(TAG, "onTwilightStateChanged");
+ updateActivated();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 8589de1a1884..8f212db7d90a 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1556,6 +1556,11 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
}
+ if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG);
+ }
+
long ident = Binder.clearCallingIdentity();
try {
return JobSchedulerService.this.schedule(job, uid);
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 29c54e9bf78c..88d6c14fb5de 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -454,7 +454,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
@Override
public String toString() {
- return mPackageName + "/" + mTag;
+ return mPackageName + "/" + mTag + " (uid=" + mUserId + ")";
}
private void postAdjustLocalVolume(final int stream, final int direction, final int flags,
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index a4d2cd25cb14..a3f09c03ae74 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -47,10 +47,12 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.speech.RecognizerIntent;
import android.text.TextUtils;
@@ -67,6 +69,7 @@ import com.android.server.Watchdog.Monitor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -97,7 +100,9 @@ public class MediaSessionService extends SystemService implements Monitor {
private ContentResolver mContentResolver;
private SettingsObserver mSettingsObserver;
- private int mCurrentUserId = -1;
+ // List of user IDs running in the foreground.
+ // Multiple users can be in the foreground if the work profile is on.
+ private final List<Integer> mCurrentUserIdList = new ArrayList<>();
// Used to notify system UI when remote volume was changed. TODO find a
// better way to handle this.
@@ -181,22 +186,26 @@ public class MediaSessionService extends SystemService implements Monitor {
}
@Override
- public void onStartUser(int userHandle) {
+ public void onStartUser(int userId) {
+ if (DEBUG) Log.d(TAG, "onStartUser: " + userId);
updateUser();
}
@Override
- public void onSwitchUser(int userHandle) {
+ public void onSwitchUser(int userId) {
+ if (DEBUG) Log.d(TAG, "onSwitchUser: " + userId);
updateUser();
}
@Override
- public void onStopUser(int userHandle) {
+ public void onStopUser(int userId) {
+ if (DEBUG) Log.d(TAG, "onStopUser: " + userId);
synchronized (mLock) {
- UserRecord user = mUserRecords.get(userHandle);
+ UserRecord user = mUserRecords.get(userId);
if (user != null) {
destroyUserLocked(user);
}
+ updateUser();
}
}
@@ -228,18 +237,23 @@ public class MediaSessionService extends SystemService implements Monitor {
private void updateUser() {
synchronized (mLock) {
- int userId = ActivityManager.getCurrentUser();
- if (mCurrentUserId != userId) {
- final int oldUserId = mCurrentUserId;
- mCurrentUserId = userId; // do this first
-
- UserRecord oldUser = mUserRecords.get(oldUserId);
- if (oldUser != null) {
- oldUser.stopLocked();
+ UserManager manager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+ int currentUser = ActivityManager.getCurrentUser();
+ int[] userIds = manager.getEnabledProfileIds(currentUser);
+ mCurrentUserIdList.clear();
+ if (userIds != null && userIds.length > 0) {
+ for (int userId : userIds) {
+ mCurrentUserIdList.add(userId);
+ }
+ } else {
+ // This shouldn't happen.
+ Log.w(TAG, "Failed to get enabled profiles.");
+ mCurrentUserIdList.add(currentUser);
+ }
+ for (int userId : mCurrentUserIdList) {
+ if (mUserRecords.get(userId) == null) {
+ mUserRecords.put(userId, new UserRecord(getContext(), userId));
}
-
- UserRecord newUser = getOrCreateUser(userId);
- newUser.startLocked();
}
}
}
@@ -272,7 +286,6 @@ public class MediaSessionService extends SystemService implements Monitor {
* @param user The user to dispose of
*/
private void destroyUserLocked(UserRecord user) {
- user.stopLocked();
user.destroyLocked();
mUserRecords.remove(user.mUserId);
}
@@ -436,9 +449,9 @@ public class MediaSessionService extends SystemService implements Monitor {
}
mAllSessions.add(session);
- mPriorityStack.addSession(session);
+ mPriorityStack.addSession(session, mCurrentUserIdList.contains(userId));
- UserRecord user = getOrCreateUser(userId);
+ UserRecord user = mUserRecords.get(userId);
user.addSessionLocked(session);
mHandler.post(MessageHandler.MSG_SESSIONS_CHANGED, userId, 0);
@@ -449,15 +462,6 @@ public class MediaSessionService extends SystemService implements Monitor {
return session;
}
- private UserRecord getOrCreateUser(int userId) {
- UserRecord user = mUserRecords.get(userId);
- if (user == null) {
- user = new UserRecord(getContext(), userId);
- mUserRecords.put(userId, user);
- }
- return user;
- }
-
private int findIndexOfSessionsListenerLocked(IActiveSessionsListener listener) {
for (int i = mSessionsListeners.size() - 1; i >= 0; i--) {
if (mSessionsListeners.get(i).mListener.asBinder() == listener.asBinder()) {
@@ -536,13 +540,6 @@ public class MediaSessionService extends SystemService implements Monitor {
restoreMediaButtonReceiver();
}
- public void startLocked() {
- }
-
- public void stopLocked() {
- // nothing for now
- }
-
public void destroyLocked() {
for (int i = mSessions.size() - 1; i >= 0; i--) {
MediaSessionRecord session = mSessions.get(i);
@@ -578,7 +575,7 @@ public class MediaSessionService extends SystemService implements Monitor {
private void restoreMediaButtonReceiver() {
String receiverName = Settings.Secure.getStringForUser(mContentResolver,
- Settings.System.MEDIA_BUTTON_RECEIVER, UserHandle.USER_CURRENT);
+ Settings.System.MEDIA_BUTTON_RECEIVER, mUserId);
if (!TextUtils.isEmpty(receiverName)) {
ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
if (eventReceiver == null) {
@@ -767,12 +764,22 @@ public class MediaSessionService extends SystemService implements Monitor {
synchronized (mLock) {
// If we don't have a media button receiver to fall back on
// include non-playing sessions for dispatching
- UserRecord ur = mUserRecords.get(mCurrentUserId);
- boolean useNotPlayingSessions = (ur == null) ||
- (ur.mLastMediaButtonReceiver == null
- && ur.mRestoredMediaButtonReceiver == null);
- MediaSessionRecord session = mPriorityStack
- .getDefaultMediaButtonSession(mCurrentUserId, useNotPlayingSessions);
+ boolean useNotPlayingSessions = true;
+ for (int userId : mCurrentUserIdList) {
+ UserRecord ur = mUserRecords.get(userId);
+ if (ur.mLastMediaButtonReceiver != null
+ || ur.mRestoredMediaButtonReceiver != null) {
+ useNotPlayingSessions = false;
+ break;
+ }
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "dispatchMediaKeyEvent, useNotPlayingSessions="
+ + useNotPlayingSessions);
+ }
+ MediaSessionRecord session = mPriorityStack.getDefaultMediaButtonSession(
+ mCurrentUserIdList, useNotPlayingSessions);
if (isVoiceKey(keyEvent.getKeyCode())) {
handleVoiceKeyEventLocked(keyEvent, needWakeLock, session);
} else {
@@ -786,13 +793,11 @@ public class MediaSessionService extends SystemService implements Monitor {
@Override
public void dispatchAdjustVolume(int suggestedStream, int delta, int flags) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
MediaSessionRecord session = mPriorityStack
- .getDefaultVolumeSession(mCurrentUserId);
+ .getDefaultVolumeSession(mCurrentUserIdList);
dispatchAdjustVolumeLocked(suggestedStream, delta, flags, session);
}
} finally {
@@ -899,7 +904,7 @@ public class MediaSessionService extends SystemService implements Monitor {
}
} else {
session.adjustVolume(direction, flags, getContext().getPackageName(),
- UserHandle.myUserId(), true);
+ Process.SYSTEM_UID, true);
}
}
@@ -946,13 +951,16 @@ public class MediaSessionService extends SystemService implements Monitor {
// won't release it later
session.sendMediaButton(keyEvent,
needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
- mKeyEventReceiver, getContext().getApplicationInfo().uid,
+ mKeyEventReceiver, Process.SYSTEM_UID,
getContext().getPackageName());
} else {
// Launch the last PendingIntent we had with priority
- UserRecord user = mUserRecords.get(mCurrentUserId);
- if (user != null && (user.mLastMediaButtonReceiver != null
- || user.mRestoredMediaButtonReceiver != null)) {
+ for (int userId : mCurrentUserIdList) {
+ UserRecord user = mUserRecords.get(userId);
+ if (user.mLastMediaButtonReceiver == null
+ && user.mRestoredMediaButtonReceiver == null) {
+ continue;
+ }
if (DEBUG) {
Log.d(TAG, "Sending media key to last known PendingIntent "
+ user.mLastMediaButtonReceiver + " or restored Intent "
@@ -972,30 +980,30 @@ public class MediaSessionService extends SystemService implements Monitor {
} else {
mediaButtonIntent.setComponent(user.mRestoredMediaButtonReceiver);
getContext().sendBroadcastAsUser(mediaButtonIntent,
- new UserHandle(mCurrentUserId));
+ UserHandle.of(userId));
}
} catch (CanceledException e) {
Log.i(TAG, "Error sending key event to media button receiver "
+ user.mLastMediaButtonReceiver, e);
}
- } else {
- if (DEBUG) {
- Log.d(TAG, "Sending media key ordered broadcast");
- }
- if (needWakeLock) {
- mMediaEventWakeLock.acquire();
- }
- // Fallback to legacy behavior
- Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
- keyIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- keyIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
- if (needWakeLock) {
- keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED,
- WAKELOCK_RELEASE_ON_FINISHED);
- }
- getContext().sendOrderedBroadcastAsUser(keyIntent, UserHandle.CURRENT,
- null, mKeyEventDone, mHandler, Activity.RESULT_OK, null, null);
+ return;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "Sending media key ordered broadcast");
+ }
+ if (needWakeLock) {
+ mMediaEventWakeLock.acquire();
+ }
+ // Fallback to legacy behavior
+ Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
+ keyIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ keyIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+ if (needWakeLock) {
+ keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED, WAKELOCK_RELEASE_ON_FINISHED);
}
+ // Send broadcast only to the full user.
+ getContext().sendOrderedBroadcastAsUser(keyIntent, UserHandle.CURRENT,
+ null, mKeyEventDone, mHandler, Activity.RESULT_OK, null, null);
}
}
@@ -1025,6 +1033,7 @@ public class MediaSessionService extends SystemService implements Monitor {
if (voiceIntent != null) {
voiceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ if (DEBUG) Log.d(TAG, "voiceIntent: " + voiceIntent);
getContext().startActivityAsUser(voiceIntent, UserHandle.CURRENT);
}
} catch (ActivityNotFoundException e) {
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index cc007eff9075..3327b36536d9 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -32,7 +32,7 @@ import java.util.List;
* Keeps track of media sessions and their priority for notifications, media
* button dispatch, etc.
*/
-public class MediaSessionStack {
+class MediaSessionStack {
/**
* These are states that usually indicate the user took an action and should
* bump priority regardless of the old state.
@@ -68,13 +68,10 @@ public class MediaSessionStack {
* Checks if a media session is created from the most recent app.
*
* @param record A media session record to be examined.
- * @return true if the media session's package name equals to the most recent app, false
- * otherwise.
+ * @return {@code true} if the media session's package name equals to the most recent app, false
+ * otherwise.
*/
private static boolean isFromMostRecentApp(MediaSessionRecord record) {
- if (ActivityManager.getCurrentUser() != record.getUserId()) {
- return false;
- }
try {
List<ActivityManager.RecentTaskInfo> tasks =
ActivityManagerNative.getDefault().getRecentTasks(1,
@@ -84,9 +81,10 @@ public class MediaSessionStack {
ActivityManager.RECENT_WITH_EXCLUDED, record.getUserId()).getList();
if (tasks != null && !tasks.isEmpty()) {
ActivityManager.RecentTaskInfo recentTask = tasks.get(0);
- if (recentTask.baseIntent != null)
+ if (recentTask.userId == record.getUserId() && recentTask.baseIntent != null) {
return recentTask.baseIntent.getComponent().getPackageName()
.equals(record.getPackageName());
+ }
}
} catch (RemoteException e) {
return false;
@@ -98,11 +96,12 @@ public class MediaSessionStack {
* Add a record to the priority tracker.
*
* @param record The record to add.
+ * @param fromForegroundUser {@code true} if the session is created by the foreground user.
*/
- public void addSession(MediaSessionRecord record) {
+ public void addSession(MediaSessionRecord record, boolean fromForegroundUser) {
mSessions.add(record);
clearCache();
- if (isFromMostRecentApp(record)) {
+ if (fromForegroundUser && isFromMostRecentApp(record)) {
mLastInterestingRecord = record;
}
}
@@ -210,12 +209,13 @@ public class MediaSessionStack {
/**
* Get the highest priority session that can handle media buttons.
*
- * @param userId The user to check.
+ * @param userIdList The user lists to check.
* @param includeNotPlaying Return a non-playing session if nothing else is
* available
* @return The default media button session or null.
*/
- public MediaSessionRecord getDefaultMediaButtonSession(int userId, boolean includeNotPlaying) {
+ public MediaSessionRecord getDefaultMediaButtonSession(
+ List<Integer> userIdList, boolean includeNotPlaying) {
if (mGlobalPrioritySession != null && mGlobalPrioritySession.isActive()) {
return mGlobalPrioritySession;
}
@@ -223,7 +223,7 @@ public class MediaSessionStack {
return mCachedButtonReceiver;
}
ArrayList<MediaSessionRecord> records = getPriorityListLocked(true,
- MediaSession.FLAG_HANDLES_MEDIA_BUTTONS, userId);
+ MediaSession.FLAG_HANDLES_MEDIA_BUTTONS, userIdList);
if (records.size() > 0) {
MediaSessionRecord record = records.get(0);
if (record.isPlaybackActive(false)) {
@@ -248,14 +248,14 @@ public class MediaSessionStack {
return mCachedButtonReceiver;
}
- public MediaSessionRecord getDefaultVolumeSession(int userId) {
+ public MediaSessionRecord getDefaultVolumeSession(List<Integer> userIdList) {
if (mGlobalPrioritySession != null && mGlobalPrioritySession.isActive()) {
return mGlobalPrioritySession;
}
if (mCachedVolumeDefault != null) {
return mCachedVolumeDefault;
}
- ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userId);
+ ArrayList<MediaSessionRecord> records = getPriorityListLocked(true, 0, userIdList);
int size = records.size();
for (int i = 0; i < size; i++) {
MediaSessionRecord record = records.get(i);
@@ -298,6 +298,13 @@ public class MediaSessionStack {
}
}
+ private ArrayList<MediaSessionRecord> getPriorityListLocked(boolean activeOnly, int withFlags,
+ int userId) {
+ List<Integer> userIdList = new ArrayList<>();
+ userIdList.add(userId);
+ return getPriorityListLocked(activeOnly, withFlags, userIdList);
+ }
+
/**
* Get a priority sorted list of sessions. Can filter to only return active
* sessions or sessions with specific flags.
@@ -306,22 +313,23 @@ public class MediaSessionStack {
* all sessions.
* @param withFlags Only return sessions with all the specified flags set. 0
* returns all sessions.
- * @param userId The user to get sessions for. {@link UserHandle#USER_ALL}
+ * @param userIdList The user to get sessions for. {@link UserHandle#USER_ALL}
* will return sessions for all users.
* @return The priority sorted list of sessions.
*/
private ArrayList<MediaSessionRecord> getPriorityListLocked(boolean activeOnly, int withFlags,
- int userId) {
+ List<Integer> userIdList) {
ArrayList<MediaSessionRecord> result = new ArrayList<MediaSessionRecord>();
int lastLocalIndex = 0;
int lastActiveIndex = 0;
int lastPublishedIndex = 0;
+ boolean filterUser = !userIdList.contains(UserHandle.USER_ALL);
int size = mSessions.size();
for (int i = 0; i < size; i++) {
final MediaSessionRecord session = mSessions.get(i);
- if (userId != UserHandle.USER_ALL && userId != session.getUserId()) {
+ if (filterUser && !userIdList.contains(session.getUserId())) {
// Filter out sessions for the wrong user
continue;
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index f15fdd5304a1..b22a08484b8a 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1241,6 +1241,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
// TODO: reach into ConnectivityManager to proactively disable bringing
// up this network, since we know that traffic will be blocked.
+
+ if (template.getMatchRule() == MATCH_MOBILE_ALL) {
+ // If mobile data usage hits the limit or if the user resumes the data, we need to
+ // notify telephony.
+ final SubscriptionManager sm = SubscriptionManager.from(mContext);
+ final TelephonyManager tm = TelephonyManager.from(mContext);
+
+ final int[] subIds = sm.getActiveSubscriptionIdList();
+ for (int subId : subIds) {
+ final String subscriberId = tm.getSubscriberId(subId);
+ final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
+ // Template is matched when subscriber id matches.
+ if (template.matches(probeIdent)) {
+ tm.setPolicyDataEnabled(enabled, subId);
+ }
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ec77dafb2914..8d19a24753a2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1851,7 +1851,7 @@ public class NotificationManagerService extends SystemService {
enforceSystemOrSystemUIOrVolume("INotificationManager.setZenMode");
final long identity = Binder.clearCallingIdentity();
try {
- mZenModeHelper.setManualZenMode(mode, conditionId, reason);
+ mZenModeHelper.setManualZenMode(mode, conditionId, null, reason);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1928,7 +1928,7 @@ public class NotificationManagerService extends SystemService {
if (zen == -1) throw new IllegalArgumentException("Invalid filter: " + filter);
final long identity = Binder.clearCallingIdentity();
try {
- mZenModeHelper.setManualZenMode(zen, null, "setInterruptionFilter");
+ mZenModeHelper.setManualZenMode(zen, null, pkg, "setInterruptionFilter");
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 6864ed898ada..8c9dc3ba60f2 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -54,7 +54,6 @@ import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.EventInfo;
import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.service.notification.ZenModeConfig.ZenRule;
-import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.Log;
import android.util.SparseArray;
@@ -229,7 +228,7 @@ public class ZenModeHelper {
public void requestFromListener(ComponentName name, int filter) {
final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
if (newZen != -1) {
- setManualZenMode(newZen, null,
+ setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
"listener:" + (name != null ? name.flattenToShortString() : null));
}
}
@@ -452,11 +451,11 @@ public class ZenModeHelper {
rule.creationTime);
}
- public void setManualZenMode(int zenMode, Uri conditionId, String reason) {
- setManualZenMode(zenMode, conditionId, reason, true /*setRingerMode*/);
+ public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
+ setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
}
- private void setManualZenMode(int zenMode, Uri conditionId, String reason,
+ private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
boolean setRingerMode) {
ZenModeConfig newConfig;
synchronized (mConfig) {
@@ -478,6 +477,7 @@ public class ZenModeHelper {
newRule.enabled = true;
newRule.zenMode = zenMode;
newRule.conditionId = conditionId;
+ newRule.enabler = caller;
newConfig.manualRule = newRule;
}
setConfigLocked(newConfig, reason, setRingerMode);
@@ -950,7 +950,8 @@ public class ZenModeHelper {
break;
}
if (newZen != -1) {
- setManualZenMode(newZen, null, "ringerModeInternal", false /*setRingerMode*/);
+ setManualZenMode(newZen, null, "ringerModeInternal", null,
+ false /*setRingerMode*/);
}
if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
@@ -988,7 +989,8 @@ public class ZenModeHelper {
break;
}
if (newZen != -1) {
- setManualZenMode(newZen, null, "ringerModeExternal", false /*setRingerMode*/);
+ setManualZenMode(newZen, null, "ringerModeExternal", caller,
+ false /*setRingerMode*/);
}
ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 098b39e50d92..1cff926d14e1 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -31,6 +31,7 @@ import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.UserHandle;
+import android.os.storage.StorageManager;
import android.print.PrintManager;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
@@ -605,6 +606,15 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(nfcTagPkg, CONTACTS_PERMISSIONS, false, userId);
grantRuntimePermissionsLPw(nfcTagPkg, PHONE_PERMISSIONS, false, userId);
}
+
+ // Storage Manager
+ Intent storageManagerIntent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
+ PackageParser.Package storageManagerPckg = getDefaultSystemHandlerActivityPackageLPr(
+ storageManagerIntent, userId);
+ if (storageManagerPckg != null
+ && doesPackageSupportRuntimePermissions(storageManagerPckg)) {
+ grantRuntimePermissionsLPw(storageManagerPckg, STORAGE_PERMISSIONS, true, userId);
+ }
mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
}
}
@@ -619,6 +629,7 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, userId);
grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(dialerPackage, CAMERA_PERMISSIONS, userId);
}
}
@@ -656,6 +667,7 @@ final class DefaultPermissionGrantPolicy {
grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, false, true, userId);
grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, false, true, userId);
grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, false, true, userId);
+ grantRuntimePermissionsLPw(dialerPackage, CAMERA_PERMISSIONS, false, true, userId);
}
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 03d5645f7e5d..cff2da9f005c 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -19,19 +19,18 @@ package com.android.server.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.ActivityManagerNative;
import android.app.AppGlobals;
-import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
-import android.content.IIntentSender;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ILauncherApps;
import android.content.pm.IOnAppsChangedListener;
import android.content.pm.IPackageManager;
+import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -439,7 +438,7 @@ public class LauncherAppsService extends SystemService {
}
@Override
- public void startShortcut(String callingPackage, String packageName, String shortcutId,
+ public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
Rect sourceBounds, Bundle startActivityOptions, int userId) {
verifyCallingPackage(callingPackage);
ensureInUserProfiles(userId, "Cannot start activity for unrelated profile " + userId);
@@ -458,39 +457,36 @@ public class LauncherAppsService extends SystemService {
final Intent intent = mShortcutServiceInternal.createShortcutIntent(getCallingUserId(),
callingPackage, packageName, shortcutId, userId);
if (intent == null) {
- return;
+ return false;
}
// Note the target activity doesn't have to be exported.
prepareIntentForLaunch(intent, sourceBounds);
- startShortcutIntentAsPublisher(
+ return startShortcutIntentAsPublisher(
intent, packageName, startActivityOptions, userId);
}
- @VisibleForTesting
- protected void startShortcutIntentAsPublisher(@NonNull Intent intent,
+ private boolean startShortcutIntentAsPublisher(@NonNull Intent intent,
@NonNull String publisherPackage, Bundle startActivityOptions, int userId) {
-
+ final int code;
+ final long ident = injectClearCallingIdentity();
try {
- final IIntentSender intentSender;
-
- final long ident = Binder.clearCallingIdentity();
- try {
- intentSender = mActivityManagerInternal.getActivityIntentSenderAsPackage(
- publisherPackage, userId, /* requestCode= */ 0,
- intent, PendingIntent.FLAG_ONE_SHOT,
- /* options= */ startActivityOptions);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ code = mActivityManagerInternal.startActivityAsPackage(publisherPackage,
+ userId, intent, startActivityOptions);
+ if (code >= ActivityManager.START_SUCCESS) {
+ return true; // Success
+ } else {
+ Log.e(TAG, "Couldn't start activity, code=" + code);
}
-
- // Negative result means a failure.
- ActivityManagerNative.getDefault().sendIntentSender(
- intentSender, 0, null, null, null, null, null);
-
- } catch (RemoteException e) {
- return;
+ return code >= ActivityManager.START_SUCCESS;
+ } catch (SecurityException e) {
+ if (DEBUG) {
+ Slog.d(TAG, "SecurityException while launching intent", e);
+ }
+ return false;
+ } finally {
+ injectRestoreCallingIdentity(ident);
}
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 01b3dc28b50e..02c6472b2f88 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -213,9 +213,19 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
// Use the package manager install and install lock here for the OTA dex optimizer.
PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
collectingInstaller, mPackageManagerService.mInstallLock, mContext);
+ // Make sure that core apps are optimized according to their own "reason".
+ // If the core apps are not preopted in the B OTA, and REASON_AB_OTA is not speed
+ // (by default is speed-profile) they will be interepreted/JITed. This in itself is not a
+ // problem as we will end up doing profile guided compilation. However, some core apps may
+ // be loaded by system server which doesn't JIT and we need to make sure we don't
+ // interpret-only
+ int compilationReason = nextPackage.coreApp
+ ? PackageManagerService.REASON_CORE_APP
+ : PackageManagerService.REASON_AB_OTA;
+
optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles,
null /* ISAs */, false /* checkProfiles */,
- getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA));
+ getCompilerFilterForReason(compilationReason));
mCommandsForCurrentPackage = collectingConnection.commands;
if (mCommandsForCurrentPackage.isEmpty()) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 83af0173c514..6a56fa6e629b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -182,6 +182,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
*/
private final Random mRandom = new SecureRandom();
+ /** All sessions allocated */
+ @GuardedBy("mSessions")
+ private final SparseBooleanArray mAllocatedSessions = new SparseBooleanArray();
+
@GuardedBy("mSessions")
private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>();
@@ -365,6 +369,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
// keep details around for dumpsys.
mHistoricalSessions.put(session.sessionId, session);
}
+ mAllocatedSessions.put(session.sessionId, true);
}
}
}
@@ -666,23 +671,26 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
"Too many historical sessions for UID " + callingUid);
}
- final long createdMillis = System.currentTimeMillis();
sessionId = allocateSessionIdLocked();
+ }
- // We're staging to exactly one location
- File stageDir = null;
- String stageCid = null;
- if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
- final boolean isEphemeral =
- (params.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
- stageDir = buildStageDir(params.volumeUuid, sessionId, isEphemeral);
- } else {
- stageCid = buildExternalStageCid(sessionId);
- }
+ final long createdMillis = System.currentTimeMillis();
+ // We're staging to exactly one location
+ File stageDir = null;
+ String stageCid = null;
+ if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+ final boolean isEphemeral =
+ (params.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
+ stageDir = buildStageDir(params.volumeUuid, sessionId, isEphemeral);
+ } else {
+ stageCid = buildExternalStageCid(sessionId);
+ }
- session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
- mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
- params, createdMillis, stageDir, stageCid, false, false);
+ session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
+ mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
+ params, createdMillis, stageDir, stageCid, false, false);
+
+ synchronized (mSessions) {
mSessions.put(sessionId, session);
}
@@ -765,8 +773,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
int sessionId;
do {
sessionId = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
- if (mSessions.get(sessionId) == null && mHistoricalSessions.get(sessionId) == null
- && !mLegacySessions.get(sessionId, false)) {
+ if (!mAllocatedSessions.get(sessionId, false)) {
+ mAllocatedSessions.put(sessionId, true);
return sessionId;
}
} while (n++ < 32);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 84ebdd15947d..78fa3a37dcf5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -95,6 +95,7 @@ import static com.android.server.pm.InstructionSets.getPreferredInstructionSet;
import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet;
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason;
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getFullCompilerFilter;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.getNonProfileGuidedCompilerFilter;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_FAILURE;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
@@ -2800,7 +2801,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- int[] stats = performDexOpt(coreApps, false,
+ int[] stats = performDexOptUpgrade(coreApps, false,
getCompilerFilterForReason(REASON_CORE_APP));
final int elapsedTimeSeconds =
@@ -7267,22 +7268,17 @@ public class PackageManagerService extends IPackageManager.Stub {
try {
IMountService ms = PackageHelper.getMountService();
if (ms != null) {
- final boolean isUpgrade = isUpgrade();
- boolean doTrim = isUpgrade;
- if (doTrim) {
- Slog.w(TAG, "Running disk maintenance immediately due to system update");
- } else {
- final long interval = android.provider.Settings.Global.getLong(
- mContext.getContentResolver(),
- android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
- DEFAULT_MANDATORY_FSTRIM_INTERVAL);
- if (interval > 0) {
- final long timeSinceLast = System.currentTimeMillis() - ms.lastMaintenance();
- if (timeSinceLast > interval) {
- doTrim = true;
- Slog.w(TAG, "No disk maintenance in " + timeSinceLast
- + "; running immediately");
- }
+ boolean doTrim = false;
+ final long interval = android.provider.Settings.Global.getLong(
+ mContext.getContentResolver(),
+ android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
+ DEFAULT_MANDATORY_FSTRIM_INTERVAL);
+ if (interval > 0) {
+ final long timeSinceLast = System.currentTimeMillis() - ms.lastMaintenance();
+ if (timeSinceLast > interval) {
+ doTrim = true;
+ Slog.w(TAG, "No disk maintenance in " + timeSinceLast
+ + "; running immediately");
}
}
if (doTrim) {
@@ -7329,7 +7325,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
final long startTime = System.nanoTime();
- final int[] stats = performDexOpt(pkgs, mIsPreNUpgrade /* showDialog */,
+ final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,
getCompilerFilterForReason(causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT));
final int elapsedTimeSeconds =
@@ -7348,7 +7344,7 @@ public class PackageManagerService extends IPackageManager.Stub {
* which are (in order) {@code numberOfPackagesOptimized}, {@code numberOfPackagesSkipped}
* and {@code numberOfPackagesFailed}.
*/
- private int[] performDexOpt(List<PackageParser.Package> pkgs, boolean showDialog,
+ private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog,
String compilerFilter) {
int numberOfPackagesVisited = 0;
@@ -7382,6 +7378,19 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ // If the OTA updates a system app which was previously preopted to a non-preopted state
+ // the app might end up being verified at runtime. That's because by default the apps
+ // are verify-profile but for preopted apps there's no profile.
+ // Do a hacky check to ensure that if we have no profiles (a reasonable indication
+ // that before the OTA the app was preopted) the app gets compiled with a non-profile
+ // filter (by default interpret-only).
+ // Note that at this stage unused apps are already filtered.
+ if (isSystemApp(pkg) &&
+ DexFile.isProfileGuidedCompilerFilter(compilerFilter) &&
+ !Environment.getReferenceProfile(pkg.packageName).exists()) {
+ compilerFilter = getNonProfileGuidedCompilerFilter(compilerFilter);
+ }
+
// checkProfiles is false to avoid merging profiles during boot which
// might interfere with background compilation (b/28612421).
// Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
@@ -20440,12 +20449,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
}
}
- void onBeforeUserStartUninitialized(final int userId) {
- synchronized (mPackages) {
- if (mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
- return;
- }
- }
+ void onNewUserCreated(final int userId) {
mDefaultPermissionPolicy.grantDefaultPermissions(userId);
// If permission review for legacy apps is required, we represent
// dagerous permissions for such apps as always granted runtime
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 1a4e4e0ad80b..b94d0f0dbd1c 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -1185,8 +1185,8 @@ class ShortcutPackage extends ShortcutPackageItem {
private static void saveShortcut(XmlSerializer out, ShortcutInfo si, boolean forBackup)
throws IOException, XmlPullParserException {
if (forBackup) {
- if (!si.isPinned()) {
- return; // Backup only pinned icons.
+ if (!(si.isPinned() && si.isEnabled())) {
+ return; // We only backup pinned shortcuts that are enabled.
}
}
out.startTag(null, TAG_SHORTCUT);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index c6949e499021..730217db9501 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -355,6 +355,12 @@ public class ShortcutService extends IShortcutService.Stub {
@interface ShortcutOperation {
}
+ @GuardedBy("mLock")
+ private int mWtfCount = 0;
+
+ @GuardedBy("mLock")
+ private Exception mLastWtfStacktrace;
+
public ShortcutService(Context context) {
this(context, BackgroundThread.get().getLooper(), /*onyForPackgeManagerApis*/ false);
}
@@ -1438,6 +1444,10 @@ public class ShortcutService extends IShortcutService.Stub {
shortcut.getPackage().equals(shortcut.getActivity().getPackageName()),
"Cannot publish shortcut: activity " + shortcut.getActivity() + " does not"
+ " belong to package " + shortcut.getPackage());
+ Preconditions.checkState(
+ injectIsMainActivity(shortcut.getActivity(), shortcut.getUserId()),
+ "Cannot publish shortcut: activity " + shortcut.getActivity() + " is not"
+ + " main activity");
}
if (!forUpdate) {
@@ -2193,6 +2203,7 @@ public class ShortcutService extends IShortcutService.Stub {
launcherUserId, callingPackage, packageName, shortcutId, userId);
// "si == null" should suffice here, but check the flags too just to make sure.
if (si == null || !si.isEnabled() || !si.isAlive()) {
+ Log.e(TAG, "Shortcut " + shortcutId + " does not exist or disabled");
return null;
}
return si.getIntent();
@@ -2321,28 +2332,49 @@ public class ShortcutService extends IShortcutService.Stub {
*/
@VisibleForTesting
final PackageMonitor mPackageMonitor = new PackageMonitor() {
+
+ private boolean isUserUnlocked() {
+ return mUserManager.isUserUnlocked(getChangingUserId());
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // clearCallingIdentity is not needed normally, but need to do it for the unit test.
+ final long token = injectClearCallingIdentity();
+ try {
+ super.onReceive(context, intent);
+ } finally {
+ injectRestoreCallingIdentity(token);
+ }
+ }
+
@Override
public void onPackageAdded(String packageName, int uid) {
+ if (!isUserUnlocked()) return;
handlePackageAdded(packageName, getChangingUserId());
}
@Override
public void onPackageUpdateFinished(String packageName, int uid) {
+ if (!isUserUnlocked()) return;
handlePackageUpdateFinished(packageName, getChangingUserId());
}
@Override
public void onPackageRemoved(String packageName, int uid) {
+ if (!isUserUnlocked()) return;
handlePackageRemoved(packageName, getChangingUserId());
}
@Override
public void onPackageDataCleared(String packageName, int uid) {
+ if (!isUserUnlocked()) return;
handlePackageDataCleared(packageName, getChangingUserId());
}
@Override
public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ if (!isUserUnlocked()) return false;
handlePackageChanged(packageName, getChangingUserId());
return false; // We don't need to receive onSomePackagesChanged(), so just false.
}
@@ -2984,6 +3016,15 @@ public class ShortcutService extends IShortcutService.Stub {
dumpStatLS(pw, p, Stats.IS_ACTIVITY_ENABLED, "isActivityEnabled");
}
+ pw.println();
+ pw.print(" #Failures: ");
+ pw.println(mWtfCount);
+
+ if (mLastWtfStacktrace != null) {
+ pw.print(" Last failure stack trace: ");
+ pw.println(Log.getStackTraceString(mLastWtfStacktrace));
+ }
+
for (int i = 0; i < mUsers.size(); i++) {
pw.println();
mUsers.valueAt(i).dump(pw, " ");
@@ -3058,6 +3099,10 @@ public class ShortcutService extends IShortcutService.Stub {
case "--user":
if (takeUser) {
mUserId = UserHandle.parseUserArg(getNextArgRequired());
+ if (!mUserManager.isUserUnlocked(mUserId)) {
+ throw new CommandException(
+ "User " + mUserId + " is not running or locked");
+ }
break;
}
// fallthrough
@@ -3303,7 +3348,14 @@ public class ShortcutService extends IShortcutService.Stub {
}
// Injection point.
- void wtf(String message, Exception e) {
+ void wtf(String message, Throwable e) {
+ if (e == null) {
+ e = new RuntimeException("Stacktrace");
+ }
+ synchronized (mLock) {
+ mWtfCount++;
+ mLastWtfStacktrace = new Exception("Last failure was logged here:");
+ }
Slog.wtf(TAG, message, e);
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d750cbf17f66..68ccbdfceca9 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1799,6 +1799,18 @@ public class UserManagerService extends IUserManager.Stub {
mUserVersion = USER_VERSION;
Bundle restrictions = new Bundle();
+ try {
+ final String[] defaultFirstUserRestrictions = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_defaultFirstUserRestrictions);
+ for (String userRestriction : defaultFirstUserRestrictions) {
+ if (UserRestrictionsUtils.isValidRestriction(userRestriction)) {
+ restrictions.putBoolean(userRestriction, true);
+ }
+ }
+ } catch (Resources.NotFoundException e) {
+ Log.e(LOG_TAG, "Couldn't find resource: config_defaultFirstUserRestrictions", e);
+ }
+
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
}
@@ -2304,6 +2316,7 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.append(userId, restrictions);
}
+ mPm.onNewUserCreated(userId);
Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
@@ -2874,10 +2887,6 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mRestrictionsLock) {
applyUserRestrictionsLR(userId);
}
- UserInfo userInfo = getUserInfoNoChecks(userId);
- if (userInfo != null && !userInfo.isInitialized()) {
- mPm.onBeforeUserStartUninitialized(userId);
- }
}
maybeInitializeDemoMode(userId);
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index c082143e9b5f..04997570b89e 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -104,7 +104,8 @@ public class UserRestrictionsUtils {
UserManager.DISALLOW_RUN_IN_BACKGROUND,
UserManager.DISALLOW_DATA_ROAMING,
UserManager.DISALLOW_SET_USER_ICON,
- UserManager.DISALLOW_SET_WALLPAPER
+ UserManager.DISALLOW_SET_WALLPAPER,
+ UserManager.DISALLOW_OEM_UNLOCK
});
/**
@@ -138,7 +139,8 @@ public class UserRestrictionsUtils {
*/
private static final Set<String> IMMUTABLE_BY_OWNERS = Sets.newArraySet(
UserManager.DISALLOW_RECORD_AUDIO,
- UserManager.DISALLOW_WALLPAPER
+ UserManager.DISALLOW_WALLPAPER,
+ UserManager.DISALLOW_OEM_UNLOCK
);
/**
@@ -426,6 +428,7 @@ public class UserRestrictionsUtils {
newValue ? 1 : 0);
break;
case UserManager.DISALLOW_FACTORY_RESET:
+ case UserManager.DISALLOW_OEM_UNLOCK:
if (newValue) {
PersistentDataBlockManager manager = (PersistentDataBlockManager) context
.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index 2e32fe381722..c764833e08a6 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -134,7 +134,7 @@ public class ImmersiveModeConfirmation {
}
public void immersiveModeChangedLw(String pkg, boolean isImmersiveMode,
- boolean userSetupComplete) {
+ boolean userSetupComplete, boolean navBarEmpty) {
mHandler.removeMessages(H.SHOW);
if (isImmersiveMode) {
final boolean disabled = PolicyControl.disableImmersiveConfirmation(pkg);
@@ -144,6 +144,7 @@ public class ImmersiveModeConfirmation {
&& (DEBUG_SHOW_EVERY_TIME || !mConfirmed)
&& userSetupComplete
&& !mVrModeEnabled
+ && !navBarEmpty
&& !UserManager.isDeviceInDemoMode(mContext)) {
mHandler.sendEmptyMessageDelayed(H.SHOW, mShowDelayMs);
}
@@ -152,12 +153,13 @@ public class ImmersiveModeConfirmation {
}
}
- public boolean onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode) {
+ public boolean onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode,
+ boolean navBarEmpty) {
if (!isScreenOn && (time - mPanicTime < mPanicThresholdMs)) {
// turning the screen back on within the panic threshold
return mClingWindow == null;
}
- if (isScreenOn && inImmersiveMode) {
+ if (isScreenOn && inImmersiveMode && !navBarEmpty) {
// turning the screen off, remember if we were in immersive mode
mPanicTime = time;
} else {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 45322b3be85c..fbc727d348a3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -216,6 +216,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
+ static final int PENDING_KEY_NULL = -1;
+
// Controls navigation bar opacity depending on which workspace stacks are currently
// visible.
// Nav bar is always opaque when either the freeform stack or docked stack is visible.
@@ -410,6 +412,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
volatile boolean mRecentsVisible;
volatile boolean mTvPictureInPictureVisible;
+ // Used to hold the last user key used to wake the device. This helps us prevent up events
+ // from being passed to the foregrounded app without a corresponding down event
+ volatile int mPendingWakeKey = PENDING_KEY_NULL;
+
int mRecentAppsHeldModifiers;
boolean mLanguageSwitchKeyPressed;
@@ -1018,7 +1024,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Detect user pressing the power button in panic when an application has
// taken over the whole screen.
boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
- SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags));
+ SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
+ isNavBarEmpty(mLastSystemUiFlags));
if (panic) {
mHandler.post(mHiddenNavPanic);
}
@@ -5560,12 +5567,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// key to the application.
result = ACTION_PASS_TO_USER;
isWakeKey = false;
- } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
+
+ if (interactive) {
+ // If the screen is awake, but the button pressed was the one that woke the device
+ // then don't pass it to the application
+ if (keyCode == mPendingWakeKey && !down) {
+ result = 0;
+ }
+ // Reset the pending key
+ mPendingWakeKey = PENDING_KEY_NULL;
+ }
+ } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
// If we're currently dozing with the screen on and the keyguard showing, pass the key
// to the application but preserve its wake key status to make sure we still move
// from dozing to fully interactive if we would normally go from off to fully
// interactive.
result = ACTION_PASS_TO_USER;
+ // Since we're dispatching the input, reset the pending key
+ mPendingWakeKey = PENDING_KEY_NULL;
} else {
// When the screen is off and the key is not injected, determine whether
// to wake the device but don't pass the key to the application.
@@ -5573,6 +5592,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
isWakeKey = false;
}
+ // Cache the wake key on down event so we can also avoid sending the up event to the app
+ if (isWakeKey && down) {
+ mPendingWakeKey = keyCode;
+ }
}
// If the key would be handled globally, just return the result, don't worry about special
@@ -5949,7 +5972,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- if (shouldDispatchInputWhenNonInteractive()) {
+ if (shouldDispatchInputWhenNonInteractive(null)) {
return ACTION_PASS_TO_USER;
}
@@ -5964,7 +5987,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return 0;
}
- private boolean shouldDispatchInputWhenNonInteractive() {
+ private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
if (displayOff && !mHasFeatureWatch) {
@@ -5976,6 +5999,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return true;
}
+ // Watches handle BACK specially
+ if (mHasFeatureWatch
+ && event != null
+ && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
+ || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
+ return false;
+ }
+
// Send events to a dozing dream even if the screen is off since the dream
// is in control of the state of the screen.
IDreamManager dreamManager = getDreamManager();
@@ -7280,8 +7311,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private boolean areSystemNavigationKeysEnabled() {
- return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.SYSTEM_NAVIGATION_KEYS_ENABLED, 1) == 1;
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 1) == 1;
}
@Override
@@ -7560,7 +7591,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (win != null && oldImmersiveMode != newImmersiveMode) {
final String pkg = win.getOwningPackage();
mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
- isUserSetupComplete());
+ isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility()));
}
vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
@@ -7619,6 +7650,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
&& canHideNavigationBar();
}
+ private static boolean isNavBarEmpty(int systemUiFlags) {
+ final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME
+ | View.STATUS_BAR_DISABLE_BACK
+ | View.STATUS_BAR_DISABLE_RECENT);
+
+ return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
+ }
+
/**
* @return whether the navigation or status bar can be made translucent
*
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index ca92b907686c..552803f47652 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -29,6 +29,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Slog;
import android.view.KeyEvent;
@@ -942,6 +943,20 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
+ " token=" + tok.token);
}
pw.println(" mCurrentUserId=" + mCurrentUserId);
+ pw.println(" mIcons=");
+ for (String slot : mIcons.keySet()) {
+ pw.println(" ");
+ pw.print(slot);
+ pw.print(" -> ");
+ final StatusBarIcon icon = mIcons.get(slot);
+ pw.print(icon);
+ if (!TextUtils.isEmpty(icon.contentDescription)) {
+ pw.print(" \"");
+ pw.print(icon.contentDescription);
+ pw.print("\"");
+ }
+ pw.println();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index 6158c929a296..89e5e5833117 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -556,7 +556,7 @@ public final class TwilightService extends SystemService {
public void onChange(boolean selfChange) {
super.onChange(selfChange);
int value = Secure.getIntForUser(getContext().getContentResolver(),
- Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_LOCKED_OFF, mCurrentUser);
+ Secure.TWILIGHT_MODE, Secure.TWILIGHT_MODE_AUTO, mCurrentUser);
if (value == Secure.TWILIGHT_MODE_LOCKED_OFF) {
setLockedState(new TwilightState(false, 0));
} else if (value == Secure.TWILIGHT_MODE_LOCKED_ON) {
diff --git a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
index 77e8b1fa541f..40ee5d88fc8a 100644
--- a/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
+++ b/services/core/java/com/android/server/vr/EnabledComponentsObserver.java
@@ -246,7 +246,9 @@ public class EnabledComponentsObserver implements SettingChangeListener {
Intent queryIntent = new Intent(serviceName);
List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
queryIntent,
- PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA |
+ PackageManager.MATCH_DIRECT_BOOT_AWARE |
+ PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
userId);
if (installedServices != null) {
for (int i = 0, count = installedServices.size(); i < count; i++) {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 79fe18b77585..4b58a3b6a7aa 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -85,6 +85,7 @@ import android.view.WindowManager;
import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
import com.android.server.EventLogTags;
@@ -166,7 +167,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
* Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
* that the wallpaper has changed. The CREATE is triggered when there is no
* wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
- * everytime the wallpaper is changed.
+ * every time the wallpaper is changed.
*/
private class WallpaperObserver extends FileObserver {
@@ -175,7 +176,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
final File mWallpaperDir;
final File mWallpaperFile;
final File mWallpaperLockFile;
- final File mWallpaperInfoFile;
public WallpaperObserver(WallpaperData wallpaper) {
super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
@@ -185,7 +185,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
mWallpaper = wallpaper;
mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
mWallpaperLockFile = new File(mWallpaperDir, WALLPAPER_LOCK_ORIG);
- mWallpaperInfoFile = new File(mWallpaperDir, WALLPAPER_INFO);
}
private WallpaperData dataForEvent(boolean sysChanged, boolean lockChanged) {
@@ -943,10 +942,28 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
mLockWallpaperMap.remove(userId);
}
- void onUnlockUser(int userId) {
+ void onUnlockUser(final int userId) {
synchronized (mLock) {
if (mCurrentUserId == userId && mWaitingForUnlock) {
switchUser(userId, null);
+
+ // Make sure that the SELinux labeling of all the relevant files is correct.
+ // This corrects for mislabeling bugs that might have arisen from move-to
+ // operations involving the wallpaper files. This isn't timing-critical,
+ // so we do it in the background to avoid holding up the user unlock operation.
+ Runnable relabeler = new Runnable() {
+ @Override
+ public void run() {
+ final File wallpaperDir = getWallpaperDir(userId);
+ for (String filename : sPerUserFiles) {
+ File f = new File(wallpaperDir, filename);
+ if (f.exists()) {
+ SELinux.restorecon(f);
+ }
+ }
+ }
+ };
+ BackgroundThread.getHandler().post(relabeler);
}
}
}
@@ -1282,8 +1299,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
@Override
- public WallpaperInfo getWallpaperInfo() {
- int userId = UserHandle.getCallingUserId();
+ public WallpaperInfo getWallpaperInfo(int userId) {
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, true, "getWallpaperIdForUser", null);
synchronized (mLock) {
WallpaperData wallpaper = mWallpaperMap.get(userId);
if (wallpaper != null && wallpaper.connection != null) {
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 2b581562d680..3aefc08746bc 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -604,7 +604,7 @@ public class AppTransition implements Dump {
float scaleH = mTmpRect.height() / (float) appHeight;
Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
computePivot(mTmpRect.left, scaleW),
- computePivot(mTmpRect.right, scaleH));
+ computePivot(mTmpRect.top, scaleH));
scale.setInterpolator(mDecelerateInterpolator);
Animation alpha = new AlphaAnimation(0, 1);
@@ -1615,8 +1615,7 @@ public class AppTransition implements Dump {
if (isTransitionSet()) {
clear();
mNextAppTransitionType = NEXT_TRANSIT_TYPE_SCALE_UP;
- putDefaultNextAppTransitionCoordinates(startX, startY, startX + startWidth,
- startY + startHeight, null);
+ putDefaultNextAppTransitionCoordinates(startX, startY, startWidth, startHeight, null);
postAnimationCallback();
}
}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index e73649ddcf3c..f93e2ffa73be 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -388,8 +388,8 @@ public class DockedStackDividerController implements DimLayerUser {
inputMethodManagerInternal.hideCurrentInputMethod();
mImeHideRequested = true;
}
- } else {
- setMinimizedDockedStack(false);
+ } else if (setMinimizedDockedStack(false)) {
+ mService.mWindowPlacerLocked.performSurfacePlacement();
}
}
@@ -542,31 +542,43 @@ public class DockedStackDividerController implements DimLayerUser {
return;
}
- clearImeAdjustAnimation();
+ final boolean imeChanged = clearImeAdjustAnimation();
+ boolean minimizedChange = false;
if (minimizedDock) {
if (animate) {
startAdjustAnimation(0f, 1f);
} else {
- setMinimizedDockedStack(true);
+ minimizedChange |= setMinimizedDockedStack(true);
}
} else {
if (animate) {
startAdjustAnimation(1f, 0f);
} else {
- setMinimizedDockedStack(false);
+ minimizedChange |= setMinimizedDockedStack(false);
+ }
+ }
+ if (imeChanged || minimizedChange) {
+ if (imeChanged && !minimizedChange) {
+ Slog.d(TAG, "setMinimizedDockedStack: IME adjust changed due to minimizing,"
+ + " minimizedDock=" + minimizedDock
+ + " minimizedChange=" + minimizedChange);
}
+ mService.mWindowPlacerLocked.performSurfacePlacement();
}
}
- private void clearImeAdjustAnimation() {
+ private boolean clearImeAdjustAnimation() {
+ boolean changed = false;
final ArrayList<TaskStack> stacks = mDisplayContent.getStacks();
for (int i = stacks.size() - 1; i >= 0; --i) {
final TaskStack stack = stacks.get(i);
if (stack != null && stack.isAdjustedForIme()) {
stack.resetAdjustedForIme(true /* adjustBoundsNow */);
+ changed = true;
}
}
mAnimatingForIme = false;
+ return changed;
}
private void startAdjustAnimation(float from, float to) {
@@ -625,8 +637,21 @@ public class DockedStackDividerController implements DimLayerUser {
if (mDelayedImeWin != null) {
mDelayedImeWin.mWinAnimator.endDelayingAnimationStart();
}
+ // If the adjust status changed since this was posted, only notify
+ // the new states and don't animate.
+ long duration = 0;
+ if (mAdjustedForIme == adjustedForIme
+ && mAdjustedForDivider == adjustedForDivider) {
+ duration = IME_ADJUST_ANIM_DURATION;
+ } else {
+ Slog.w(TAG, "IME adjust changed while waiting for drawn:"
+ + " adjustedForIme=" + adjustedForIme
+ + " adjustedForDivider=" + adjustedForDivider
+ + " mAdjustedForIme=" + mAdjustedForIme
+ + " mAdjustedForDivider=" + mAdjustedForDivider);
+ }
notifyAdjustedForImeChanged(
- adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION);
+ mAdjustedForIme || mAdjustedForDivider, duration);
};
} else {
notifyAdjustedForImeChanged(
@@ -634,15 +659,10 @@ public class DockedStackDividerController implements DimLayerUser {
}
}
- private void setMinimizedDockedStack(boolean minimized) {
+ private boolean setMinimizedDockedStack(boolean minimized) {
final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
notifyDockedStackMinimizedChanged(minimized, 0);
- if (stack == null) {
- return;
- }
- if (stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f)) {
- mService.mWindowPlacerLocked.performSurfacePlacement();
- }
+ return stack != null && stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f);
}
private boolean isAnimationMaximizing() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4c79149f64d3..84788cfda4da 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -545,7 +545,7 @@ public class WindowManagerService extends IWindowManager.Stub
SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2);
int mRotation = 0;
- int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+ int mLastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean mAltOrientation = false;
private boolean mKeyguardWaitingForActivityDrawn;
@@ -3521,13 +3521,16 @@ public class WindowManagerService extends IWindowManager.Stub
// can re-appear and inflict its own orientation on us. Keep the
// orientation stable until this all settles down.
return mLastWindowForcedOrientation;
- } else if (mPolicy.isKeyguardLocked()
- && mLastKeyguardForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
- // Use the last orientation the keyguard forced while the display is frozen with the
- // keyguard locked.
+ } else if (mPolicy.isKeyguardLocked()) {
+ // Use the last orientation the while the display is frozen with the
+ // keyguard locked. This could be the keyguard forced orientation or
+ // from a SHOW_WHEN_LOCKED window. We don't want to check the show when
+ // locked window directly though as things aren't stable while
+ // the display is frozen, for example the window could be momentarily unavailable
+ // due to activity relaunch.
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
- + "return " + mLastKeyguardForcedOrientation);
- return mLastKeyguardForcedOrientation;
+ + "return " + mLastOrientation);
+ return mLastOrientation;
}
} else {
// TODO(multidisplay): Change to the correct display.
@@ -3657,12 +3660,12 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
- "No app is requesting an orientation, return " + mForcedAppOrientation);
+ "No app is requesting an orientation, return " + mLastOrientation);
// The next app has not been requested to be visible, so we keep the current orientation
// to prevent freezing/unfreezing the display too early unless we are in multi-window, in
// which we don't let the app customize the orientation unless it was the home task that
// is handled above.
- return inMultiWindow ? SCREEN_ORIENTATION_UNSPECIFIED : mForcedAppOrientation;
+ return inMultiWindow ? SCREEN_ORIENTATION_UNSPECIFIED : mLastOrientation;
}
@Override
@@ -3745,8 +3748,8 @@ public class WindowManagerService extends IWindowManager.Stub
long ident = Binder.clearCallingIdentity();
try {
int req = getOrientationLocked();
- if (req != mForcedAppOrientation) {
- mForcedAppOrientation = req;
+ if (req != mLastOrientation) {
+ mLastOrientation = req;
//send a message to Policy indicating orientation change to take
//action like disabling/enabling sensors etc.,
mPolicy.setCurrentOrientationLw(req);
@@ -6159,6 +6162,21 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ @Override
+ public Bitmap screenshotWallpaper() {
+ if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
+ "screenshotWallpaper()")) {
+ throw new SecurityException("Requires READ_FRAME_BUFFER permission");
+ }
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
+ return screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1, true, 1f,
+ Bitmap.Config.ARGB_8888, true);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ }
+ }
+
/**
* Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
* In portrait mode, it grabs the upper region of the screen based on the vertical dimension
@@ -6175,7 +6193,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void run() {
Bitmap bm = screenshotApplicationsInner(null, Display.DEFAULT_DISPLAY, -1, -1,
- true, 1f, Bitmap.Config.ARGB_8888);
+ true, 1f, Bitmap.Config.ARGB_8888, false);
try {
receiver.send(bm);
} catch (RemoteException e) {
@@ -6205,14 +6223,27 @@ public class WindowManagerService extends IWindowManager.Stub
try {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotApplications");
return screenshotApplicationsInner(appToken, displayId, width, height, false,
- frameScale, Bitmap.Config.RGB_565);
+ frameScale, Bitmap.Config.RGB_565, false);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
}
+ /**
+ * Takes a snapshot of the screen. In landscape mode this grabs the whole screen.
+ * In portrait mode, it grabs the full screenshot.
+ *
+ * @param displayId the Display to take a screenshot of.
+ * @param width the width of the target bitmap
+ * @param height the height of the target bitmap
+ * @param includeFullDisplay true if the screen should not be cropped before capture
+ * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
+ * @param config of the output bitmap
+ * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
+ */
Bitmap screenshotApplicationsInner(IBinder appToken, int displayId, int width, int height,
- boolean includeFullDisplay, float frameScale, Bitmap.Config config) {
+ boolean includeFullDisplay, float frameScale, Bitmap.Config config,
+ boolean wallpaperOnly) {
final DisplayContent displayContent;
synchronized(mWindowMap) {
displayContent = getDisplayContentLocked(displayId);
@@ -6239,7 +6270,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean screenshotReady;
int minLayer;
- if (appToken == null) {
+ if (appToken == null && !wallpaperOnly) {
screenshotReady = true;
minLayer = 0;
} else {
@@ -6279,11 +6310,20 @@ public class WindowManagerService extends IWindowManager.Stub
if (ws.mLayer >= aboveAppLayer) {
continue;
}
+ if (wallpaperOnly && !ws.mIsWallpaper) {
+ continue;
+ }
if (ws.mIsImWindow) {
if (!includeImeInScreenshot) {
continue;
}
} else if (ws.mIsWallpaper) {
+ // If this is the wallpaper layer and we're only looking for the wallpaper layer
+ // then the target window state is this one.
+ if (wallpaperOnly) {
+ appWin = ws;
+ }
+
if (appWin == null) {
// We have not ran across the target window yet, so it is probably
// behind the wallpaper. This can happen when the keyguard is up and
@@ -6331,8 +6371,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
- ws.isDisplayedLw() && winAnim.getShown()) {
+ final boolean foundTargetWs =
+ (ws.mAppToken != null && ws.mAppToken.token == appToken)
+ || (appWin != null && wallpaperOnly);
+ if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) {
screenshotReady = true;
}
@@ -6622,13 +6664,13 @@ public class WindowManagerService extends IWindowManager.Stub
// an orientation that has different metrics than it expected.
// eg. Portrait instead of Landscape.
- int rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation);
+ int rotation = mPolicy.rotationForOrientationLw(mLastOrientation, mRotation);
boolean altOrientation = !mPolicy.rotationHasCompatibleMetricsLw(
- mForcedAppOrientation, rotation);
+ mLastOrientation, rotation);
if (DEBUG_ORIENTATION) {
- Slog.v(TAG_WM, "Application requested orientation "
- + mForcedAppOrientation + ", got rotation " + rotation
+ Slog.v(TAG_WM, "Selected orientation "
+ + mLastOrientation + ", got rotation " + rotation
+ " which has " + (altOrientation ? "incompatible" : "compatible")
+ " metrics");
}
@@ -6642,7 +6684,7 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.v(TAG_WM,
"Rotation changed to " + rotation + (altOrientation ? " (alt)" : "")
+ " from " + mRotation + (mAltOrientation ? " (alt)" : "")
- + ", forceApp=" + mForcedAppOrientation);
+ + ", lastOrientation=" + mLastOrientation);
}
int oldRotation = mRotation;
@@ -10487,7 +10529,7 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mRotation="); pw.print(mRotation);
pw.print(" mAltOrientation="); pw.println(mAltOrientation);
pw.print(" mLastWindowForcedOrientation="); pw.print(mLastWindowForcedOrientation);
- pw.print(" mForcedAppOrientation="); pw.println(mForcedAppOrientation);
+ pw.print(" mLastOrientation="); pw.println(mLastOrientation);
pw.print(" mDeferredRotationPauseCount="); pw.println(mDeferredRotationPauseCount);
pw.print(" Animation settings: disabled="); pw.print(mAnimationsDisabled);
pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index c9123fd2227f..2120be1ec531 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -218,6 +218,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private static final String ATTR_SETUP_COMPLETE = "setup-complete";
private static final String ATTR_PROVISIONING_STATE = "provisioning-state";
private static final String ATTR_PERMISSION_POLICY = "permission-policy";
+ private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED =
+ "device-provisioning-config-applied";
private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer";
private static final String ATTR_APPLICATION_RESTRICTIONS_MANAGER
@@ -417,6 +419,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int mUserProvisioningState;
int mPermissionPolicy;
+ boolean mDeviceProvisioningConfigApplied = false;
+
final ArrayMap<ComponentName, ActiveAdmin> mAdminMap = new ArrayMap<>();
final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();
@@ -2173,6 +2177,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.attribute(null, ATTR_SETUP_COMPLETE,
Boolean.toString(true));
}
+ if (policy.mDeviceProvisioningConfigApplied) {
+ out.attribute(null, ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED,
+ Boolean.toString(true));
+ }
if (policy.mUserProvisioningState != DevicePolicyManager.STATE_USER_UNMANAGED) {
out.attribute(null, ATTR_PROVISIONING_STATE,
Integer.toString(policy.mUserProvisioningState));
@@ -2333,6 +2341,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (userSetupComplete != null && Boolean.toString(true).equals(userSetupComplete)) {
policy.mUserSetupComplete = true;
}
+ String deviceProvisioningConfigApplied = parser.getAttributeValue(null,
+ ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED);
+ if (deviceProvisioningConfigApplied != null
+ && Boolean.toString(true).equals(deviceProvisioningConfigApplied)) {
+ policy.mDeviceProvisioningConfigApplied = true;
+ }
String provisioningState = parser.getAttributeValue(null, ATTR_PROVISIONING_STATE);
if (!TextUtils.isEmpty(provisioningState)) {
policy.mUserProvisioningState = Integer.parseInt(provisioningState);
@@ -8975,6 +8989,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ @Override
+ public boolean isDeviceProvisioned() {
+ return !TextUtils.isEmpty(mInjector.systemPropertiesGet(PROPERTY_DEVICE_OWNER_PRESENT));
+ }
+
private void removePackageIfRequired(final String packageName, final int userId) {
if (!packageHasActiveAdmins(packageName, userId)) {
// Will not do anything if uninstall was not requested or was already started.
@@ -9041,4 +9060,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// restrictions.
pushUserRestrictions(userHandle);
}
+
+ @Override
+ public void setDeviceProvisioningConfigApplied() {
+ enforceManageUsers();
+ synchronized (this) {
+ DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
+ policy.mDeviceProvisioningConfigApplied = true;
+ saveSettingsLocked(UserHandle.USER_SYSTEM);
+ }
+ }
+
+ @Override
+ public boolean isDeviceProvisioningConfigApplied() {
+ enforceManageUsers();
+ synchronized (this) {
+ final DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
+ return policy.mDeviceProvisioningConfigApplied;
+ }
+ }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2236caebdc7c..a839373d787e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -51,6 +51,7 @@ import android.util.Slog;
import android.view.WindowManager;
import com.android.internal.R;
+import com.android.internal.app.NightDisplayController;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.SamplingProfilerIntegration;
import com.android.internal.os.ZygoteInit;
@@ -63,6 +64,7 @@ import com.android.server.clipboard.ClipboardService;
import com.android.server.connectivity.MetricsLoggerService;
import com.android.server.devicepolicy.DevicePolicyManagerService;
import com.android.server.display.DisplayManagerService;
+import com.android.server.display.NightDisplayService;
import com.android.server.dreams.DreamManagerService;
import com.android.server.fingerprint.FingerprintService;
import com.android.server.hdmi.HdmiControlService;
@@ -157,6 +159,8 @@ public final class SystemServer {
"com.google.android.clockwork.ThermalObserver";
private static final String WEAR_BLUETOOTH_SERVICE_CLASS =
"com.google.android.clockwork.bluetooth.WearBluetoothService";
+ private static final String WEAR_WIFI_MEDIATOR_SERVICE_CLASS =
+ "com.google.android.clockwork.wifi.WearWifiMediatorService";
private static final String WEAR_TIME_SERVICE_CLASS =
"com.google.android.clockwork.time.WearTimeService";
private static final String ACCOUNT_SERVICE_CLASS =
@@ -284,9 +288,6 @@ public final class SystemServer {
// we've defined it before booting further.
Build.ensureFingerprintProperty();
- // Initialize Environment for the system user.
- Environment.init();
-
// Within the system server, it is an error to access Environment paths without
// explicitly specifying a user.
Environment.setUserRequired(true);
@@ -998,6 +999,10 @@ public final class SystemServer {
mSystemServiceManager.startService(TwilightService.class);
+ if (NightDisplayController.isAvailable(context)) {
+ mSystemServiceManager.startService(NightDisplayService.class);
+ }
+
mSystemServiceManager.startService(JobSchedulerService.class);
mSystemServiceManager.startService(SoundTriggerService.class);
@@ -1160,6 +1165,7 @@ public final class SystemServer {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
mSystemServiceManager.startService(WEAR_BLUETOOTH_SERVICE_CLASS);
+ mSystemServiceManager.startService(WEAR_WIFI_MEDIATOR_SERVICE_CLASS);
if (!disableNonCoreServices) {
mSystemServiceManager.startService(WEAR_TIME_SERVICE_CLASS);
}
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
new file mode 100644
index 000000000000..53c2fd7ce543
--- /dev/null
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -0,0 +1,581 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.ip;
+
+import static android.system.OsConstants.*;
+
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructGroupReq;
+import android.system.StructTimeval;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import libcore.io.IoUtils;
+import libcore.util.HexEncoding;
+
+import java.io.FileDescriptor;
+import java.io.InterruptedIOException;
+import java.io.IOException;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+
+/**
+ * Basic IPv6 Router Advertisement Daemon.
+ *
+ * TODO:
+ *
+ * - Rewrite using Handler (and friends) so that AlarmManager can deliver
+ * "kick" messages when it's time to send a multicast RA.
+ *
+ * - Support transmitting MAX_URGENT_RTR_ADVERTISEMENTS number of empty
+ * RAs with zero default router lifetime when transitioning from an
+ * advertising state to a non-advertising state.
+ *
+ * @hide
+ */
+public class RouterAdvertisementDaemon {
+ private static final String TAG = RouterAdvertisementDaemon.class.getSimpleName();
+ private static final byte ICMPV6_ND_ROUTER_SOLICIT = asByte(133);
+ private static final byte ICMPV6_ND_ROUTER_ADVERT = asByte(134);
+ private static final int IPV6_MIN_MTU = 1280;
+ private static final int MIN_RA_HEADER_SIZE = 16;
+
+ // Summary of various timers and lifetimes.
+ private static final int MIN_RTR_ADV_INTERVAL_SEC = 300;
+ private static final int MAX_RTR_ADV_INTERVAL_SEC = 600;
+ // In general, router, prefix, and DNS lifetimes are all advised to be
+ // greater than or equal to 3 * MAX_RTR_ADV_INTERVAL. Here, we double
+ // that to allow for multicast packet loss.
+ //
+ // This MAX_RTR_ADV_INTERVAL_SEC and DEFAULT_LIFETIME are also consistent
+ // with the https://tools.ietf.org/html/rfc7772#section-4 discussion of
+ // "approximately 7 RAs per hour".
+ private static final int DEFAULT_LIFETIME = 6 * MAX_RTR_ADV_INTERVAL_SEC;
+ // From https://tools.ietf.org/html/rfc4861#section-10 .
+ private static final int MIN_DELAY_BETWEEN_RAS_SEC = 3;
+ // Both initial and final RAs, but also for changes in RA contents.
+ // From https://tools.ietf.org/html/rfc4861#section-10 .
+ private static final int MAX_URGENT_RTR_ADVERTISEMENTS = 5;
+
+ private static final int DAY_IN_SECONDS = 86_400;
+
+ private static final byte[] ALL_NODES = new byte[] {
+ (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+ };
+
+ private final String mIfName;
+ private final int mIfIndex;
+ private final byte[] mHwAddr;
+ private final InetSocketAddress mAllNodes;
+
+ // This lock is to protect the RA from being updated while being
+ // transmitted on another thread (multicast or unicast).
+ //
+ // TODO: This should be handled with a more RCU-like approach.
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private final byte[] mRA = new byte[IPV6_MIN_MTU];
+ @GuardedBy("mLock")
+ private int mRaLength;
+
+ private volatile FileDescriptor mSocket;
+ private volatile MulticastTransmitter mMulticastTransmitter;
+ private volatile UnicastResponder mUnicastResponder;
+
+ public static class RaParams {
+ public boolean hasDefaultRoute;
+ public int mtu;
+ public HashSet<IpPrefix> prefixes;
+ public HashSet<Inet6Address> dnses;
+
+ public RaParams() {
+ hasDefaultRoute = false;
+ mtu = IPV6_MIN_MTU;
+ prefixes = new HashSet<IpPrefix>();
+ dnses = new HashSet<Inet6Address>();
+ }
+
+ public RaParams(RaParams other) {
+ hasDefaultRoute = other.hasDefaultRoute;
+ mtu = other.mtu;
+ prefixes = (HashSet) other.prefixes.clone();
+ dnses = (HashSet) other.dnses.clone();
+ }
+ }
+
+
+ public RouterAdvertisementDaemon(String ifname, int ifindex, byte[] hwaddr) {
+ mIfName = ifname;
+ mIfIndex = ifindex;
+ mHwAddr = hwaddr;
+ mAllNodes = new InetSocketAddress(getAllNodesForScopeId(mIfIndex), 0);
+ }
+
+ public void buildNewRa(RaParams params) {
+ if (params == null || params.prefixes.isEmpty()) {
+ // No RA to be served at this time.
+ clearRa();
+ return;
+ }
+
+ if (params.mtu < IPV6_MIN_MTU) {
+ params.mtu = IPV6_MIN_MTU;
+ }
+
+ final ByteBuffer ra = ByteBuffer.wrap(mRA);
+ ra.order(ByteOrder.BIG_ENDIAN);
+
+ synchronized (mLock) {
+ try {
+ putHeader(ra, params.hasDefaultRoute);
+ putSlla(ra, mHwAddr);
+ // https://tools.ietf.org/html/rfc5175#section-4 says:
+ //
+ // "MUST NOT be added to a Router Advertisement message
+ // if no flags in the option are set."
+ //
+ // putExpandedFlagsOption(ra);
+ putMtu(ra, params.mtu);
+ for (IpPrefix ipp : params.prefixes) {
+ putPio(ra, ipp);
+ }
+ if (params.dnses.size() > 0) {
+ putRdnss(ra, params.dnses);
+ }
+ mRaLength = ra.position();
+ } catch (BufferOverflowException e) {
+ Log.e(TAG, "Could not construct new RA: " + e);
+ mRaLength = 0;
+ return;
+ }
+ }
+
+ maybeNotifyMulticastTransmitter();
+ }
+
+ public boolean start() {
+ if (!createSocket()) {
+ return false;
+ }
+
+ mMulticastTransmitter = new MulticastTransmitter();
+ mMulticastTransmitter.start();
+
+ mUnicastResponder = new UnicastResponder();
+ mUnicastResponder.start();
+
+ return true;
+ }
+
+ public void stop() {
+ closeSocket();
+ mMulticastTransmitter = null;
+ mUnicastResponder = null;
+ }
+
+ private void clearRa() {
+ boolean notifySocket;
+ synchronized (mLock) {
+ notifySocket = (mRaLength != 0);
+ mRaLength = 0;
+ }
+ if (notifySocket) {
+ maybeNotifyMulticastTransmitter();
+ }
+ }
+
+ private void maybeNotifyMulticastTransmitter() {
+ final MulticastTransmitter m = mMulticastTransmitter;
+ if (m != null) {
+ m.hup();
+ }
+ }
+
+ private static Inet6Address getAllNodesForScopeId(int scopeId) {
+ try {
+ return Inet6Address.getByAddress("ff02::1", ALL_NODES, scopeId);
+ } catch (UnknownHostException uhe) {
+ Log.wtf(TAG, "Failed to construct ff02::1 InetAddress: " + uhe);
+ return null;
+ }
+ }
+
+ private static byte asByte(int value) { return (byte) value; }
+ private static short asShort(int value) { return (short) value; }
+
+ private static void putHeader(ByteBuffer ra, boolean hasDefaultRoute) {
+ /**
+ Router Advertisement Message Format
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Cur Hop Limit |M|O|H|Prf|P|R|R| Router Lifetime |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reachable Time |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Retrans Timer |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options ...
+ +-+-+-+-+-+-+-+-+-+-+-+-
+ */
+ final byte DEFAULT_HOPLIMIT = 64;
+ ra.put(ICMPV6_ND_ROUTER_ADVERT)
+ .put(asByte(0))
+ .putShort(asShort(0))
+ .put(DEFAULT_HOPLIMIT)
+ // RFC 4191 "high" preference, iff. advertising a default route.
+ .put(hasDefaultRoute ? asByte(0x08) : asByte(0))
+ .putShort(hasDefaultRoute ? asShort(DEFAULT_LIFETIME) : asShort(0))
+ .putInt(0)
+ .putInt(0);
+ }
+
+ private static void putSlla(ByteBuffer ra, byte[] slla) {
+ /**
+ Source/Target Link-layer Address
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Link-Layer Address ...
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ if (slla == null || slla.length != 6) {
+ // Only IEEE 802.3 6-byte addresses are supported.
+ return;
+ }
+ final byte ND_OPTION_SLLA = 1;
+ final byte SLLA_NUM_8OCTETS = 1;
+ ra.put(ND_OPTION_SLLA)
+ .put(SLLA_NUM_8OCTETS)
+ .put(slla);
+ }
+
+ private static void putExpandedFlagsOption(ByteBuffer ra) {
+ /**
+ Router Advertisement Expanded Flags Option
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Bit fields available ..
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ... for assignment |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+ final byte ND_OPTION_EFO = 26;
+ final byte EFO_NUM_8OCTETS = 1;
+
+ ra.put(ND_OPTION_EFO)
+ .put(EFO_NUM_8OCTETS)
+ .putShort(asShort(0))
+ .putInt(0);
+ }
+
+ private static void putMtu(ByteBuffer ra, int mtu) {
+ /**
+ MTU
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | MTU |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ final byte ND_OPTION_MTU = 5;
+ final byte MTU_NUM_8OCTETS = 1;
+ ra.put(ND_OPTION_MTU)
+ .put(MTU_NUM_8OCTETS)
+ .putShort(asShort(0))
+ .putInt(mtu);
+ }
+
+ private static void putPio(ByteBuffer ra, IpPrefix ipp) {
+ /**
+ Prefix Information
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Prefix Length |L|A| Reserved1 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Valid Lifetime |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Preferred Lifetime |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved2 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Prefix +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ final int prefixLength = ipp.getPrefixLength();
+ if (prefixLength != 64) {
+ return;
+ }
+ final byte ND_OPTION_PIO = 3;
+ final byte PIO_NUM_8OCTETS = 4;
+
+ final byte[] addr = ipp.getAddress().getAddress();
+ ra.put(ND_OPTION_PIO)
+ .put(PIO_NUM_8OCTETS)
+ .put(asByte(prefixLength))
+ .put(asByte(0xc0)) // L&A set
+ .putInt(DEFAULT_LIFETIME)
+ .putInt(DEFAULT_LIFETIME)
+ .putInt(0)
+ .put(addr);
+ }
+
+ private static void putRio(ByteBuffer ra, IpPrefix ipp) {
+ /**
+ Route Information Option
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Prefix Length |Resvd|Prf|Resvd|
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Route Lifetime |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Prefix (Variable Length) |
+ . .
+ . .
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ final int prefixLength = ipp.getPrefixLength();
+ if (prefixLength > 64) {
+ return;
+ }
+ final byte ND_OPTION_RIO = 24;
+ final byte RIO_NUM_8OCTETS = asByte(
+ (prefixLength == 0) ? 1 : (prefixLength <= 8) ? 2 : 3);
+
+ final byte[] addr = ipp.getAddress().getAddress();
+ ra.put(ND_OPTION_RIO)
+ .put(RIO_NUM_8OCTETS)
+ .put(asByte(prefixLength))
+ .put(asByte(0x18))
+ .putInt(DEFAULT_LIFETIME);
+
+ // Rely upon an IpPrefix's address being properly zeroed.
+ if (prefixLength > 0) {
+ ra.put(addr, 0, (prefixLength <= 64) ? 8 : 16);
+ }
+ }
+
+ private static void putRdnss(ByteBuffer ra, Set<Inet6Address> dnses) {
+ /**
+ Recursive DNS Server (RDNSS) Option
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Lifetime |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ : Addresses of IPv6 Recursive DNS Servers :
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+ final byte ND_OPTION_RDNSS = 25;
+ final byte RDNSS_NUM_8OCTETS = asByte(dnses.size() * 2 + 1);
+ ra.put(ND_OPTION_RDNSS)
+ .put(RDNSS_NUM_8OCTETS)
+ .putShort(asShort(0))
+ .putInt(DEFAULT_LIFETIME);
+
+ for (Inet6Address dns : dnses) {
+ ra.put(dns.getAddress());
+ }
+ }
+
+ private boolean createSocket() {
+ final int SEND_TIMEOUT_MS = 300;
+
+ try {
+ mSocket = Os.socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ // Setting SNDTIMEO is purely for defensive purposes.
+ Os.setsockoptTimeval(
+ mSocket, SOL_SOCKET, SO_SNDTIMEO, StructTimeval.fromMillis(SEND_TIMEOUT_MS));
+ Os.setsockoptIfreq(mSocket, SOL_SOCKET, SO_BINDTODEVICE, mIfName);
+ NetworkUtils.protectFromVpn(mSocket);
+ NetworkUtils.setupRaSocket(mSocket, mIfIndex);
+ } catch (ErrnoException | IOException e) {
+ Log.e(TAG, "Failed to create RA daemon socket: " + e);
+ return false;
+ }
+
+ return true;
+ }
+
+ private void closeSocket() {
+ if (mSocket != null) {
+ IoUtils.closeQuietly(mSocket);
+ }
+ mSocket = null;
+ }
+
+ private boolean isSocketValid() {
+ final FileDescriptor s = mSocket;
+ return (s != null) && s.valid();
+ }
+
+ private boolean isSuitableDestination(InetSocketAddress dest) {
+ if (mAllNodes.equals(dest)) {
+ return true;
+ }
+
+ final InetAddress destip = dest.getAddress();
+ return (destip instanceof Inet6Address) &&
+ destip.isLinkLocalAddress() &&
+ (((Inet6Address) destip).getScopeId() == mIfIndex);
+ }
+
+ private void maybeSendRA(InetSocketAddress dest) {
+ if (dest == null || !isSuitableDestination(dest)) {
+ dest = mAllNodes;
+ }
+
+ try {
+ synchronized (mLock) {
+ if (mRaLength < MIN_RA_HEADER_SIZE) {
+ // No actual RA to send.
+ return;
+ }
+ Os.sendto(mSocket, mRA, 0, mRaLength, 0, dest);
+ }
+ Log.d(TAG, "RA sendto " + dest.getAddress().getHostAddress());
+ } catch (ErrnoException | SocketException e) {
+ if (isSocketValid()) {
+ Log.e(TAG, "sendto error: " + e);
+ }
+ }
+ }
+
+ private final class UnicastResponder extends Thread {
+ private final InetSocketAddress solicitor = new InetSocketAddress();
+ // The recycled buffer for receiving Router Solicitations from clients.
+ // If the RS is larger than IPV6_MIN_MTU the packets are truncated.
+ // This is fine since currently only byte 0 is examined anyway.
+ private final byte mSolication[] = new byte[IPV6_MIN_MTU];
+
+ @Override
+ public void run() {
+ while (isSocketValid()) {
+ try {
+ // Blocking receive.
+ final int rval = Os.recvfrom(
+ mSocket, mSolication, 0, mSolication.length, 0, solicitor);
+ // Do the least possible amount of validation.
+ if (rval < 1 || mSolication[0] != ICMPV6_ND_ROUTER_SOLICIT) {
+ continue;
+ }
+ } catch (ErrnoException | SocketException e) {
+ if (isSocketValid()) {
+ Log.e(TAG, "recvfrom error: " + e);
+ }
+ continue;
+ }
+
+ maybeSendRA(solicitor);
+ }
+ }
+ }
+
+ // TODO: Consider moving this to run on a provided Looper as a Handler,
+ // with WakeupMessage-style messages providing the timer driven input.
+ private final class MulticastTransmitter extends Thread {
+ private final Random mRandom = new Random();
+ private final AtomicInteger mUrgentAnnouncements = new AtomicInteger(0);
+
+ @Override
+ public void run() {
+ while (isSocketValid()) {
+ try {
+ Thread.sleep(getNextMulticastTransmitDelayMs());
+ } catch (InterruptedException ignored) {
+ // Stop sleeping, immediately send an RA, and continue.
+ }
+
+ maybeSendRA(mAllNodes);
+ }
+ }
+
+ public void hup() {
+ // Set to one fewer that the desired number, because as soon as
+ // the thread interrupt is processed we immediately send an RA
+ // and mUrgentAnnouncements is not examined until the subsequent
+ // sleep interval computation (i.e. this way we send 3 and not 4).
+ mUrgentAnnouncements.set(MAX_URGENT_RTR_ADVERTISEMENTS - 1);
+ interrupt();
+ }
+
+ private int getNextMulticastTransmitDelaySec() {
+ synchronized (mLock) {
+ if (mRaLength < MIN_RA_HEADER_SIZE) {
+ // No actual RA to send; just sleep for 1 day.
+ return DAY_IN_SECONDS;
+ }
+ }
+
+ final int urgentPending = mUrgentAnnouncements.getAndDecrement();
+ if (urgentPending > 0) {
+ return MIN_DELAY_BETWEEN_RAS_SEC;
+ }
+
+ return MIN_RTR_ADV_INTERVAL_SEC + mRandom.nextInt(
+ MAX_RTR_ADV_INTERVAL_SEC - MIN_RTR_ADV_INTERVAL_SEC);
+ }
+
+ private long getNextMulticastTransmitDelayMs() {
+ return 1000 * (long) getNextMulticastTransmitDelaySec();
+ }
+ }
+}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index 04049a17e6ce..c351e738a04f 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -55,6 +55,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.MediaStore;
import android.provider.Settings;
+import android.util.KeyValueListParser;
import android.util.Slog;
import com.android.internal.os.BackgroundThread;
import com.android.internal.R;
@@ -75,15 +76,17 @@ public class RetailDemoModeService extends SystemService {
private static final String TAG = RetailDemoModeService.class.getSimpleName();
private static final String DEMO_USER_NAME = "Demo";
- private static final String ACTION_RESET_DEMO = "com.android.server.am.ACTION_RESET_DEMO";
+ private static final String ACTION_RESET_DEMO =
+ "com.android.server.retaildemo.ACTION_RESET_DEMO";
private static final int MSG_TURN_SCREEN_ON = 0;
private static final int MSG_INACTIVITY_TIME_OUT = 1;
private static final int MSG_START_NEW_SESSION = 2;
private static final long SCREEN_WAKEUP_DELAY = 2500;
- private static final long USER_INACTIVITY_TIMEOUT = 30000;
- private static final long WARNING_DIALOG_TIMEOUT = 6000;
+ private static final long USER_INACTIVITY_TIMEOUT_MIN = 10000;
+ private static final long USER_INACTIVITY_TIMEOUT_DEFAULT = 30000;
+ private static final long WARNING_DIALOG_TIMEOUT_DEFAULT = 6000;
private static final long MILLIS_PER_SECOND = 1000;
private static final int[] VOLUME_STREAMS_TO_MUTE = {
@@ -97,6 +100,8 @@ public class RetailDemoModeService extends SystemService {
boolean mDeviceInDemoMode = false;
int mCurrentUserId = UserHandle.USER_SYSTEM;
+ long mUserInactivityTimeout;
+ long mWarningDialogTimeout;
private ActivityManagerService mAms;
private ActivityManagerInternal mAmi;
private AudioManager mAudioManager;
@@ -180,9 +185,79 @@ public class RetailDemoModeService extends SystemService {
}
}
+ private class SettingsObserver extends ContentObserver {
+
+ private final static String KEY_USER_INACTIVITY_TIMEOUT = "user_inactivity_timeout_ms";
+ private final static String KEY_WARNING_DIALOG_TIMEOUT = "warning_dialog_timeout_ms";
+
+ private final Uri mDeviceDemoModeUri = Settings.Global
+ .getUriFor(Settings.Global.DEVICE_DEMO_MODE);
+ private final Uri mDeviceProvisionedUri = Settings.Global
+ .getUriFor(Settings.Global.DEVICE_PROVISIONED);
+ private final Uri mRetailDemoConstantsUri = Settings.Global
+ .getUriFor(Settings.Global.RETAIL_DEMO_MODE_CONSTANTS);
+
+ private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+ public SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ public void register() {
+ ContentResolver cr = getContext().getContentResolver();
+ cr.registerContentObserver(mDeviceDemoModeUri, false, this, UserHandle.USER_SYSTEM);
+ cr.registerContentObserver(mDeviceProvisionedUri, false, this, UserHandle.USER_SYSTEM);
+ cr.registerContentObserver(mRetailDemoConstantsUri, false, this,
+ UserHandle.USER_SYSTEM);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (mRetailDemoConstantsUri.equals(uri)) {
+ refreshTimeoutConstants();
+ return;
+ }
+ if (mDeviceDemoModeUri.equals(uri)) {
+ mDeviceInDemoMode = UserManager.isDeviceInDemoMode(getContext());
+ if (mDeviceInDemoMode) {
+ mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
+ } else if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+ }
+ // If device is provisioned and left demo mode - run the cleanup in demo folder
+ if (!mDeviceInDemoMode && isDeviceProvisioned()) {
+ // Run on the bg thread to not block the fg thread
+ BackgroundThread.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ if (!deletePreloadsFolderContents()) {
+ Slog.w(TAG, "Failed to delete preloads folder contents");
+ }
+ }
+ });
+ }
+ }
+
+ private void refreshTimeoutConstants() {
+ try {
+ mParser.setString(Settings.Global.getString(getContext().getContentResolver(),
+ Settings.Global.RETAIL_DEMO_MODE_CONSTANTS));
+ } catch (IllegalArgumentException exc) {
+ Slog.e(TAG, "Invalid string passed to KeyValueListParser");
+ // Consuming the exception to fall back to default values.
+ }
+ mWarningDialogTimeout = mParser.getLong(KEY_WARNING_DIALOG_TIMEOUT,
+ WARNING_DIALOG_TIMEOUT_DEFAULT);
+ mUserInactivityTimeout = mParser.getLong(KEY_USER_INACTIVITY_TIMEOUT,
+ USER_INACTIVITY_TIMEOUT_DEFAULT);
+ mUserInactivityTimeout = Math.max(mUserInactivityTimeout, USER_INACTIVITY_TIMEOUT_MIN);
+ }
+ }
+
private void showInactivityCountdownDialog() {
UserInactivityCountdownDialog dialog = new UserInactivityCountdownDialog(getContext(),
- WARNING_DIALOG_TIMEOUT, MILLIS_PER_SECOND);
+ mWarningDialogTimeout, MILLIS_PER_SECOND);
dialog.setNegativeButtonClickListener(null);
dialog.setPositiveButtonClickListener(new DialogInterface.OnClickListener() {
@Override
@@ -246,13 +321,15 @@ public class RetailDemoModeService extends SystemService {
private void setupDemoUser(UserInfo userInfo) {
UserManager um = getUserManager();
UserHandle user = UserHandle.of(userInfo.id);
- LockPatternUtils lockPatternUtils = new LockPatternUtils(getContext());
- lockPatternUtils.setLockScreenDisabled(true, userInfo.id);
um.setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
um.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
um.setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
um.setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
um.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
+ um.setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
+ // Disallow rebooting in safe mode - controlled by user 0
+ getUserManager().setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true,
+ UserHandle.SYSTEM);
Settings.Secure.putIntForUser(getContext().getContentResolver(),
Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
Settings.Secure.putIntForUser(getContext().getContentResolver(),
@@ -308,49 +385,13 @@ public class RetailDemoModeService extends SystemService {
return mAudioManager;
}
- private void registerSettingsChangeObserver() {
- final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
- final Uri deviceProvisionedUri = Settings.Global.getUriFor(
- Settings.Global.DEVICE_PROVISIONED);
- final ContentResolver cr = getContext().getContentResolver();
- final ContentObserver deviceDemoModeSettingObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange, Uri uri, int userId) {
- if (deviceDemoModeUri.equals(uri)) {
- mDeviceInDemoMode = UserManager.isDeviceInDemoMode(getContext());
- if (mDeviceInDemoMode) {
- mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
- } else if (mWakeLock.isHeld()) {
- mWakeLock.release();
- }
- }
- // If device is provisioned and left demo mode - run the cleanup in demo folder
- if (!mDeviceInDemoMode && isDeviceProvisioned()) {
- // Run on the bg thread to not block the fg thread
- BackgroundThread.getHandler().post(new Runnable() {
- @Override
- public void run() {
- if (!deleteDemoFolderContents()) {
- Slog.w(TAG, "Failed to delete demo folder contents");
- }
- }
- });
- }
- }
- };
- cr.registerContentObserver(deviceDemoModeUri, false, deviceDemoModeSettingObserver,
- UserHandle.USER_SYSTEM);
- cr.registerContentObserver(deviceProvisionedUri, false, deviceDemoModeSettingObserver,
- UserHandle.USER_SYSTEM);
- }
-
private boolean isDeviceProvisioned() {
return Settings.Global.getInt(
getContext().getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
}
- private boolean deleteDemoFolderContents() {
- final File dir = Environment.getDataPreloadsDemoDirectory();
+ private boolean deletePreloadsFolderContents() {
+ final File dir = Environment.getDataPreloadsDirectory();
Slog.i(TAG, "Deleting contents of " + dir);
return FileUtils.deleteContents(dir);
}
@@ -431,7 +472,9 @@ public class RetailDemoModeService extends SystemService {
mDeviceInDemoMode = true;
mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
}
- registerSettingsChangeObserver();
+ SettingsObserver settingsObserver = new SettingsObserver(mHandler);
+ settingsObserver.register();
+ settingsObserver.refreshTimeoutConstants();
registerBroadcastReceiver();
}
@@ -455,6 +498,9 @@ public class RetailDemoModeService extends SystemService {
mAmi.updatePersistentConfigurationForUser(getSystemUsersConfiguration(), userId);
turnOffAllFlashLights();
muteVolumeStreams();
+ // Disable lock screen for demo users.
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(getContext());
+ lockPatternUtils.setLockScreenDisabled(true, userId);
mNm.notifyAsUser(TAG, 1, createResetNotification(), UserHandle.of(userId));
synchronized (mActivityLock) {
@@ -491,7 +537,7 @@ public class RetailDemoModeService extends SystemService {
}
}
mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
- mHandler.sendEmptyMessageDelayed(MSG_INACTIVITY_TIME_OUT, USER_INACTIVITY_TIMEOUT);
+ mHandler.sendEmptyMessageDelayed(MSG_INACTIVITY_TIME_OUT, mUserInactivityTimeout);
}
};
}
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index ba77b03c5e73..f2a93155d3f5 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -1040,6 +1040,8 @@ public class ConnectivityServiceTest extends AndroidTestCase {
enum CallbackState {
NONE,
AVAILABLE,
+ NETWORK_CAPABILITIES,
+ LINK_PROPERTIES,
LOSING,
LOST
}
@@ -1072,18 +1074,21 @@ public class ConnectivityServiceTest extends AndroidTestCase {
}
private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
- private void setLastCallback(CallbackState state, Network network, Object o) {
+ protected void setLastCallback(CallbackState state, Network network, Object o) {
mCallbacks.offer(new CallbackInfo(state, network, o));
}
+ @Override
public void onAvailable(Network network) {
setLastCallback(CallbackState.AVAILABLE, network, null);
}
+ @Override
public void onLosing(Network network, int maxMsToLive) {
setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
}
+ @Override
public void onLost(Network network) {
setLastCallback(CallbackState.LOST, network, null);
}
@@ -1744,6 +1749,67 @@ public class ConnectivityServiceTest extends AndroidTestCase {
defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
}
+ private class TestRequestUpdateCallback extends TestNetworkCallback {
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
+ setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
+ }
+
+ @Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
+ setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
+ }
+ }
+
+ @LargeTest
+ public void testRequestCallbackUpdates() throws Exception {
+ // File a network request for mobile.
+ final TestNetworkCallback cellNetworkCallback = new TestRequestUpdateCallback();
+ final NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ mCm.requestNetwork(cellRequest, cellNetworkCallback);
+
+ // Bring up the mobile network.
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+
+ // We should get onAvailable().
+ cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ // We should get onCapabilitiesChanged(), when the mobile network successfully validates.
+ cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+
+ // Update LinkProperties.
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName("foonet_data0");
+ mCellNetworkAgent.sendLinkProperties(lp);
+ // We should get onLinkPropertiesChanged().
+ cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+
+ // Register a garden variety default network request.
+ final TestNetworkCallback dfltNetworkCallback = new TestRequestUpdateCallback();
+ mCm.registerDefaultNetworkCallback(dfltNetworkCallback);
+ // Only onAvailable() is called; no other information is delivered.
+ dfltNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ dfltNetworkCallback.assertNoCallback();
+
+ // Request a NetworkCapabilities update; only the requesting callback is notified.
+ mCm.requestNetworkCapabilities(dfltNetworkCallback);
+ dfltNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+ dfltNetworkCallback.assertNoCallback();
+
+ // Request a LinkProperties update; only the requesting callback is notified.
+ mCm.requestLinkProperties(dfltNetworkCallback);
+ dfltNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ cellNetworkCallback.assertNoCallback();
+ dfltNetworkCallback.assertNoCallback();
+
+ mCm.unregisterNetworkCallback(dfltNetworkCallback);
+ mCm.unregisterNetworkCallback(cellNetworkCallback);
+ }
+
@SmallTest
public void testRequestBenchmark() throws Exception {
// Benchmarks connecting and switching performance in the presence of a large number of
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 3f6ab369f6bb..1be57bccbdb7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -38,6 +38,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.IUidObserver;
import android.app.usage.UsageStatsManagerInternal;
@@ -104,6 +105,7 @@ import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
+import java.util.function.Function;
public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected static final String TAG = "ShortcutManagerTest";
@@ -382,9 +384,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
@Override
void injectPostToHandler(Runnable r) {
- final long token = mContext.injectClearCallingIdentity();
- r.run();
- mContext.injectRestoreCallingIdentity(token);
+ runOnHandler(r);
}
@Override
@@ -400,9 +400,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
@Override
- void wtf(String message, Exception e) {
+ void wtf(String message, Throwable th) {
// During tests, WTF is fatal.
- fail(message + " exception: " + e);
+ fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th));
}
}
@@ -452,9 +452,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
@Override
void postToPackageMonitorHandler(Runnable r) {
- final long token = mContext.injectClearCallingIdentity();
- r.run();
- mContext.injectRestoreCallingIdentity(token);
+ runOnHandler(r);
}
@Override
@@ -473,13 +471,6 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
void injectRestoreCallingIdentity(long token) {
mInjectedCallingUid = (int) token;
}
-
- @Override
- protected void startShortcutIntentAsPublisher(@NonNull Intent intent,
- @NonNull String publisherPackage, Bundle startActivityOptions, int userId) {
- // Just forward to startActivityAsUser() during unit tests.
- mContext.startActivityAsUser(intent, startActivityOptions, UserHandle.of(userId));
- }
}
protected class LauncherAppsTestable extends LauncherApps {
@@ -497,6 +488,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
public static class ShortcutActivity3 extends Activity {
}
+ protected Looper mLooper;
+ protected Handler mHandler;
+
protected ServiceContext mServiceContext;
protected ClientContext mClientContext;
@@ -615,6 +609,10 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected final HashMap<String, LinkedHashMap<ComponentName, Integer>> mActivityMetadataResId
= new HashMap<>();
+ protected final Map<Integer, UserInfo> mUserInfos = new HashMap<>();
+ protected final Map<Integer, Boolean> mRunningUsers = new HashMap<>();
+ protected final Map<Integer, Boolean> mUnlockedUsers = new HashMap<>();
+
static {
QUERY_ALL.setQueryFlags(
ShortcutQuery.FLAG_GET_ALL_KINDS);
@@ -624,6 +622,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
protected void setUp() throws Exception {
super.setUp();
+ mLooper = Looper.getMainLooper();
+ mHandler = new Handler(mLooper);
+
mServiceContext = spy(new ServiceContext());
mClientContext = new ClientContext();
@@ -667,29 +668,48 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
deleteAllSavedFiles();
// Set up users.
- doAnswer(inv -> {
- assertSystem();
- return USER_INFO_0;
- }).when(mMockUserManager).getUserInfo(eq(USER_0));
-
- doAnswer(inv -> {
- assertSystem();
- return USER_INFO_10;
- }).when(mMockUserManager).getUserInfo(eq(USER_10));
-
- doAnswer(inv -> {
- assertSystem();
- return USER_INFO_11;
- }).when(mMockUserManager).getUserInfo(eq(USER_11));
-
- doAnswer(inv -> {
- assertSystem();
- return USER_INFO_P0;
- }).when(mMockUserManager).getUserInfo(eq(USER_P0));
-
- // User 0 is always running.
- when(mMockUserManager.isUserRunning(eq(USER_0))).thenAnswer(new AnswerIsUserRunning(true));
-
+ when(mMockUserManager.getUserInfo(anyInt())).thenAnswer(new AnswerWithSystemCheck<>(
+ inv -> mUserInfos.get((Integer) inv.getArguments()[0])));
+
+ mUserInfos.put(USER_0, USER_INFO_0);
+ mUserInfos.put(USER_10, USER_INFO_10);
+ mUserInfos.put(USER_11, USER_INFO_11);
+ mUserInfos.put(USER_P0, USER_INFO_P0);
+
+ // Set up isUserRunning and isUserUnlocked.
+ when(mMockUserManager.isUserRunning(anyInt())).thenAnswer(new AnswerWithSystemCheck<>(
+ inv -> mRunningUsers.get((Integer) inv.getArguments()[0])));
+
+ when(mMockUserManager.isUserUnlocked(anyInt())).thenAnswer(new AnswerWithSystemCheck<>(
+ inv -> {
+ final int userId = (Integer) inv.getArguments()[0];
+ return mRunningUsers.get(userId) && mUnlockedUsers.get(userId);
+ }));
+
+ // User 0 is always running
+ mRunningUsers.put(USER_0, true);
+ mRunningUsers.put(USER_10, false);
+ mRunningUsers.put(USER_11, false);
+ mRunningUsers.put(USER_P0, false);
+
+ // Unlock all users by default.
+ mUnlockedUsers.put(USER_0, true);
+ mUnlockedUsers.put(USER_10, true);
+ mUnlockedUsers.put(USER_11, true);
+ mUnlockedUsers.put(USER_P0, true);
+
+ // Set up mMockActivityManagerInternal.
+ // By default, startActivityAsPackage() will simply forward to startActivityAsUser().
+ doAnswer(new AnswerWithSystemCheck<>(inv -> {
+ mServiceContext.startActivityAsUser(
+ (Intent) inv.getArguments()[2],
+ (Bundle) inv.getArguments()[3],
+ UserHandle.of((Integer) inv.getArguments()[1]));
+ return ActivityManager.START_SUCCESS;
+ })).when(mMockActivityManagerInternal).startActivityAsPackage(anyString(), anyInt(),
+ any(Intent.class), any(Bundle.class));
+
+ // Set up resources
setUpAppResources();
// Start the service.
@@ -705,18 +725,18 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
/**
* Returns a boolean but also checks if the current UID is SYSTEM_UID.
*/
- protected class AnswerIsUserRunning implements Answer<Boolean> {
- protected final boolean mAnswer;
+ protected class AnswerWithSystemCheck<T> implements Answer<T> {
+ private final Function<InvocationOnMock, T> mChecker;
- protected AnswerIsUserRunning(boolean answer) {
- mAnswer = answer;
+ public AnswerWithSystemCheck(Function<InvocationOnMock, T> checker) {
+ mChecker = checker;
}
@Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- assertEquals("isUserRunning() must be called on SYSTEM UID.",
+ public T answer(InvocationOnMock invocation) throws Throwable {
+ assertEquals("Must be called on SYSTEM UID.",
Process.SYSTEM_UID, mInjectedCallingUid);
- return mAnswer;
+ return mChecker.apply(invocation);
}
}
@@ -805,7 +825,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
// Instantiate targets.
- mService = new ShortcutServiceTestable(mServiceContext, Looper.getMainLooper());
+ mService = new ShortcutServiceTestable(mServiceContext, mLooper);
mManager = new ShortcutManagerTestable(mClientContext, mService);
mInternal = LocalServices.getService(ShortcutServiceInternal.class);
@@ -844,6 +864,15 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
mLauncherAppsMap.clear();
}
+ protected void runOnHandler(Runnable r) {
+ final long token = mServiceContext.injectClearCallingIdentity();
+ try {
+ r.run();
+ } finally {
+ mServiceContext.injectRestoreCallingIdentity(token);
+ }
+ }
+
protected void addPackage(String packageName, int uid, int version) {
addPackage(packageName, uid, version, packageName);
}
@@ -1383,20 +1412,22 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
protected void assertShortcutNotLaunchable(@NonNull String packageName,
- @NonNull String shortcutId, int userId) {
+ @NonNull String shortcutId, int userId, Class<?> expectedException) {
reset(mServiceContext);
+ Exception thrown = null;
try {
mLauncherApps.startShortcut(packageName, shortcutId, null, null,
UserHandle.of(userId));
- } catch (SecurityException expected) {
- // security exception is okay.
- return;
+ } catch (Exception e) {
+ thrown = e;
}
// This shouldn't have been called.
verify(mServiceContext, times(0)).startActivityAsUser(
any(Intent.class),
any(Bundle.class),
any(UserHandle.class));
+ assertNotNull("Exception was not thrown", thrown);
+ assertEquals("Exception type different", expectedException, thrown.getClass());
}
protected void assertBitmapDirectories(int userId, String... expectedDirectories) {
@@ -1442,12 +1473,30 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
return new File(si.getBitmapPath()).getName();
}
+ /**
+ * @return all shortcuts stored internally for the caller. This reflects the *internal* view
+ * of shortcuts, which may be different from what {@link #getCallerVisibleShortcuts} would
+ * return, because getCallerVisibleShortcuts() will get shortcuts from the proper "front door"
+ * which performs some extra checks, like {@link ShortcutPackage#onRestored}.
+ */
protected List<ShortcutInfo> getCallerShortcuts() {
final ShortcutPackage p = mService.getPackageShortcutForTest(
getCallingPackage(), getCallingUserId());
return p == null ? null : p.getAllShortcutsForTest();
}
+ /**
+ * @return all shortcuts owned by caller that are actually visible via ShortcutManager.
+ * See also {@link #getCallerShortcuts}.
+ */
+ protected List<ShortcutInfo> getCallerVisibleShortcuts() {
+ final ArrayList<ShortcutInfo> ret = new ArrayList<>();
+ ret.addAll(mManager.getDynamicShortcuts());
+ ret.addAll(mManager.getPinnedShortcuts());
+ ret.addAll(mManager.getManifestShortcuts());
+ return ret;
+ }
+
protected ShortcutInfo getCallerShortcut(String shortcutId) {
return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId());
}
@@ -1658,6 +1707,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s5"), HANDLE_USER_P0);
});
+
+ // Note LAUNCHER_3 has allowBackup=false.
runWithCaller(LAUNCHER_3, USER_0, () -> {
mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4"), HANDLE_USER_0);
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 c7be3d93942e..bf6c2ff97bec 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -55,6 +55,7 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
@@ -63,6 +64,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.Manifest.permission;
+import android.app.ActivityManager;
+import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -74,6 +77,7 @@ import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
@@ -1670,18 +1674,32 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Get pinned shortcuts from launcher
runWithCaller(LAUNCHER_1, USER_0, () -> {
- // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists.
- assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(assertAllDisabled(
- mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
- /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser())))),
- "s2");
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+ // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists, and disabled.
+ assertWith(mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))
+ .haveIds("s2")
+ .areAllPinned()
+ .areAllNotWithKeyFieldsOnly()
+ .areAllDisabled();
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0,
+ ActivityNotFoundException.class);
- assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
- mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
- /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))),
- "s3", "s4");
- assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+ // Here, s4 is still enabled and launchable, but s3 is disabled.
+ assertWith(mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+ /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))
+ .haveIds("s3", "s4")
+ .areAllPinned()
+ .areAllNotWithKeyFieldsOnly()
+
+ .selectByIds("s3")
+ .areAllDisabled()
+
+ .revertToOriginalList()
+ .selectByIds("s4")
+ .areAllEnabled();
+
+ assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s3", USER_0,
+ ActivityNotFoundException.class);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s4", USER_0);
assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(assertAllEnabled(
@@ -2112,12 +2130,18 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10,
+ SecurityException.class);
});
runWithCaller(LAUNCHER_1, USER_P0, () -> {
assertShortcutIds(assertAllPinned(
@@ -2154,12 +2178,18 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10,
+ SecurityException.class);
});
runWithCaller(LAUNCHER_2, USER_P0, () -> {
assertShortcutIds(assertAllPinned(
@@ -2196,12 +2226,18 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10,
+ SecurityException.class);
});
runWithCaller(LAUNCHER_2, USER_10, () -> {
assertShortcutIds(assertAllPinned(
@@ -2261,19 +2297,27 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
"s1", "s2", "s3");
assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0,
+ ActivityNotFoundException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0,
+ ActivityNotFoundException.class);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10,
+ SecurityException.class);
});
runWithCaller(LAUNCHER_1, USER_P0, () -> {
assertShortcutIds(assertAllPinned(
@@ -2304,18 +2348,25 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0,
+ ActivityNotFoundException.class);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10,
+ SecurityException.class);
});
runWithCaller(LAUNCHER_2, USER_P0, () -> {
assertShortcutIds(assertAllPinned(
@@ -2345,19 +2396,27 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
"s1", "s3");
assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0,
+ ActivityNotFoundException.class);
assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s2", USER_0,
+ ActivityNotFoundException.class);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10,
+ SecurityException.class);
});
runWithCaller(LAUNCHER_2, USER_10, () -> {
assertShortcutIds(assertAllPinned(
@@ -2373,20 +2432,29 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
/* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
"s1", "s2", "s3");
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_0,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0,
+ SecurityException.class);
- assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s1", USER_0,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s2", USER_0,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s3", USER_0,
+ SecurityException.class);
assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10,
+ ActivityNotFoundException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10,
+ ActivityNotFoundException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10,
+ ActivityNotFoundException.class);
});
// Save & load and make sure we still have the same information.
@@ -2422,19 +2490,27 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
"s1", "s2", "s3");
assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0,
+ ActivityNotFoundException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0,
+ ActivityNotFoundException.class);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10,
+ SecurityException.class);
});
runWithCaller(LAUNCHER_1, USER_P0, () -> {
assertShortcutIds(assertAllPinned(
@@ -2465,18 +2541,25 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0,
+ ActivityNotFoundException.class);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10,
+ SecurityException.class);
});
runWithCaller(LAUNCHER_2, USER_P0, () -> {
assertShortcutIds(assertAllPinned(
@@ -2506,80 +2589,143 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
"s1", "s3");
assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0,
+ ActivityNotFoundException.class);
assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s2", USER_0,
+ ActivityNotFoundException.class);
assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
- assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10,
+ SecurityException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10,
+ SecurityException.class);
});
}
public void testStartShortcut() {
// Create some shortcuts.
- setCaller(CALLING_PACKAGE_1);
- final ShortcutInfo s1_1 = makeShortcut(
- "s1",
- "Title 1",
- makeComponent(ShortcutActivity.class),
- /* icon =*/ null,
- makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
- "key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ final ShortcutInfo s1_1 = makeShortcut(
+ "s1",
+ "Title 1",
+ makeComponent(ShortcutActivity.class),
+ /* icon =*/ null,
+ makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+ "key1", "val1", "nest", makeBundle("key", 123)),
+ /* rank */ 10);
- final ShortcutInfo s1_2 = makeShortcut(
- "s2",
- "Title 2",
- /* activity */ null,
- /* icon =*/ null,
- makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ final ShortcutInfo s1_2 = makeShortcut(
+ "s2",
+ "Title 2",
+ /* activity */ null,
+ /* icon =*/ null,
+ makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+ /* rank */ 12);
- assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
+ final ShortcutInfo s1_3 = makeShortcut("s3");
- setCaller(CALLING_PACKAGE_2);
- final ShortcutInfo s2_1 = makeShortcut(
- "s1",
- "ABC",
- makeComponent(ShortcutActivity.class),
- /* icon =*/ null,
- makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
- "key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
- assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
+ assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2, s1_3)));
+ });
- // Pin all.
- setCaller(LAUNCHER_1);
- mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
- list("s1", "s2"), getCallingUser());
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ final ShortcutInfo s2_1 = makeShortcut(
+ "s1",
+ "ABC",
+ makeComponent(ShortcutActivity.class),
+ /* icon =*/ null,
+ makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
+ "key1", "val1", "nest", makeBundle("key", 123)),
+ /* weight */ 10);
+ assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
+ });
- mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
- list("s1"), getCallingUser());
+ // Pin some.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+ list("s1", "s2"), getCallingUser());
+
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+ list("s1"), getCallingUser());
+ });
// Just to make it complicated, delete some.
- setCaller(CALLING_PACKAGE_1);
- mManager.removeDynamicShortcuts(list("s2"));
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ mManager.removeDynamicShortcuts(list("s2"));
+ });
- // intent and check.
- setCaller(LAUNCHER_1);
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ assertEquals(
+ ShortcutActivity2.class.getName(),
+ launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s1", USER_0)
+ .getComponent().getClassName());
+ assertEquals(
+ ShortcutActivity3.class.getName(),
+ launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s2", USER_0)
+ .getComponent().getClassName());
+ assertEquals(
+ ShortcutActivity.class.getName(),
+ launchShortcutAndGetIntent(CALLING_PACKAGE_2, "s1", USER_0)
+ .getComponent().getClassName());
- Intent intent;
- intent = launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s1", USER_0);
- assertEquals(ShortcutActivity2.class.getName(), intent.getComponent().getClassName());
+ assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+ assertShortcutNotLaunchable("no-such-package", "s2", USER_0,
+ ActivityNotFoundException.class);
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "xxxx", USER_0,
+ ActivityNotFoundException.class);
+ });
- intent = launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s2", USER_0);
- assertEquals(ShortcutActivity3.class.getName(), intent.getComponent().getClassName());
+ // LAUNCHER_1 is no longer the default launcher
+ setDefaultLauncherChecker((pkg, userId) -> false);
+
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ // Not the default launcher, but pinned shortcuts are still lauchable.
+ assertEquals(
+ ShortcutActivity2.class.getName(),
+ launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s1", USER_0)
+ .getComponent().getClassName());
+ assertEquals(
+ ShortcutActivity3.class.getName(),
+ launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s2", USER_0)
+ .getComponent().getClassName());
+ assertEquals(
+ ShortcutActivity.class.getName(),
+ launchShortcutAndGetIntent(CALLING_PACKAGE_2, "s1", USER_0)
+ .getComponent().getClassName());
+
+ // Not pinned, so not lauchable.
+ });
+
+ // Test inner errors.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ // Not launchable.
+ doAnswer(new AnswerWithSystemCheck<>(inv -> {
+ return ActivityManager.START_CLASS_NOT_FOUND;
+ })).when(mMockActivityManagerInternal).startActivityAsPackage(anyString(), anyInt(),
+ any(Intent.class), any(Bundle.class));
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_0,
+ ActivityNotFoundException.class);
+
+ // Still not launchable.
+ doAnswer(new AnswerWithSystemCheck<>(inv -> {
+ return ActivityManager.START_PERMISSION_DENIED;
+ })).when(mMockActivityManagerInternal).startActivityAsPackage(anyString(), anyInt(),
+ any(Intent.class), any(Bundle.class));
+ assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_0,
+ ActivityNotFoundException.class);
+ });
- intent = launchShortcutAndGetIntent(CALLING_PACKAGE_2, "s1", USER_0);
- assertEquals(ShortcutActivity.class.getName(), intent.getComponent().getClassName());
// TODO Check extra, etc
}
@@ -2843,8 +2989,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertCallbackNotReceived(c11_1);
// Work profile, now running.
- doAnswer(new AnswerIsUserRunning(false)).when(mMockUserManager).isUserRunning(anyInt());
- doAnswer(new AnswerIsUserRunning(true)).when(mMockUserManager).isUserRunning(eq(USER_P0));
+ mRunningUsers.clear();
+ mRunningUsers.put(USER_P0, true);
resetAll(all);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
@@ -2862,9 +3008,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertCallbackReceived(cP0_1, HANDLE_USER_P0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s4");
// Normal secondary user.
-
- doAnswer(new AnswerIsUserRunning(false)).when(mMockUserManager).isUserRunning(anyInt());
- doAnswer(new AnswerIsUserRunning(true)).when(mMockUserManager).isUserRunning(eq(USER_10));
+ mRunningUsers.clear();
+ mRunningUsers.put(USER_10, true);
resetAll(all);
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -3327,7 +3472,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -3344,7 +3489,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -3706,7 +3851,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertWith(getCallerShortcuts())
@@ -3746,7 +3891,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
uninstallPackage(USER_0, CALLING_PACKAGE_1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDeleteIntent(CALLING_PACKAGE_1, USER_0));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -3763,8 +3908,10 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
+ mRunningUsers.put(USER_10, true);
+
uninstallPackage(USER_10, CALLING_PACKAGE_2);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDeleteIntent(CALLING_PACKAGE_2, USER_10));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -3855,7 +4002,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDataClear(CALLING_PACKAGE_1, USER_0));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -3872,7 +4019,9 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mRunningUsers.put(USER_10, true);
+
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDataClear(CALLING_PACKAGE_2, USER_10));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -3892,12 +4041,14 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
public void testHandlePackageClearData_manifestRepublished() {
+ mRunningUsers.put(USER_10, true);
+
// Add two manifests and two dynamics.
addManifestShortcutResource(
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -3918,7 +4069,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
// Clear data
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDataClear(CALLING_PACKAGE_1, USER_10));
// Only manifest shortcuts will remain, and are no longer pinned.
@@ -3983,9 +4134,9 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
reset(c0);
reset(c10);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_10));
waitOnMainThread();
@@ -4006,7 +4157,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
updatePackageVersion(CALLING_PACKAGE_1, 1);
// Then send the broadcast, to only user-0.
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
waitOnMainThread();
@@ -4037,12 +4188,14 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// notification to the launcher.
mInjectedCurrentTimeMillis = START_TIME + 200;
- doAnswer(new AnswerIsUserRunning(true)).when(mMockUserManager).isUserRunning(eq(USER_10));
+ mRunningUsers.put(USER_10, true);
reset(c0);
reset(c10);
mService.handleUnlockUser(USER_10);
+ waitOnMainThread();
+
shortcuts = ArgumentCaptor.forClass(List.class);
verify(c0, times(0)).onShortcutsChanged(
eq(CALLING_PACKAGE_1),
@@ -4069,7 +4222,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
updatePackageVersion(CALLING_PACKAGE_2, 10);
// Then send the broadcast, to only user-0.
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_2, USER_0));
mService.handleUnlockUser(USER_10);
@@ -4093,7 +4246,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
updatePackageVersion(CALLING_PACKAGE_3, 100);
// Then send the broadcast, to only user-0.
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_3, USER_0));
mService.handleUnlockUser(USER_10);
@@ -4175,7 +4328,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Update the package.
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -4201,8 +4354,10 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
addManifestShortcutResource(ACTIVITY1, R.xml.shortcut_1);
addManifestShortcutResource(ACTIVITY2, R.xml.shortcut_1_alt);
+ mRunningUsers.put(USER_10, true);
+
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4234,7 +4389,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
// First, no changes.
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4257,7 +4412,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Disable activity 1
mEnabledActivityChecker = (activity, userId) -> !ACTIVITY1.equals(activity);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4277,7 +4432,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Re-enable activity 1.
// Manifest shortcuts will be re-published, but dynamic ones are not.
mEnabledActivityChecker = (activity, userId) -> true;
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4301,7 +4456,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// Disable activity 2
// Because "ms1-alt" and "s2" are both pinned, they will remain, but disabled.
mEnabledActivityChecker = (activity, userId) -> !ACTIVITY2.equals(activity);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageChangedIntent(CALLING_PACKAGE_1, USER_10));
runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
@@ -4364,7 +4519,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
setCaller(LAUNCHER_1, USER_0);
assertForLauncherCallback(mLauncherApps, () -> {
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageUpdateIntent(CALLING_PACKAGE_1, USER_0));
}).assertCallbackCalledForPackageAndUser(CALLING_PACKAGE_1, HANDLE_USER_0)
// Make sure the launcher gets callbacks.
@@ -4481,8 +4636,10 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_1));
assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_2));
- assertExistsAndShadow(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_1)));
- assertExistsAndShadow(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_2)));
+ assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+ PackageWithUser.of(USER_0, LAUNCHER_1)));
+ assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+ PackageWithUser.of(USER_0, LAUNCHER_2)));
assertNull(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
@@ -4490,90 +4647,98 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
installPackage(USER_0, CALLING_PACKAGE_1);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertShortcutIds(assertAllPinned(
- mManager.getPinnedShortcuts()),
- "s1", "s2");
+ assertWith(getCallerVisibleShortcuts())
+ .selectDynamic()
+ .isEmpty()
+
+ .revertToOriginalList()
+ .selectPinned()
+ .haveIds("s1", "s2");
});
installPackage(USER_0, LAUNCHER_1);
runWithCaller(LAUNCHER_1, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
- "s1");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
- /* empty, not restored */ );
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty, not restored */ );
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s1");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .isEmpty();
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
- assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+ assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+ .isEmpty();
});
installPackage(USER_0, CALLING_PACKAGE_2);
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertShortcutIds(assertAllPinned(
- mManager.getPinnedShortcuts()),
- "s1", "s2", "s3");
+ assertWith(getCallerVisibleShortcuts())
+ .selectDynamic()
+ .isEmpty()
+
+ .revertToOriginalList()
+ .selectPinned()
+ .haveIds("s1", "s2", "s3");
});
runWithCaller(LAUNCHER_1, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
- "s1");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s1", "s2");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* empty, not restored */ );
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s1");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s1", "s2");
- assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
+
+ assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+ .isEmpty();
});
// 3 shouldn't be backed up, so no pinned shortcuts.
installPackage(USER_0, CALLING_PACKAGE_3);
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertEquals(0, mManager.getPinnedShortcuts().size());
+ assertWith(getCallerVisibleShortcuts())
+ .isEmpty();
});
// Launcher on a different profile shouldn't be restored.
runWithCaller(LAUNCHER_1, USER_P0, () -> {
- assertEquals(0,
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)
- .size());
- assertEquals(0,
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)
- .size());
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* wasn't restored, so still empty */ );
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .isEmpty();
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .isEmpty();
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
});
// Package on a different profile, no restore.
installPackage(USER_P0, CALLING_PACKAGE_1);
runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertEquals(0, mManager.getPinnedShortcuts().size());
+ assertWith(getCallerVisibleShortcuts())
+ .isEmpty();
});
// Restore launcher 2 on user 0.
installPackage(USER_0, LAUNCHER_2);
runWithCaller(LAUNCHER_2, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
- "s2");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s2", "s3");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* wasn't restored, so still empty */ );
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s2");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s2", "s3");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
- assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+ assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+ .isEmpty();
});
@@ -4581,33 +4746,33 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
// make sure they still have the same result.
installPackage(USER_0, CALLING_PACKAGE_1);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertShortcutIds(assertAllPinned(
- mManager.getPinnedShortcuts()),
- "s1", "s2");
+ assertWith(getCallerVisibleShortcuts())
+ .areAllPinned()
+ .haveIds("s1", "s2");
});
installPackage(USER_0, LAUNCHER_1);
runWithCaller(LAUNCHER_1, USER_0, () -> {
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
- "s1");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
- "s1", "s2");
- assertShortcutIds(assertAllPinned(
- mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
- /* wasn't restored, so still empty */ );
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s1");
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .areAllPinned()
+ .haveIds("s1", "s2");
- assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
+
+ assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+ .isEmpty();
});
installPackage(USER_0, CALLING_PACKAGE_2);
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
- assertEquals(0, mManager.getDynamicShortcuts().size());
- assertShortcutIds(assertAllPinned(
- mManager.getPinnedShortcuts()),
- "s1", "s2", "s3");
+ assertWith(getCallerVisibleShortcuts())
+ .areAllPinned()
+ .haveIds("s1", "s2", "s3");
});
}
@@ -4928,6 +5093,112 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
});
}
+ public void testBackupAndRestore_disabled() {
+ prepareCrossProfileDataSet();
+
+ // Before doing backup & restore, disable s1.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ mManager.disableShortcuts(list("s1"));
+ });
+
+ backupAndRestore();
+
+ // Below is copied from checkBackupAndRestore_success.
+
+ // Make sure non-system user is not restored.
+ final ShortcutUser userP0 = mService.getUserShortcutsLocked(USER_P0);
+ assertEquals(0, userP0.getAllPackagesForTest().size());
+ assertEquals(0, userP0.getAllLaunchersForTest().size());
+
+ // Make sure only "allowBackup" apps are restored, and are shadow.
+ final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
+ assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_1));
+ assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_2));
+ assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+ PackageWithUser.of(USER_0, LAUNCHER_1)));
+ assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+ PackageWithUser.of(USER_0, LAUNCHER_2)));
+
+ assertNull(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
+ assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
+ assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_P0, LAUNCHER_1)));
+
+ installPackage(USER_0, CALLING_PACKAGE_1);
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerVisibleShortcuts())
+ .areAllEnabled() // disabled shortcuts shouldn't be restored.
+
+ .selectDynamic()
+ .isEmpty()
+
+ .revertToOriginalList()
+ .selectPinned()
+ // s1 is not restored.
+ .haveIds("s2");
+ });
+
+ installPackage(USER_0, LAUNCHER_1);
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ // Note, s1 was pinned by launcher 1, but was disabled, so isn't restored.
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+ .isEmpty();
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+ .isEmpty();
+
+ assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+ .isEmpty();
+
+ assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+ .isEmpty();
+ });
+ }
+
+
+ public void testBackupAndRestore_manifestNotRestored() {
+ // Publish two manifest shortcuts.
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_2);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(mServiceContext,
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+ // Pin from launcher 1.
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1", "ms2"), HANDLE_USER_0);
+ });
+
+ // Update and now ms2 is gone -> disabled.
+ addManifestShortcutResource(
+ new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+ R.xml.shortcut_1);
+ updatePackageVersion(CALLING_PACKAGE_1, 1);
+ mService.mPackageMonitor.onReceive(mServiceContext,
+ genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+ // Make sure the manifest shortcuts have been published.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertWith(getCallerShortcuts())
+ .areAllPinned()
+ .haveIds("ms1", "ms2")
+
+ .selectByIds("ms1")
+ .areAllManifest()
+ .areAllEnabled()
+
+ .revertToOriginalList()
+ .selectByIds("ms2")
+ .areAllNotManifest()
+ .areAllDisabled();
+ });
+
+ // Now do the regular backup & restore test.
+ // The existence of the manifest shortcuts shouldn't affect the result.
+ prepareCrossProfileDataSet();
+ backupAndRestore();
+ }
+
public void testSaveAndLoad_crossProfile() {
prepareCrossProfileDataSet();
@@ -5364,7 +5635,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5385,7 +5656,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_2, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5422,7 +5693,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_2, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5455,8 +5726,32 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
assertEmpty(mManager.getManifestShortcuts());
assertEmpty(mManager.getPinnedShortcuts());
});
+ // Send add broadcast, but the user is not running, so should be ignored.
+ mRunningUsers.put(USER_10, false);
+ mUnlockedUsers.put(USER_10, false);
+
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
+ runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+ assertEmpty(mManager.getManifestShortcuts());
+ assertEmpty(mManager.getPinnedShortcuts());
+ });
+
+ // Try again, but the user is locked, so still ignored.
+ mRunningUsers.put(USER_10, true);
+
+ mService.mPackageMonitor.onReceive(getTestContext(),
+ genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
+ runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+ assertEmpty(mManager.getManifestShortcuts());
+ assertEmpty(mManager.getPinnedShortcuts());
+ });
+
+ // Unlock the user, now it should work.
+ mUnlockedUsers.put(USER_10, true);
+
// Send PACKAGE_ADD broadcast to have Package 2 on user-10 publish manifest shortcuts.
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_10));
runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
@@ -5497,7 +5792,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
R.xml.shortcut_5_reverse);
updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
@@ -5525,7 +5820,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_2, ShortcutActivity2.class.getName()),
R.xml.shortcut_0);
updatePackageLastUpdateTime(CALLING_PACKAGE_2, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_2, USER_0));
// No manifest shortcuts, and pinned ones are disabled.
@@ -5556,7 +5851,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -5571,7 +5866,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -5586,7 +5881,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_3);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -5602,7 +5897,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_4);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5630,7 +5925,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5668,7 +5963,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_error_4);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Make sure 3, 4 and 5 still exist but disabled.
@@ -5716,7 +6011,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -5821,7 +6116,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -5918,7 +6213,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -5937,7 +6232,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1_disable);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Because shortcut 1 wasn't pinned, it'll just go away.
@@ -5958,7 +6253,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Only the valid one is published.
@@ -5981,7 +6276,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1_disable);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
// Because shortcut 1 was pinned, it'll still exist as pinned, but disabled.
@@ -6014,7 +6309,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2_duplicate);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6044,7 +6339,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6116,7 +6411,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6166,7 +6461,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(LAUNCHER_1, USER_0, () -> {
@@ -6177,7 +6472,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6259,7 +6554,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_5);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -6329,7 +6624,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(2, mManager.getManifestShortcuts().size());
@@ -6455,7 +6750,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_2);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(2, mManager.getManifestShortcuts().size());
@@ -6604,7 +6899,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
R.xml.shortcut_1);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(1, mManager.getManifestShortcuts().size());
@@ -6624,7 +6919,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()),
R.xml.shortcut_1_alt);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(3, mManager.getManifestShortcuts().size());
@@ -6644,7 +6939,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()),
R.xml.shortcut_5_alt); // manifest has 5, but max is 3, so a2 will have 3.
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(5, mManager.getManifestShortcuts().size());
@@ -6663,7 +6958,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity2.class.getName()),
R.xml.shortcut_0);
updatePackageVersion(CALLING_PACKAGE_1, 1);
- mService.mPackageMonitor.onReceive(getTestContext(),
+ mService.mPackageMonitor.onReceive(getTestContext(),
genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
assertEquals(0, mManager.getManifestShortcuts().size());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index f570ff24ce36..d5460929960b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -130,7 +130,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertExpectException(NullPointerException.class, "action must be set",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
- // same for add.
assertExpectException(
IllegalArgumentException.class, "Short label must be provided", () -> {
ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
@@ -139,6 +138,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertTrue(getManager().setDynamicShortcuts(list(si)));
});
+ // same for add.
assertExpectException(
IllegalArgumentException.class, "Short label must be provided", () -> {
ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
@@ -147,7 +147,6 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertTrue(getManager().addDynamicShortcuts(list(si)));
});
- // same for add.
assertExpectException(NullPointerException.class, "Intent must be provided", () -> {
ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
.setActivity(new ComponentName(getTestContext().getPackageName(), "s"))
@@ -181,6 +180,33 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.build();
assertTrue(getManager().addDynamicShortcuts(list(si)));
});
+
+ // Now all activities are not main.
+ mMainActivityChecker = (component, userId) -> false;
+
+ assertExpectException(
+ IllegalStateException.class, "is not main", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(new ComponentName(getTestContext(), "s"))
+ .build();
+ assertTrue(getManager().setDynamicShortcuts(list(si)));
+ });
+ // For add
+ assertExpectException(
+ IllegalStateException.class, "is not main", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(new ComponentName(getTestContext(), "s"))
+ .build();
+ assertTrue(getManager().addDynamicShortcuts(list(si)));
+ });
+ // For update
+ assertExpectException(
+ IllegalStateException.class, "is not main", () -> {
+ ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
+ .setActivity(new ComponentName(getTestContext(), "s"))
+ .build();
+ assertTrue(getManager().updateShortcuts(list(si)));
+ });
}
public void testShortcutInfoParcel() {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 766e930649e9..52f75f680560 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -407,11 +407,11 @@ public abstract class Connection extends Conferenceable {
/**
* Boolean connection extra key on a {@link Connection} which indicates that adding an
- * additional call is disallowed when there is a video call in progress.
+ * additional call is disallowed.
* @hide
*/
- public static final String EXTRA_DISABLE_ADD_CALL_DURING_VIDEO_CALL =
- "android.telecom.extra.DISABLE_ADD_CALL_DURING_VIDEO_CALL";
+ public static final String EXTRA_DISABLE_ADD_CALL =
+ "android.telecom.extra.DISABLE_ADD_CALL";
/**
* Connection event used to inform Telecom that it should play the on hold tone. This is used
@@ -1551,6 +1551,8 @@ public abstract class Connection extends Conferenceable {
return "RINGING";
case STATE_DIALING:
return "DIALING";
+ case STATE_PULLING_CALL:
+ return "PULLING_CALL";
case STATE_ACTIVE:
return "ACTIVE";
case STATE_HOLDING:
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index fc7d7412d8b5..0c75630cab16 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -556,6 +556,9 @@ public abstract class ConnectionService extends Service {
case Connection.STATE_DIALING:
mAdapter.setDialing(id);
break;
+ case Connection.STATE_PULLING_CALL:
+ mAdapter.setPulling(id);
+ break;
case Connection.STATE_DISCONNECTED:
// Handled in onDisconnected()
break;
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index c8cd3c0486fb..df7d539d1782 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -143,6 +143,21 @@ final class ConnectionServiceAdapter implements DeathRecipient {
}
/**
+ * Sets a call's state to pulling (e.g. a call with {@link Connection#PROPERTY_IS_EXTERNAL_CALL}
+ * is being pulled to the local device.
+ *
+ * @param callId The unique ID of the call whose state is changing to dialing.
+ */
+ void setPulling(String callId) {
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ adapter.setPulling(callId);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ /**
* Sets a call's state to disconnected.
*
* @param callId The unique ID of the call whose state is changing to disconnected.
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index bf28feb92d91..486f9d594e91 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -65,6 +65,7 @@ final class ConnectionServiceAdapterServant {
private static final int MSG_REMOVE_EXTRAS = 25;
private static final int MSG_ON_CONNECTION_EVENT = 26;
private static final int MSG_SET_CONNECTION_PROPERTIES = 27;
+ private static final int MSG_SET_PULLING = 28;
private final IConnectionServiceAdapter mDelegate;
@@ -101,6 +102,9 @@ final class ConnectionServiceAdapterServant {
case MSG_SET_DIALING:
mDelegate.setDialing((String) msg.obj);
break;
+ case MSG_SET_PULLING:
+ mDelegate.setPulling((String) msg.obj);
+ break;
case MSG_SET_DISCONNECTED: {
SomeArgs args = (SomeArgs) msg.obj;
try {
@@ -299,6 +303,11 @@ final class ConnectionServiceAdapterServant {
}
@Override
+ public void setPulling(String connectionId) {
+ mHandler.obtainMessage(MSG_SET_PULLING, connectionId).sendToTarget();
+ }
+
+ @Override
public void setDisconnected(
String connectionId, DisconnectCause disconnectCause) {
SomeArgs args = SomeArgs.obtain();
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index dbc2b0c9f850..473e39457f58 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -220,6 +220,7 @@ public final class PhoneAccount implements Parcelable {
private final Icon mIcon;
private final Bundle mExtras;
private boolean mIsEnabled;
+ private String mGroupId;
/**
* Helper class for creating a {@link PhoneAccount}.
@@ -236,6 +237,7 @@ public final class PhoneAccount implements Parcelable {
private Icon mIcon;
private Bundle mExtras;
private boolean mIsEnabled = false;
+ private String mGroupId = "";
/**
* Creates a builder with the specified {@link PhoneAccountHandle} and label.
@@ -263,6 +265,7 @@ public final class PhoneAccount implements Parcelable {
mIcon = phoneAccount.getIcon();
mIsEnabled = phoneAccount.isEnabled();
mExtras = phoneAccount.getExtras();
+ mGroupId = phoneAccount.getGroupId();
}
/**
@@ -387,6 +390,27 @@ public final class PhoneAccount implements Parcelable {
}
/**
+ * Sets the group Id of the {@link PhoneAccount}. When a new {@link PhoneAccount} is
+ * registered to Telecom, it will replace another {@link PhoneAccount} that is already
+ * registered in Telecom and take on the current user defaults and enabled status. There can
+ * only be one {@link PhoneAccount} with a non-empty group number registered to Telecom at a
+ * time. By default, there is no group Id for a {@link PhoneAccount} (an empty String). Only
+ * grouped {@link PhoneAccount}s with the same {@link ConnectionService} can be replaced.
+ * @param groupId The group Id of the {@link PhoneAccount} that will replace any other
+ * registered {@link PhoneAccount} in Telecom with the same Group Id.
+ * @return The builder
+ * @hide
+ */
+ public Builder setGroupId(String groupId) {
+ if (groupId != null) {
+ mGroupId = groupId;
+ } else {
+ mGroupId = "";
+ }
+ return this;
+ }
+
+ /**
* Creates an instance of a {@link PhoneAccount} based on the current builder settings.
*
* @return The {@link PhoneAccount}.
@@ -408,7 +432,8 @@ public final class PhoneAccount implements Parcelable {
mShortDescription,
mSupportedUriSchemes,
mExtras,
- mIsEnabled);
+ mIsEnabled,
+ mGroupId);
}
}
@@ -423,7 +448,8 @@ public final class PhoneAccount implements Parcelable {
CharSequence shortDescription,
List<String> supportedUriSchemes,
Bundle extras,
- boolean isEnabled) {
+ boolean isEnabled,
+ String groupId) {
mAccountHandle = account;
mAddress = address;
mSubscriptionAddress = subscriptionAddress;
@@ -435,6 +461,7 @@ public final class PhoneAccount implements Parcelable {
mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
mExtras = extras;
mIsEnabled = isEnabled;
+ mGroupId = groupId;
}
public static Builder builder(
@@ -564,6 +591,21 @@ public final class PhoneAccount implements Parcelable {
}
/**
+ * A non-empty {@link String} representing the group that A {@link PhoneAccount} is in or an
+ * empty {@link String} if the {@link PhoneAccount} is not in a group. If this
+ * {@link PhoneAccount} is in a group, this new {@link PhoneAccount} will replace a registered
+ * {@link PhoneAccount} that is in the same group. When the {@link PhoneAccount} is replaced,
+ * its user defined defaults and enabled status will also pass to this new {@link PhoneAccount}.
+ * Only {@link PhoneAccount}s that share the same {@link ConnectionService} can be replaced.
+ *
+ * @return A non-empty String Id if this {@link PhoneAccount} belongs to a group.
+ * @hide
+ */
+ public String getGroupId() {
+ return mGroupId;
+ }
+
+ /**
* Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
* scheme.
*
@@ -644,6 +686,7 @@ public final class PhoneAccount implements Parcelable {
}
out.writeByte((byte) (mIsEnabled ? 1 : 0));
out.writeBundle(mExtras);
+ out.writeString(mGroupId);
}
public static final Creator<PhoneAccount> CREATOR
@@ -687,6 +730,7 @@ public final class PhoneAccount implements Parcelable {
}
mIsEnabled = in.readByte() == 1;
mExtras = in.readBundle();
+ mGroupId = in.readString();
}
@Override
@@ -704,6 +748,8 @@ public final class PhoneAccount implements Parcelable {
}
sb.append(" Extras: ");
sb.append(mExtras);
+ sb.append(" GroupId: ");
+ sb.append(Log.pii(mGroupId));
sb.append("]");
return sb.toString();
}
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 21a7706e5f55..306b3c15fa11 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -118,6 +118,12 @@ final class RemoteConnectionService {
}
@Override
+ public void setPulling(String callId) {
+ findConnectionForAction(callId, "setPulling")
+ .setState(Connection.STATE_PULLING_CALL);
+ }
+
+ @Override
public void setDisconnected(String callId, DisconnectCause disconnectCause) {
if (mConnectionById.containsKey(callId)) {
findConnectionForAction(callId, "setDisconnected")
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 9bc8ffe4ec6e..3bf83ae19777 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -47,6 +47,8 @@ oneway interface IConnectionServiceAdapter {
void setDialing(String callId);
+ void setPulling(String callId);
+
void setDisconnected(String callId, in DisconnectCause disconnectCause);
void setOnHold(String callId);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index a5e50aa1ee5d..2a95d3ec07cd 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -24,6 +24,7 @@ import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ServiceManager;
+import com.android.ims.ImsReasonInfo;
import com.android.internal.telephony.ICarrierConfigLoader;
/**
@@ -285,6 +286,16 @@ public class CarrierConfigManager {
public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL =
"carrier_default_wfc_ims_roaming_enabled_bool";
+ /**
+ * Flag indicating whether failed calls due to no service should prompt the user to enable
+ * WIFI calling. When {@code true}, if the user attempts to establish a call when there is no
+ * service available, they are connected to WIFI, and WIFI calling is disabled, a different
+ * call failure message will be used to encourage the user to enable WIFI calling.
+ * @hide
+ */
+ public static final String KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL =
+ "carrier_promote_wfc_on_call_fail_bool";
+
/** Flag specifying whether provisioning is required for VOLTE. */
public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
= "carrier_volte_provisioning_required_bool";
@@ -819,11 +830,32 @@ public class CarrierConfigManager {
"allow_merge_wifi_calls_when_vowifi_off_bool";
/**
- * When true, indicates that adding a call is disabled when there is an ongoing video call.
+ * When true, indicates that adding a call is disabled when there is an ongoing video call
+ * or when there is an ongoing call on wifi which was downgraded from video and VoWifi is
+ * turned off.
*/
public static final String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL =
"allow_add_call_during_video_call";
+ /**
+ * Defines operator-specific {@link com.android.ims.ImsReasonInfo} mappings.
+ *
+ * Format: "ORIGINAL_CODE|MESSAGE|NEW_CODE"
+ * Where {@code ORIGINAL_CODE} corresponds to a {@link ImsReasonInfo#getCode()} code,
+ * {@code MESSAGE} corresponds to an expected {@link ImsReasonInfo#getExtraMessage()} string,
+ * and {@code NEW_CODE} is the new {@code ImsReasonInfo#CODE_*} which this combination of
+ * original code and message shall be remapped to.
+ *
+ * Example: "501|call completion elsewhere|1014"
+ * When the {@link ImsReasonInfo#getCode()} is {@link ImsReasonInfo#CODE_USER_TERMINATED} and
+ * the {@link ImsReasonInfo#getExtraMessage()} is {@code "call completion elsewhere"},
+ * {@link ImsReasonInfo#CODE_ANSWERED_ELSEWHERE} shall be used as the {@link ImsReasonInfo}
+ * code instead.
+ * @hide
+ */
+ public static final String KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY =
+ "ims_reasoninfo_mapping_string_array";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -841,6 +873,7 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL, false);
+ sDefaults.putBoolean(KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL, false);
sDefaults.putInt(KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT, 2);
sDefaults.putBoolean(KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false);
@@ -979,6 +1012,8 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL, false);
sDefaults.putBoolean(KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL, true);
sDefaults.putBoolean(KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL, true);
+
+ sDefaults.putStringArray(KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY, null);
}
/**
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 80ae4aff4254..d7d4e840aa77 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -206,6 +206,12 @@ public class DisconnectCause {
*/
public static final int ANSWERED_ELSEWHERE = 52;
+ /**
+ * The call was terminated because the maximum allowable number of calls has been reached.
+ * {@hide}
+ */
+ public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 53;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Please assign the new type the next id value below.
@@ -214,14 +220,14 @@ public class DisconnectCause {
// 4) Update toString() with the newly added disconnect type.
// 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
//
- // NextId: 53
+ // NextId: 54
//*********************************************************************************************
/** Smallest valid value for call disconnect codes. */
public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
/** Largest valid value for call disconnect codes. */
- public static final int MAXIMUM_VALID_VALUE = ANSWERED_ELSEWHERE;
+ public static final int MAXIMUM_VALID_VALUE = MAXIMUM_NUMBER_OF_CALLS_REACHED;
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
@@ -335,6 +341,8 @@ public class DisconnectCause {
return "CALL_PULLED";
case ANSWERED_ELSEWHERE:
return "ANSWERED_ELSEWHERE";
+ case MAXIMUM_NUMBER_OF_CALLS_REACHED:
+ return "MAXIMUM_NUMER_OF_CALLS_REACHED";
default:
return "INVALID: " + cause;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 26ef0cbb87a5..df81d7f90008 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5538,5 +5538,22 @@ public class TelephonyManager {
}
return 0;
}
+
+ /**
+ * Policy control of data connection. Usually used when data limit is passed.
+ * @param enabled True if enabling the data, otherwise disabling.
+ * @param subId sub id
+ * @hide
+ */
+ public void setPolicyDataEnabled(boolean enabled, int subId) {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ service.setPolicyDataEnabled(enabled, subId);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#setPolicyDataEnabled", e);
+ }
+ }
}
diff --git a/telephony/java/com/android/ims/ImsExternalCallState.java b/telephony/java/com/android/ims/ImsExternalCallState.java
index 71c1837b6ff8..da2607356d6c 100644
--- a/telephony/java/com/android/ims/ImsExternalCallState.java
+++ b/telephony/java/com/android/ims/ImsExternalCallState.java
@@ -19,6 +19,7 @@ package com.android.ims;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telecom.Log;
import android.telephony.Rlog;
/*
@@ -130,7 +131,7 @@ public class ImsExternalCallState implements Parcelable {
@Override
public String toString() {
return "ImsExternalCallState { mCallId = " + mCallId +
- ", mAddress = " + mAddress +
+ ", mAddress = " + Log.pii(mAddress) +
", mIsPullable = " + mIsPullable +
", mCallState = " + mCallState +
", mCallType = " + mCallType +
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index 9369b20255a7..408ad31674c4 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -25,6 +25,7 @@ import android.os.Parcelable;
* @hide
*/
public class ImsReasonInfo implements Parcelable {
+
/**
* Specific code of each types
*/
@@ -284,6 +285,19 @@ public class ImsReasonInfo implements Parcelable {
public static final int CODE_EPDG_TUNNEL_LOST_CONNECTION = 1402;
/**
+ * The maximum number of calls allowed has been reached. Used in a multi-endpoint scenario
+ * where the number of calls across all connected devices has reached the maximum.
+ */
+ public static final int CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED = 1403;
+
+ /**
+ * Similar to {@link #CODE_LOCAL_CALL_DECLINE}, except indicates that a remote device has
+ * declined the call. Used in a multi-endpoint scenario where a remote device declined an
+ * incoming call.
+ */
+ public static final int CODE_REMOTE_CALL_DECLINE = 1404;
+
+ /**
* Network string error messages.
* mExtraMessage may have these values.
*/
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 8166e00f31cf..f01e4c0a8c69 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -105,6 +105,7 @@ public class DctConstants {
public static final int EVENT_DEVICE_PROVISIONED_CHANGE = BASE + 43;
public static final int EVENT_REDIRECTION_DETECTED = BASE + 44;
public static final int EVENT_PCO_DATA_RECEIVED = BASE + 45;
+ public static final int EVENT_SET_CARRIER_DATA_ENABLED = BASE + 46;
/***** Constants *****/
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 2168b0ea80db..167e1a739ca5 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1158,4 +1158,12 @@ interface ITelephony {
* @hide
*/
long getVtDataUsage();
+
+ /**
+ * Policy control of data connection. Usually used when data limit is passed.
+ * @param enabled True if enabling the data, otherwise disabling.
+ * @param subId Subscription index
+ * @hide
+ */
+ void setPolicyDataEnabled(boolean enabled, int subId);
}
diff --git a/tests/AppLaunch/Android.mk b/tests/AppLaunch/Android.mk
index c0560fd78e6c..e6f6c394f42d 100644
--- a/tests/AppLaunch/Android.mk
+++ b/tests/AppLaunch/Android.mk
@@ -11,7 +11,9 @@ LOCAL_PACKAGE_NAME := AppLaunch
LOCAL_CERTIFICATE := platform
LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
include $(BUILD_PACKAGE)
# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH)) \ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/AppLaunch/AndroidManifest.xml b/tests/AppLaunch/AndroidManifest.xml
index ac6760bb8366..7dfd7bafbaaa 100644
--- a/tests/AppLaunch/AndroidManifest.xml
+++ b/tests/AppLaunch/AndroidManifest.xml
@@ -3,6 +3,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.tests.applaunch"
android:sharedUserId="android.uid.system" >
+
+ <uses-permission android:name="android.permission.REAL_GET_TASKS" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <uses-sdk
+ android:minSdkVersion="22"
+ android:targetSdkVersion="24" />
+
<instrumentation android:label="Measure app start up time"
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.android.tests.applaunch" />
@@ -10,4 +18,4 @@
<application android:label="App Launch Test">
<uses-library android:name="android.test.runner" />
</application>
-</manifest> \ No newline at end of file
+</manifest>
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 085b7aaaa9e5..2346f8547550 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -15,14 +15,13 @@
*/
package com.android.tests.applaunch;
+import java.io.OutputStreamWriter;
+
import android.accounts.Account;
import android.accounts.AccountManager;
+import android.app.ActivityManagerNative;
import android.app.ActivityManager;
import android.app.ActivityManager.ProcessErrorStateInfo;
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
-import android.app.IActivityManager.WaitResult;
-import android.app.UiAutomation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -31,16 +30,29 @@ import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.app.UiAutomation;
+import android.app.IActivityManager;
+import android.app.IActivityManager.WaitResult;
+import android.support.test.rule.logging.AtraceLogger;
import android.test.InstrumentationTestCase;
import android.test.InstrumentationTestRunner;
import android.util.Log;
-
+import java.io.File;
+import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
+import android.os.ParcelFileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.InputStreamReader;
/**
* This test is intended to measure the time it takes for the apps to start.
@@ -55,27 +67,66 @@ public class AppLaunch extends InstrumentationTestCase {
private static final int JOIN_TIMEOUT = 10000;
private static final String TAG = AppLaunch.class.getSimpleName();
- private static final String KEY_APPS = "apps";
- private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
// optional parameter: comma separated list of required account types before proceeding
// with the app launch
private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
- private static final String KEY_SKIP_INITIAL_LAUNCH = "skip_initial_launch";
+ private static final String KEY_APPS = "apps";
+ private static final String KEY_TRIAL_LAUNCH = "trial_launch";
+ private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
+ private static final String KEY_LAUNCH_ORDER = "launch_order";
+ private static final String KEY_DROP_CACHE = "drop_cache";
+ private static final String KEY_SIMPLEPPERF_CMD = "simpleperf_cmd";
+ private static final String KEY_TRACE_ITERATIONS = "trace_iterations";
+ private static final String KEY_LAUNCH_DIRECTORY = "launch_directory";
+ private static final String KEY_TRACE_DIRECTORY = "trace_directory";
+ private static final String KEY_TRACE_CATEGORY = "trace_categories";
+ private static final String KEY_TRACE_BUFFERSIZE = "trace_bufferSize";
+ private static final String KEY_TRACE_DUMPINTERVAL = "tracedump_interval";
private static final String WEARABLE_ACTION_GOOGLE =
"com.google.android.wearable.action.GOOGLE";
private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 60000; //60s to allow app to idle
private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches
- private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 2000; //2s between launching apps
+ private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 5000; //5s between launching apps
+ private static final String LAUNCH_SUB_DIRECTORY = "launch_logs";
+ private static final String LAUNCH_FILE = "applaunch.txt";
+ private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
+ private static final String DEFAULT_TRACE_CATEGORIES = "sched,freq,gfx,view,dalvik,webview,"
+ + "input,wm,disk,am,wm";
+ private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
+ private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
+ private static final String TRIAL_LAUNCH = "TRAIL_LAUNCH";
+ private static final String DELIMITER = ",";
+ private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh";
+ private static final String APP_LAUNCH_CMD = "am start -W -n";
+ private static final String SUCCESS_MESSAGE = "Status: ok";
+ private static final String THIS_TIME = "ThisTime:";
+ private static final String LAUNCH_ITERATION = "LAUNCH_ITERATION - %d";
+ private static final String TRACE_ITERATION = "TRACE_ITERATION - %d";
+ private static final String LAUNCH_ITERATION_PREFIX = "LAUNCH_ITERATION";
+ private static final String TRACE_ITERATION_PREFIX = "TRACE_ITERATION";
+ private static final String LAUNCH_ORDER_CYCLIC = "cyclic";
+ private static final String LAUNCH_ORDER_SEQUENTIAL = "sequential";
+
private Map<String, Intent> mNameToIntent;
private Map<String, String> mNameToProcess;
+ private List<LaunchOrder> mLaunchOrderList = new ArrayList<LaunchOrder>();
private Map<String, String> mNameToResultKey;
- private Map<String, Long> mNameToLaunchTime;
+ private Map<String, List<Long>> mNameToLaunchTime;
private IActivityManager mAm;
+ private String mSimplePerfCmd = null;
+ private String mLaunchOrder = null;
+ private boolean mDropCache = false;
private int mLaunchIterations = 10;
+ private int mTraceLaunchCount = 0;
+ private String mTraceDirectoryStr = null;
private Bundle mResult = new Bundle();
private Set<String> mRequiredAccounts;
- private boolean mSkipInitialLaunch = false;
+ private boolean mTrailLaunch = true;
+ private File mFile = null;
+ private FileOutputStream mOutputStream = null;
+ private BufferedWriter mBufferedWriter = null;
+
@Override
protected void setUp() throws Exception {
@@ -89,69 +140,231 @@ public class AppLaunch extends InstrumentationTestCase {
super.tearDown();
}
- public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException {
+ public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException,
+ IOException, InterruptedException {
InstrumentationTestRunner instrumentation =
(InstrumentationTestRunner)getInstrumentation();
Bundle args = instrumentation.getArguments();
mAm = ActivityManagerNative.getDefault();
-
+ String launchDirectory = args.getString(KEY_LAUNCH_DIRECTORY);
+ mTraceDirectoryStr = args.getString(KEY_TRACE_DIRECTORY);
+ mDropCache = Boolean.parseBoolean(args.getString(KEY_DROP_CACHE));
+ mSimplePerfCmd = args.getString(KEY_SIMPLEPPERF_CMD);
+ mLaunchOrder = args.getString(KEY_LAUNCH_ORDER, LAUNCH_ORDER_CYCLIC);
createMappings();
parseArgs(args);
checkAccountSignIn();
- if (!mSkipInitialLaunch) {
- // do initial app launch, without force stopping
- for (String app : mNameToResultKey.keySet()) {
- long launchTime = startApp(app, false);
- if (launchTime <= 0) {
- mNameToLaunchTime.put(app, -1L);
- // simply pass the app if launch isn't successful
- // error should have already been logged by startApp
- continue;
- } else {
- mNameToLaunchTime.put(app, launchTime);
- }
- sleep(INITIAL_LAUNCH_IDLE_TIMEOUT);
- closeApp(app, false);
- sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+ // Root directory for applaunch file to log the app launch output
+ // Will be useful in case of simpleperf command is used
+ File launchRootDir = null;
+ if (null != launchDirectory && !launchDirectory.isEmpty()) {
+ launchRootDir = new File(launchDirectory);
+ if (!launchRootDir.exists() && !launchRootDir.mkdirs()) {
+ throw new IOException("Unable to create the destination directory");
}
}
- // do the real app launch now
- for (int i = 0; i < mLaunchIterations; i++) {
- for (String app : mNameToResultKey.keySet()) {
- long prevLaunchTime = mNameToLaunchTime.get(app);
- long launchTime = 0;
- if (prevLaunchTime < 0) {
- // skip if the app has previous failures
- continue;
+
+ try {
+ File launchSubDir = new File(launchRootDir, LAUNCH_SUB_DIRECTORY);
+ if (!launchSubDir.exists() && !launchSubDir.mkdirs()) {
+ throw new IOException("Unable to create the lauch file sub directory");
+ }
+ mFile = new File(launchSubDir, LAUNCH_FILE);
+ mOutputStream = new FileOutputStream(mFile);
+ mBufferedWriter = new BufferedWriter(new OutputStreamWriter(
+ mOutputStream));
+
+ // Root directory for trace file during the launches
+ File rootTrace = null;
+ File rootTraceSubDir = null;
+ int traceBufferSize = 0;
+ int traceDumpInterval = 0;
+ Set<String> traceCategoriesSet = null;
+ if (null != mTraceDirectoryStr && !mTraceDirectoryStr.isEmpty()) {
+ rootTrace = new File(mTraceDirectoryStr);
+ if (!rootTrace.exists() && !rootTrace.mkdirs()) {
+ throw new IOException("Unable to create the trace directory");
}
- launchTime = startApp(app, true);
- if (launchTime <= 0) {
- // if it fails once, skip the rest of the launches
- mNameToLaunchTime.put(app, -1L);
- continue;
+ rootTraceSubDir = new File(rootTrace, TRACE_SUB_DIRECTORY);
+ if (!rootTraceSubDir.exists() && !rootTraceSubDir.mkdirs()) {
+ throw new IOException("Unable to create the trace sub directory");
}
- // keep the min launch time
- if (launchTime < prevLaunchTime) {
- mNameToLaunchTime.put(app, launchTime);
+ assertNotNull("Trace iteration parameter is mandatory",
+ args.getString(KEY_TRACE_ITERATIONS));
+ mTraceLaunchCount = Integer.parseInt(args.getString(KEY_TRACE_ITERATIONS));
+ String traceCategoriesStr = args
+ .getString(KEY_TRACE_CATEGORY, DEFAULT_TRACE_CATEGORIES);
+ traceBufferSize = Integer.parseInt(args.getString(KEY_TRACE_BUFFERSIZE,
+ DEFAULT_TRACE_BUFFER_SIZE));
+ traceDumpInterval = Integer.parseInt(args.getString(KEY_TRACE_DUMPINTERVAL,
+ DEFAULT_TRACE_DUMP_INTERVAL));
+ traceCategoriesSet = new HashSet<String>();
+ if (!traceCategoriesStr.isEmpty()) {
+ String[] traceCategoriesSplit = traceCategoriesStr.split(DELIMITER);
+ for (int i = 0; i < traceCategoriesSplit.length; i++) {
+ traceCategoriesSet.add(traceCategoriesSplit[i]);
+ }
}
- sleep(POST_LAUNCH_IDLE_TIMEOUT);
- closeApp(app, true);
- sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+ }
+
+ // Get the app launch order based on launch order, trial launch,
+ // launch iterations and trace iterations
+ setLaunchOrder();
+
+ for (LaunchOrder launch : mLaunchOrderList) {
+
+ // App launch times for trial launch will not be used for final
+ // launch time calculations.
+ if (launch.getLaunchReason().equals(TRIAL_LAUNCH)) {
+ // In the "applaunch.txt" file, trail launches is referenced using
+ // "TRIAL_LAUNCH"
+ long launchTime = startApp(launch.getApp(), true, launch.getLaunchReason());
+ if (launchTime < 0) {
+ List<Long> appLaunchList = new ArrayList<Long>();
+ appLaunchList.add(-1L);
+ mNameToLaunchTime.put(launch.getApp(), appLaunchList);
+ // simply pass the app if launch isn't successful
+ // error should have already been logged by startApp
+ continue;
+ }
+ sleep(INITIAL_LAUNCH_IDLE_TIMEOUT);
+ closeApp(launch.getApp(), true);
+ dropCache();
+ sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+ }
+
+ // App launch times used for final calculation
+ if (launch.getLaunchReason().contains(LAUNCH_ITERATION_PREFIX)) {
+ long launchTime = -1;
+ if (null != mNameToLaunchTime.get(launch.getApp())) {
+ long firstLaunchTime = mNameToLaunchTime.get(launch.getApp()).get(0);
+ if (firstLaunchTime < 0) {
+ // skip if the app has failures while launched first
+ continue;
+ }
+ }
+ // In the "applaunch.txt" file app launches are referenced using
+ // "LAUNCH_ITERATION - ITERATION NUM"
+ launchTime = startApp(launch.getApp(), true, launch.getLaunchReason());
+ if (launchTime < 0) {
+ // if it fails once, skip the rest of the launches
+ List<Long> appLaunchList = new ArrayList<Long>();
+ appLaunchList.add(-1L);
+ mNameToLaunchTime.put(launch.getApp(), appLaunchList);
+ continue;
+ } else {
+ if (null != mNameToLaunchTime.get(launch.getApp())) {
+ mNameToLaunchTime.get(launch.getApp()).add(launchTime);
+ } else {
+ List<Long> appLaunchList = new ArrayList<Long>();
+ appLaunchList.add(launchTime);
+ mNameToLaunchTime.put(launch.getApp(), appLaunchList);
+ }
+ }
+ sleep(POST_LAUNCH_IDLE_TIMEOUT);
+ closeApp(launch.getApp(), true);
+ dropCache();
+ sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+ }
+
+ // App launch times for trace launch will not be used for final
+ // launch time calculations.
+ if (launch.getLaunchReason().contains(TRACE_ITERATION_PREFIX)) {
+ AtraceLogger atraceLogger = AtraceLogger
+ .getAtraceLoggerInstance(getInstrumentation());
+ // Start the trace
+ try {
+ atraceLogger.atraceStart(traceCategoriesSet, traceBufferSize,
+ traceDumpInterval, rootTraceSubDir,
+ String.format("%s-%s", launch.getApp(), launch.getLaunchReason()));
+ startApp(launch.getApp(), true, launch.getLaunchReason());
+ sleep(POST_LAUNCH_IDLE_TIMEOUT);
+ } finally {
+ // Stop the trace
+ atraceLogger.atraceStop();
+ closeApp(launch.getApp(), true);
+ dropCache();
+ sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
+ }
+ }
+ }
+ } finally {
+ if (null != mBufferedWriter) {
+ mBufferedWriter.close();
}
}
+
for (String app : mNameToResultKey.keySet()) {
- long launchTime = mNameToLaunchTime.get(app);
- if (launchTime != -1) {
- mResult.putLong(mNameToResultKey.get(app), launchTime);
+ StringBuilder launchTimes = new StringBuilder();
+ for (Long launch : mNameToLaunchTime.get(app)) {
+ launchTimes.append(launch);
+ launchTimes.append(",");
}
+ mResult.putString(mNameToResultKey.get(app), launchTimes.toString());
}
instrumentation.sendStatus(0, mResult);
}
+ /**
+ * If launch order is "cyclic" then apps will be launched one after the
+ * other for each iteration count.
+ * If launch order is "sequential" then each app will be launched for given number
+ * iterations at once before launching the other apps.
+ */
+ private void setLaunchOrder() {
+ if (LAUNCH_ORDER_CYCLIC.equalsIgnoreCase(mLaunchOrder)) {
+ if (mTrailLaunch) {
+ for (String app : mNameToResultKey.keySet()) {
+ mLaunchOrderList.add(new LaunchOrder(app, TRIAL_LAUNCH));
+ }
+ }
+ for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
+ for (String app : mNameToResultKey.keySet()) {
+ mLaunchOrderList.add(new LaunchOrder(app,
+ String.format(LAUNCH_ITERATION, launchCount)));
+ }
+ }
+ if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
+ for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
+ for (String app : mNameToResultKey.keySet()) {
+ mLaunchOrderList.add(new LaunchOrder(app,
+ String.format(TRACE_ITERATION, traceCount)));
+ }
+ }
+ }
+ } else if (LAUNCH_ORDER_SEQUENTIAL.equalsIgnoreCase(mLaunchOrder)) {
+ for (String app : mNameToResultKey.keySet()) {
+ if (mTrailLaunch) {
+ mLaunchOrderList.add(new LaunchOrder(app, TRIAL_LAUNCH));
+ }
+ for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
+ mLaunchOrderList.add(new LaunchOrder(app,
+ String.format(LAUNCH_ITERATION, launchCount)));
+ }
+ if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
+ for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
+ mLaunchOrderList.add(new LaunchOrder(app,
+ String.format(TRACE_ITERATION, traceCount)));
+ }
+ }
+ }
+ } else {
+ assertTrue("Launch order is not valid parameter", false);
+ }
+ }
+
+ private void dropCache() {
+ if (true == mDropCache) {
+ assertNotNull("Issue in dropping the cache",
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand(DROP_CACHE_SCRIPT));
+ }
+ }
+
private void parseArgs(Bundle args) {
mNameToResultKey = new LinkedHashMap<String, String>();
- mNameToLaunchTime = new HashMap<String, Long>();
+ mNameToLaunchTime = new HashMap<String, List<Long>>();
String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS);
if (launchIterations != null) {
mLaunchIterations = Integer.parseInt(launchIterations);
@@ -169,7 +382,7 @@ public class AppLaunch extends InstrumentationTestCase {
}
mNameToResultKey.put(parts[0], parts[1]);
- mNameToLaunchTime.put(parts[0], 0L);
+ mNameToLaunchTime.put(parts[0], null);
}
String requiredAccounts = args.getString(KEY_REQUIRED_ACCOUNTS);
if (requiredAccounts != null) {
@@ -178,7 +391,7 @@ public class AppLaunch extends InstrumentationTestCase {
mRequiredAccounts.add(accountType);
}
}
- mSkipInitialLaunch = "true".equals(args.getString(KEY_SKIP_INITIAL_LAUNCH));
+ mTrailLaunch = "true".equals(args.getString(KEY_TRIAL_LAUNCH));
}
private boolean hasLeanback(Context context) {
@@ -222,7 +435,7 @@ public class AppLaunch extends InstrumentationTestCase {
}
}
- private long startApp(String appName, boolean forceStopBeforeLaunch)
+ private long startApp(String appName, boolean forceStopBeforeLaunch, String launchReason)
throws NameNotFoundException, RemoteException {
Log.i(TAG, "Starting " + appName);
@@ -230,9 +443,10 @@ public class AppLaunch extends InstrumentationTestCase {
if (startIntent == null) {
Log.w(TAG, "App does not exist: " + appName);
mResult.putString(mNameToResultKey.get(appName), "App does not exist");
- return -1;
+ return -1L;
}
- AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch);
+ AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch ,
+ launchReason);
Thread t = new Thread(runnable);
t.start();
try {
@@ -240,21 +454,7 @@ public class AppLaunch extends InstrumentationTestCase {
} catch (InterruptedException e) {
// ignore
}
- WaitResult result = runnable.getResult();
- // report error if any of the following is true:
- // * launch thread is alive
- // * result is not null, but:
- // * result is not START_SUCCESS
- // * or in case of no force stop, result is not TASK_TO_FRONT either
- if (t.isAlive() || (result != null
- && ((result.result != ActivityManager.START_SUCCESS)
- && (!forceStopBeforeLaunch
- && result.result != ActivityManager.START_TASK_TO_FRONT)))) {
- Log.w(TAG, "Assuming app " + appName + " crashed.");
- reportError(appName, mNameToProcess.get(appName));
- return -1;
- }
- return result.thisTime;
+ return runnable.getResult();
}
private void checkAccountSignIn() {
@@ -337,39 +537,117 @@ public class AppLaunch extends InstrumentationTestCase {
+ " not found in process list, most likely it is crashed");
}
+ private class LaunchOrder {
+ private String mApp;
+ private String mLaunchReason;
+
+ LaunchOrder(String app,String launchReason){
+ mApp = app;
+ mLaunchReason = launchReason;
+ }
+
+ public String getApp() {
+ return mApp;
+ }
+
+ public void setApp(String app) {
+ mApp = app;
+ }
+
+ public String getLaunchReason() {
+ return mLaunchReason;
+ }
+
+ public void setLaunchReason(String launchReason) {
+ mLaunchReason = launchReason;
+ }
+ }
+
private class AppLaunchRunnable implements Runnable {
private Intent mLaunchIntent;
- private IActivityManager.WaitResult mResult;
+ private Long mResult;
private boolean mForceStopBeforeLaunch;
+ private String mLaunchReason;
- public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch) {
+ public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch,
+ String launchReason) {
mLaunchIntent = intent;
mForceStopBeforeLaunch = forceStopBeforeLaunch;
+ mLaunchReason = launchReason;
}
- public IActivityManager.WaitResult getResult() {
+ public Long getResult() {
return mResult;
}
public void run() {
try {
String packageName = mLaunchIntent.getComponent().getPackageName();
+ String componentName = mLaunchIntent.getComponent().flattenToShortString();
if (mForceStopBeforeLaunch) {
mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
}
- String mimeType = mLaunchIntent.getType();
- if (mimeType == null && mLaunchIntent.getData() != null
- && "content".equals(mLaunchIntent.getData().getScheme())) {
- mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
- UserHandle.USER_CURRENT);
+ String launchCmd = String.format("%s %s", APP_LAUNCH_CMD, componentName);
+ if (null != mSimplePerfCmd) {
+ launchCmd = String.format("%s %s", mSimplePerfCmd, launchCmd);
}
-
- mResult = mAm.startActivityAndWait(null, null, mLaunchIntent, mimeType,
- null, null, 0, mLaunchIntent.getFlags(), null, null,
- UserHandle.USER_CURRENT);
+ Log.v(TAG, "Final launch cmd:" + launchCmd);
+ ParcelFileDescriptor parcelDesc = getInstrumentation().getUiAutomation()
+ .executeShellCommand(launchCmd);
+ mResult = Long.parseLong(parseLaunchTimeAndWrite(parcelDesc, String.format
+ ("App Launch :%s %s",
+ componentName, mLaunchReason)), 10);
} catch (RemoteException e) {
Log.w(TAG, "Error launching app", e);
}
}
+
+ /**
+ * Method to parse the launch time info and write the result to file
+ *
+ * @param parcelDesc
+ * @return
+ */
+ private String parseLaunchTimeAndWrite(ParcelFileDescriptor parcelDesc, String headerInfo) {
+ String launchTime = "-1";
+ boolean launchSuccess = false;
+ try {
+ InputStream inputStream = new FileInputStream(parcelDesc.getFileDescriptor());
+ StringBuilder appLaunchOuput = new StringBuilder();
+ /* SAMPLE OUTPUT :
+ Starting: Intent { cmp=com.google.android.calculator/com.android.calculator2.Calculator }
+ Status: ok
+ Activity: com.google.android.calculator/com.android.calculator2.Calculator
+ ThisTime: 357
+ TotalTime: 357
+ WaitTime: 377
+ Complete*/
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ inputStream));
+ String line = null;
+ int lineCount = 1;
+ mBufferedWriter.newLine();
+ mBufferedWriter.write(headerInfo);
+ mBufferedWriter.newLine();
+ while ((line = bufferedReader.readLine()) != null) {
+ if (lineCount == 2 && line.contains(SUCCESS_MESSAGE)) {
+ launchSuccess = true;
+ }
+ if (launchSuccess && lineCount == 4) {
+ String launchSplit[] = line.split(":");
+ launchTime = launchSplit[1].trim();
+ }
+ mBufferedWriter.write(line);
+ mBufferedWriter.newLine();
+ lineCount++;
+ }
+ mBufferedWriter.flush();
+ inputStream.close();
+ } catch (IOException e) {
+ Log.w(TAG, "Error writing the launch file", e);
+ }
+ return launchTime;
+ }
+
}
}
diff --git a/tests/SoundTriggerTestApp/AndroidManifest.xml b/tests/SoundTriggerTestApp/AndroidManifest.xml
index 71d6001c3a56..87f3e92b3a60 100644
--- a/tests/SoundTriggerTestApp/AndroidManifest.xml
+++ b/tests/SoundTriggerTestApp/AndroidManifest.xml
@@ -1,25 +1,28 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.test.soundtrigger">
-
+ <uses-permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD" />
<uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application>
<activity
- android:name="TestSoundTriggerActivity"
+ android:name=".SoundTriggerTestActivity"
android:label="SoundTrigger Test Application"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Material">
- <!--
- <intent-filter>
- <action android:name="com.android.intent.action.MANAGE_SOUND_TRIGGER" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <service
+ android:name=".SoundTriggerTestService"
+ android:stopWithTask="false"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="com.android.intent.action.MANAGE_SOUND_TRIGGER" />
+ </intent-filter>
+ </service>
</application>
</manifest>
diff --git a/tests/SoundTriggerTestApp/res/layout/main.xml b/tests/SoundTriggerTestApp/res/layout/main.xml
index 06949a0b6328..0fd8b12fafd7 100644
--- a/tests/SoundTriggerTestApp/res/layout/main.xml
+++ b/tests/SoundTriggerTestApp/res/layout/main.xml
@@ -18,81 +18,107 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical"
- >
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- >
+ android:orientation="vertical">
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/enroll"
- android:onClick="onEnrollButtonClicked"
- android:padding="20dp" />
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/reenroll"
- android:onClick="onReEnrollButtonClicked"
- android:padding="20dp" />
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/load"
+ android:onClick="onLoadButtonClicked"
+ android:padding="20dp" />
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/start_recog"
- android:onClick="onStartRecognitionButtonClicked"
- android:padding="20dp" />
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/start_recog"
+ android:onClick="onStartRecognitionButtonClicked"
+ android:padding="20dp" />
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/stop_recog"
- android:onClick="onStopRecognitionButtonClicked"
- android:padding="20dp" />
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/stop_recog"
+ android:onClick="onStopRecognitionButtonClicked"
+ android:padding="20dp" />
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/unenroll"
- android:onClick="onUnEnrollButtonClicked"
- android:padding="20dp" />
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/unload"
+ android:onClick="onUnloadButtonClicked"
+ android:padding="20dp" />
- <Button
- android:id="@+id/play_trigger_id"
- android:layout_width="wrap_content"
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/reload"
+ android:onClick="onReloadButtonClicked"
+ android:padding="20dp" />
+
+ <Button
+ android:id="@+id/play_trigger_id"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/play_trigger"
+ android:onClick="onPlayTriggerButtonClicked"
+ android:padding="20dp" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/play_trigger"
- android:onClick="onPlayTriggerButtonClicked"
- android:padding="20dp" />
+ android:layout_gravity="right">
-</LinearLayout>
+ <CheckBox
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/capture"
+ android:id="@+id/caputre_check_box"
+ android:layout_gravity="center_horizontal"
+ android:padding="20dp" />
+
+ <Button
+ android:id="@+id/play_captured_id"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/play_capture"
+ android:padding="20dp"
+ android:enabled="false" />
+ </LinearLayout>
-<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
+ <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/model_group_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="20dp"
- android:orientation="vertical">
-</RadioGroup>
+ android:orientation="vertical" />
-<ScrollView
+ <ScrollView
android:id="@+id/scroller_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:fillViewport="true">
- <TextView
- android:id="@+id/console"
- android:paddingTop="20pt"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:textSize="14dp"
- android:layout_weight="1.0"
- android:text="@string/none">
- </TextView>
-</ScrollView>
+ <TextView
+ android:id="@+id/console"
+ android:paddingTop="20pt"
+ android:layout_height="fill_parent"
+ android:layout_width="fill_parent"
+ android:textSize="14dp"
+ android:layout_weight="1.0"
+ android:text="@string/none" />
+ </ScrollView>
</LinearLayout>
diff --git a/tests/SoundTriggerTestApp/res/values/strings.xml b/tests/SoundTriggerTestApp/res/values/strings.xml
index 7c1f64944e7f..c48b64884c5e 100644
--- a/tests/SoundTriggerTestApp/res/values/strings.xml
+++ b/tests/SoundTriggerTestApp/res/values/strings.xml
@@ -16,11 +16,14 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="enroll">Load</string>
- <string name="reenroll">Re-load</string>
- <string name="unenroll">Un-load</string>
+ <string name="load">Load</string>
+ <string name="reload">Reload</string>
+ <string name="unload">Unload</string>
<string name="start_recog">Start</string>
<string name="stop_recog">Stop</string>
<string name="play_trigger">Play Trigger Audio</string>
+ <string name="capture">Capture Audio</string>
+ <string name="stop_capture">Stop Capturing Audio</string>
+ <string name="play_capture">Play Captured Audio</string>
<string name="none">Debug messages appear here:\n</string>
</resources>
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java
new file mode 100644
index 000000000000..4841bc59c794
--- /dev/null
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestActivity.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.soundtrigger;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.PowerManager;
+import android.text.Editable;
+import android.text.method.ScrollingMovementMethod;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.test.soundtrigger.SoundTriggerTestService.SoundTriggerTestBinder;
+
+public class SoundTriggerTestActivity extends Activity implements SoundTriggerTestService.UserActivity {
+ private static final String TAG = "SoundTriggerTest";
+ private static final int AUDIO_PERMISSIONS_REQUEST = 1;
+
+ private SoundTriggerTestService mService = null;
+
+ private static UUID mSelectedModelUuid = null;
+
+ private Map<RadioButton, UUID> mButtonModelUuidMap;
+ private Map<UUID, RadioButton> mModelButtons;
+ private Map<UUID, String> mModelNames;
+ private List<RadioButton> mModelRadioButtons;
+
+ private TextView mDebugView = null;
+ private ScrollView mScrollView = null;
+ private Button mPlayTriggerButton = null;
+ private PowerManager.WakeLock mScreenWakelock;
+ private Handler mHandler;
+ private RadioGroup mRadioGroup;
+ private CheckBox mCaptureAudioCheckBox;
+ private Button mPlayCapturedAudioButton = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ // Make sure that this activity can punch through the lockscreen if needed.
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
+ WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ mDebugView = (TextView) findViewById(R.id.console);
+ mScrollView = (ScrollView) findViewById(R.id.scroller_id);
+ mRadioGroup = (RadioGroup) findViewById(R.id.model_group_id);
+ mPlayTriggerButton = (Button) findViewById(R.id.play_trigger_id);
+ mDebugView.setText(mDebugView.getText(), TextView.BufferType.EDITABLE);
+ mDebugView.setMovementMethod(new ScrollingMovementMethod());
+ mCaptureAudioCheckBox = (CheckBox) findViewById(R.id.caputre_check_box);
+ mPlayCapturedAudioButton = (Button) findViewById(R.id.play_captured_id);
+ mHandler = new Handler();
+ mButtonModelUuidMap = new HashMap();
+ mModelButtons = new HashMap();
+ mModelNames = new HashMap();
+ mModelRadioButtons = new LinkedList();
+
+ setVolumeControlStream(AudioManager.STREAM_MUSIC);
+
+ // Make sure that the service is started, so even if our activity goes down, we'll still
+ // have a request for it to run.
+ startService(new Intent(getBaseContext(), SoundTriggerTestService.class));
+
+ // Bind to SoundTriggerTestService.
+ Intent intent = new Intent(this, SoundTriggerTestService.class);
+ bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ // Unbind from the service.
+ if (mService != null) {
+ mService.setUserActivity(null);
+ unbindService(mConnection);
+ }
+ }
+
+ @Override
+ public void addModel(UUID modelUuid, String name) {
+ // Create a new widget for this model, and insert everything we'd need into the map.
+ RadioButton button = new RadioButton(this);
+ mModelRadioButtons.add(button);
+ button.setText(name);
+ button.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ onRadioButtonClicked(v);
+ }
+ });
+ mButtonModelUuidMap.put(button, modelUuid);
+ mModelButtons.put(modelUuid, button);
+ mModelNames.put(modelUuid, name);
+
+ // Sort all the radio buttons by name, then push them into the group in order.
+ Collections.sort(mModelRadioButtons, new Comparator<RadioButton>(){
+ @Override
+ public int compare(RadioButton button0, RadioButton button1) {
+ return button0.getText().toString().compareTo(button1.getText().toString());
+ }
+ });
+ mRadioGroup.removeAllViews();
+ for (View v : mModelRadioButtons) {
+ mRadioGroup.addView(v);
+ }
+
+ // If we don't have something selected, select this first thing.
+ if (mSelectedModelUuid == null || mSelectedModelUuid.equals(modelUuid)) {
+ button.setChecked(true);
+ onRadioButtonClicked(button);
+ }
+ }
+
+ @Override
+ public void setModelState(UUID modelUuid, String state) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ String newButtonText = mModelNames.get(modelUuid);
+ if (state != null) {
+ newButtonText += ": " + state;
+ }
+ mModelButtons.get(modelUuid).setText(newButtonText);
+ updateSelectModelSpecificUiElements();
+ }
+ });
+ }
+
+ @Override
+ public void showMessage(String msg, boolean showToast) {
+ // Append the message to the text field, then show the toast if requested.
+ this.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ ((Editable) mDebugView.getText()).append(msg + "\n");
+ mScrollView.post(new Runnable() {
+ public void run() {
+ mScrollView.smoothScrollTo(0, mDebugView.getBottom());
+ }
+ });
+ if (showToast) {
+ Toast.makeText(SoundTriggerTestActivity.this, msg, Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void handleDetection(UUID modelUuid) {
+ screenWakeup();
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ screenRelease();
+ }
+ }, 1000L);
+ }
+
+ private void screenWakeup() {
+ if (mScreenWakelock == null) {
+ PowerManager pm = ((PowerManager)getSystemService(POWER_SERVICE));
+ mScreenWakelock = pm.newWakeLock(
+ PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
+ }
+ mScreenWakelock.acquire();
+ }
+
+ private void screenRelease() {
+ mScreenWakelock.release();
+ }
+
+ public void onLoadButtonClicked(View v) {
+ if (mService == null) {
+ Log.e(TAG, "Could not load sound model: not bound to SoundTriggerTestService");
+ } else {
+ mService.loadModel(mSelectedModelUuid);
+ }
+ }
+
+ public void onUnloadButtonClicked(View v) {
+ if (mService == null) {
+ Log.e(TAG, "Can't unload model: not bound to SoundTriggerTestService");
+ } else {
+ mService.unloadModel(mSelectedModelUuid);
+ }
+ }
+
+ public void onReloadButtonClicked(View v) {
+ if (mService == null) {
+ Log.e(TAG, "Can't reload model: not bound to SoundTriggerTestService");
+ } else {
+ mService.reloadModel(mSelectedModelUuid);
+ }
+ }
+
+ public void onStartRecognitionButtonClicked(View v) {
+ if (mService == null) {
+ Log.e(TAG, "Can't start recognition: not bound to SoundTriggerTestService");
+ } else {
+ mService.startRecognition(mSelectedModelUuid);
+ }
+ }
+
+ public void onStopRecognitionButtonClicked(View v) {
+ if (mService == null) {
+ Log.e(TAG, "Can't stop recognition: not bound to SoundTriggerTestService");
+ } else {
+ mService.stopRecognition(mSelectedModelUuid);
+ }
+ }
+
+ public synchronized void onPlayTriggerButtonClicked(View v) {
+ if (mService == null) {
+ Log.e(TAG, "Can't play trigger audio: not bound to SoundTriggerTestService");
+ } else {
+ mService.playTriggerAudio(mSelectedModelUuid);
+ }
+ }
+
+ public synchronized void onCaptureAudioCheckboxClicked(View v) {
+ // See if we have the right permissions
+ if (!mService.hasMicrophonePermission()) {
+ requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO},
+ AUDIO_PERMISSIONS_REQUEST);
+ return;
+ } else {
+ mService.setCaptureAudio(mSelectedModelUuid, mCaptureAudioCheckBox.isChecked());
+ }
+ }
+
+ @Override
+ public synchronized void onRequestPermissionsResult(int requestCode, String permissions[],
+ int[] grantResults) {
+ if (requestCode == AUDIO_PERMISSIONS_REQUEST) {
+ if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ // Make sure that the check box is set to false.
+ mCaptureAudioCheckBox.setChecked(false);
+ }
+ mService.setCaptureAudio(mSelectedModelUuid, mCaptureAudioCheckBox.isChecked());
+ }
+ }
+
+ public synchronized void onPlayCapturedAudioButtonClicked(View v) {
+ if (mService == null) {
+ Log.e(TAG, "Can't play captured audio: not bound to SoundTriggerTestService");
+ } else {
+ mService.playCapturedAudio(mSelectedModelUuid);
+ }
+ }
+
+ public synchronized void onRadioButtonClicked(View view) {
+ // Is the button now checked?
+ boolean checked = ((RadioButton) view).isChecked();
+ if (checked) {
+ mSelectedModelUuid = mButtonModelUuidMap.get(view);
+ showMessage("Selected " + mModelNames.get(mSelectedModelUuid), false);
+ updateSelectModelSpecificUiElements();
+ }
+ }
+
+ private synchronized void updateSelectModelSpecificUiElements() {
+ // Set the play trigger button to be enabled only if we actually have some audio.
+ mPlayTriggerButton.setEnabled(mService.modelHasTriggerAudio((mSelectedModelUuid)));
+ // Similar logic for the captured audio.
+ mCaptureAudioCheckBox.setChecked(
+ mService.modelWillCaptureTriggerAudio(mSelectedModelUuid));
+ mPlayCapturedAudioButton.setEnabled(mService.modelHasCapturedAudio((mSelectedModelUuid)));
+ }
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ synchronized (SoundTriggerTestActivity.this) {
+ // We've bound to LocalService, cast the IBinder and get LocalService instance
+ SoundTriggerTestBinder binder = (SoundTriggerTestBinder) service;
+ mService = binder.getService();
+ mService.setUserActivity(SoundTriggerTestActivity.this);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName arg0) {
+ synchronized (SoundTriggerTestActivity.this) {
+ mService.setUserActivity(null);
+ mService = null;
+ }
+ }
+ };
+}
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
new file mode 100644
index 000000000000..a2385d695450
--- /dev/null
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
@@ -0,0 +1,720 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.soundtrigger;
+
+import android.Manifest;
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.media.AudioAttributes;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioRecord;
+import android.media.AudioTrack;
+import android.media.MediaPlayer;
+import android.media.soundtrigger.SoundTriggerDetector;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Random;
+import java.util.UUID;
+
+public class SoundTriggerTestService extends Service {
+ private static final String TAG = "SoundTriggerTestSrv";
+ private static final String INTENT_ACTION = "com.android.intent.action.MANAGE_SOUND_TRIGGER";
+
+ // Binder given to clients.
+ private final IBinder mBinder;
+ private final Map<UUID, ModelInfo> mModelInfoMap;
+ private SoundTriggerUtil mSoundTriggerUtil;
+ private Random mRandom;
+ private UserActivity mUserActivity;
+
+ public interface UserActivity {
+ void addModel(UUID modelUuid, String state);
+ void setModelState(UUID modelUuid, String state);
+ void showMessage(String msg, boolean showToast);
+ void handleDetection(UUID modelUuid);
+ }
+
+ public SoundTriggerTestService() {
+ super();
+ mRandom = new Random();
+ mModelInfoMap = new HashMap();
+ mBinder = new SoundTriggerTestBinder();
+ }
+
+ @Override
+ public synchronized int onStartCommand(Intent intent, int flags, int startId) {
+ if (mModelInfoMap.isEmpty()) {
+ mSoundTriggerUtil = new SoundTriggerUtil(this);
+ loadModelsInDataDir();
+ }
+
+ // If we get killed, after returning from here, restart
+ return START_STICKY;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(INTENT_ACTION);
+ registerReceiver(mBroadcastReceiver, filter);
+
+ // Make sure the data directory exists, and we're the owner of it.
+ try {
+ getFilesDir().mkdir();
+ } catch (Exception e) {
+ // Don't care - we either made it, or it already exists.
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ stopAllRecognitions();
+ unregisterReceiver(mBroadcastReceiver);
+ }
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null && INTENT_ACTION.equals(intent.getAction())) {
+ String command = intent.getStringExtra("command");
+ if (command == null) {
+ Log.e(TAG, "No 'command' specified in " + INTENT_ACTION);
+ } else {
+ try {
+ if (command.equals("load")) {
+ loadModel(getModelUuidFromIntent(intent));
+ } else if (command.equals("unload")) {
+ unloadModel(getModelUuidFromIntent(intent));
+ } else if (command.equals("start")) {
+ startRecognition(getModelUuidFromIntent(intent));
+ } else if (command.equals("stop")) {
+ stopRecognition(getModelUuidFromIntent(intent));
+ } else if (command.equals("play_trigger")) {
+ playTriggerAudio(getModelUuidFromIntent(intent));
+ } else if (command.equals("play_captured")) {
+ playCapturedAudio(getModelUuidFromIntent(intent));
+ } else if (command.equals("set_capture")) {
+ setCaptureAudio(getModelUuidFromIntent(intent),
+ intent.getBooleanExtra("enabled", true));
+ } else if (command.equals("set_capture_timeout")) {
+ setCaptureAudioTimeout(getModelUuidFromIntent(intent),
+ intent.getIntExtra("timeout", 5000));
+ } else {
+ Log.e(TAG, "Unknown command '" + command + "'");
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to process " + command, e);
+ }
+ }
+ }
+ }
+ };
+
+ private UUID getModelUuidFromIntent(Intent intent) {
+ // First, see if the specified the UUID straight up.
+ String value = intent.getStringExtra("modelUuid");
+ if (value != null) {
+ return UUID.fromString(value);
+ }
+
+ // If they specified a name, use that to iterate through the map of models and find it.
+ value = intent.getStringExtra("name");
+ if (value != null) {
+ for (ModelInfo modelInfo : mModelInfoMap.values()) {
+ if (value.equals(modelInfo.name)) {
+ return modelInfo.modelUuid;
+ }
+ }
+ Log.e(TAG, "Failed to find a matching model with name '" + value + "'");
+ }
+
+ // We couldn't figure out what they were asking for.
+ throw new RuntimeException("Failed to get model from intent - specify either " +
+ "'modelUuid' or 'name'");
+ }
+
+ /**
+ * Will be called when the service is killed (through swipe aways, not if we're force killed).
+ */
+ @Override
+ public void onTaskRemoved(Intent rootIntent) {
+ super.onTaskRemoved(rootIntent);
+ stopAllRecognitions();
+ stopSelf();
+ }
+
+ @Override
+ public synchronized IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ public class SoundTriggerTestBinder extends Binder {
+ SoundTriggerTestService getService() {
+ // Return instance of our parent so clients can call public methods.
+ return SoundTriggerTestService.this;
+ }
+ }
+
+ public synchronized void setUserActivity(UserActivity activity) {
+ mUserActivity = activity;
+ if (mUserActivity != null) {
+ for (Map.Entry<UUID, ModelInfo> entry : mModelInfoMap.entrySet()) {
+ mUserActivity.addModel(entry.getKey(), entry.getValue().name);
+ mUserActivity.setModelState(entry.getKey(), entry.getValue().state);
+ }
+ }
+ }
+
+ private synchronized void stopAllRecognitions() {
+ for (ModelInfo modelInfo : mModelInfoMap.values()) {
+ if (modelInfo.detector != null) {
+ Log.i(TAG, "Stopping recognition for " + modelInfo.name);
+ try {
+ modelInfo.detector.stopRecognition();
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to stop recognition", e);
+ }
+ }
+ }
+ }
+
+ // Helper struct for holding information about a model.
+ public static class ModelInfo {
+ public String name;
+ public String state;
+ public UUID modelUuid;
+ public UUID vendorUuid;
+ public MediaPlayer triggerAudioPlayer;
+ public SoundTriggerDetector detector;
+ public byte modelData[];
+ public boolean captureAudio;
+ public int captureAudioMs;
+ public AudioTrack captureAudioTrack;
+ }
+
+ private GenericSoundModel createNewSoundModel(ModelInfo modelInfo) {
+ return new GenericSoundModel(modelInfo.modelUuid, modelInfo.vendorUuid,
+ modelInfo.modelData);
+ }
+
+ public synchronized void loadModel(UUID modelUuid) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ if (modelInfo == null) {
+ postError("Could not find model for: " + modelUuid.toString());
+ return;
+ }
+
+ postMessage("Loading model: " + modelInfo.name);
+
+ GenericSoundModel soundModel = createNewSoundModel(modelInfo);
+
+ boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(soundModel);
+ if (status) {
+ postToast("Successfully loaded " + modelInfo.name + ", UUID=" + soundModel.uuid);
+ setModelState(modelInfo, "Loaded");
+ } else {
+ postErrorToast("Failed to load " + modelInfo.name + ", UUID=" + soundModel.uuid + "!");
+ setModelState(modelInfo, "Failed to load");
+ }
+ }
+
+ public synchronized void unloadModel(UUID modelUuid) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ if (modelInfo == null) {
+ postError("Could not find model for: " + modelUuid.toString());
+ return;
+ }
+
+ postMessage("Unloading model: " + modelInfo.name);
+
+ GenericSoundModel soundModel = mSoundTriggerUtil.getSoundModel(modelUuid);
+ if (soundModel == null) {
+ postErrorToast("Sound model not found for " + modelInfo.name + "!");
+ return;
+ }
+ modelInfo.detector = null;
+ boolean status = mSoundTriggerUtil.deleteSoundModel(modelUuid);
+ if (status) {
+ postToast("Successfully unloaded " + modelInfo.name + ", UUID=" + soundModel.uuid);
+ setModelState(modelInfo, "Unloaded");
+ } else {
+ postErrorToast("Failed to unload " +
+ modelInfo.name + ", UUID=" + soundModel.uuid + "!");
+ setModelState(modelInfo, "Failed to unload");
+ }
+ }
+
+ public synchronized void reloadModel(UUID modelUuid) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ if (modelInfo == null) {
+ postError("Could not find model for: " + modelUuid.toString());
+ return;
+ }
+ postMessage("Reloading model: " + modelInfo.name);
+ GenericSoundModel soundModel = mSoundTriggerUtil.getSoundModel(modelUuid);
+ if (soundModel == null) {
+ postErrorToast("Sound model not found for " + modelInfo.name + "!");
+ return;
+ }
+ GenericSoundModel updated = createNewSoundModel(modelInfo);
+ boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(updated);
+ if (status) {
+ postToast("Successfully reloaded " + modelInfo.name + ", UUID=" + modelInfo.modelUuid);
+ setModelState(modelInfo, "Reloaded");
+ } else {
+ postErrorToast("Failed to reload "
+ + modelInfo.name + ", UUID=" + modelInfo.modelUuid + "!");
+ setModelState(modelInfo, "Failed to reload");
+ }
+ }
+
+ public synchronized void startRecognition(UUID modelUuid) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ if (modelInfo == null) {
+ postError("Could not find model for: " + modelUuid.toString());
+ return;
+ }
+
+ if (modelInfo.detector == null) {
+ postMessage("Creating SoundTriggerDetector for " + modelInfo.name);
+ modelInfo.detector = mSoundTriggerUtil.createSoundTriggerDetector(
+ modelUuid, new DetectorCallback(modelInfo));
+ }
+
+ postMessage("Starting recognition for " + modelInfo.name + ", UUID=" + modelInfo.modelUuid);
+ if (modelInfo.detector.startRecognition(modelInfo.captureAudio ?
+ SoundTriggerDetector.RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO :
+ SoundTriggerDetector.RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS)) {
+ setModelState(modelInfo, "Started");
+ } else {
+ postErrorToast("Fast failure attempting to start recognition for " +
+ modelInfo.name + ", UUID=" + modelInfo.modelUuid);
+ setModelState(modelInfo, "Failed to start");
+ }
+ }
+
+ public synchronized void stopRecognition(UUID modelUuid) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ if (modelInfo == null) {
+ postError("Could not find model for: " + modelUuid.toString());
+ return;
+ }
+
+ if (modelInfo.detector == null) {
+ postErrorToast("Stop called on null detector for " +
+ modelInfo.name + ", UUID=" + modelInfo.modelUuid);
+ return;
+ }
+ postMessage("Triggering stop recognition for " +
+ modelInfo.name + ", UUID=" + modelInfo.modelUuid);
+ if (modelInfo.detector.stopRecognition()) {
+ setModelState(modelInfo, "Stopped");
+ } else {
+ postErrorToast("Fast failure attempting to stop recognition for " +
+ modelInfo.name + ", UUID=" + modelInfo.modelUuid);
+ setModelState(modelInfo, "Failed to stop");
+ }
+ }
+
+ public synchronized void playTriggerAudio(UUID modelUuid) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ if (modelInfo == null) {
+ postError("Could not find model for: " + modelUuid.toString());
+ return;
+ }
+ if (modelInfo.triggerAudioPlayer != null) {
+ postMessage("Playing trigger audio for " + modelInfo.name);
+ modelInfo.triggerAudioPlayer.start();
+ } else {
+ postMessage("No trigger audio for " + modelInfo.name);
+ }
+ }
+
+ public synchronized void playCapturedAudio(UUID modelUuid) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ if (modelInfo == null) {
+ postError("Could not find model for: " + modelUuid.toString());
+ return;
+ }
+ if (modelInfo.captureAudioTrack != null) {
+ postMessage("Playing captured audio for " + modelInfo.name);
+ modelInfo.captureAudioTrack.stop();
+ modelInfo.captureAudioTrack.reloadStaticData();
+ modelInfo.captureAudioTrack.play();
+ } else {
+ postMessage("No captured audio for " + modelInfo.name);
+ }
+ }
+
+ public synchronized void setCaptureAudioTimeout(UUID modelUuid, int captureTimeoutMs) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ if (modelInfo == null) {
+ postError("Could not find model for: " + modelUuid.toString());
+ return;
+ }
+ modelInfo.captureAudioMs = captureTimeoutMs;
+ Log.i(TAG, "Set " + modelInfo.name + " capture audio timeout to " +
+ captureTimeoutMs + "ms");
+ }
+
+ public synchronized void setCaptureAudio(UUID modelUuid, boolean captureAudio) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ if (modelInfo == null) {
+ postError("Could not find model for: " + modelUuid.toString());
+ return;
+ }
+ modelInfo.captureAudio = captureAudio;
+ Log.i(TAG, "Set " + modelInfo.name + " capture audio to " + captureAudio);
+ }
+
+ public synchronized boolean hasMicrophonePermission() {
+ return getBaseContext().checkSelfPermission(Manifest.permission.RECORD_AUDIO)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ public synchronized boolean modelHasTriggerAudio(UUID modelUuid) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ return modelInfo != null && modelInfo.triggerAudioPlayer != null;
+ }
+
+ public synchronized boolean modelWillCaptureTriggerAudio(UUID modelUuid) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ return modelInfo != null && modelInfo.captureAudio;
+ }
+
+ public synchronized boolean modelHasCapturedAudio(UUID modelUuid) {
+ ModelInfo modelInfo = mModelInfoMap.get(modelUuid);
+ return modelInfo != null && modelInfo.captureAudioTrack != null;
+ }
+
+ private void loadModelsInDataDir() {
+ // Load all the models in the data dir.
+ boolean loadedModel = false;
+ for (File file : getFilesDir().listFiles()) {
+ // Find meta-data in .properties files, ignore everything else.
+ if (!file.getName().endsWith(".properties")) {
+ continue;
+ }
+ try {
+ Properties properties = new Properties();
+ properties.load(new FileInputStream(file));
+ createModelInfo(properties);
+ loadedModel = true;
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to load properties file " + file.getName());
+ }
+ }
+
+ // Create a few dummy models if we didn't load anything.
+ if (!loadedModel) {
+ Properties dummyModelProperties = new Properties();
+ for (String name : new String[]{"1", "2", "3"}) {
+ dummyModelProperties.setProperty("name", "Model " + name);
+ createModelInfo(dummyModelProperties);
+ }
+ }
+ }
+
+ /** Parses a Properties collection to generate a sound model.
+ *
+ * Missing keys are filled in with default/random values.
+ * @param properties Has the required 'name' property, but the remaining 'modelUuid',
+ * 'vendorUuid', 'triggerAudio', and 'dataFile' optional properties.
+ *
+ */
+ private synchronized void createModelInfo(Properties properties) {
+ try {
+ ModelInfo modelInfo = new ModelInfo();
+
+ if (!properties.containsKey("name")) {
+ throw new RuntimeException("must have a 'name' property");
+ }
+ modelInfo.name = properties.getProperty("name");
+
+ if (properties.containsKey("modelUuid")) {
+ modelInfo.modelUuid = UUID.fromString(properties.getProperty("modelUuid"));
+ } else {
+ modelInfo.modelUuid = UUID.randomUUID();
+ }
+
+ if (properties.containsKey("vendorUuid")) {
+ modelInfo.vendorUuid = UUID.fromString(properties.getProperty("vendorUuid"));
+ } else {
+ modelInfo.vendorUuid = UUID.randomUUID();
+ }
+
+ if (properties.containsKey("triggerAudio")) {
+ modelInfo.triggerAudioPlayer = MediaPlayer.create(this, Uri.parse(
+ getFilesDir().getPath() + "/" + properties.getProperty("triggerAudio")));
+ if (modelInfo.triggerAudioPlayer.getDuration() == 0) {
+ modelInfo.triggerAudioPlayer.release();
+ modelInfo.triggerAudioPlayer = null;
+ }
+ }
+
+ if (properties.containsKey("dataFile")) {
+ File modelDataFile = new File(
+ getFilesDir().getPath() + "/" + properties.getProperty("dataFile"));
+ modelInfo.modelData = new byte[(int) modelDataFile.length()];
+ FileInputStream input = new FileInputStream(modelDataFile);
+ input.read(modelInfo.modelData, 0, modelInfo.modelData.length);
+ } else {
+ modelInfo.modelData = new byte[1024];
+ mRandom.nextBytes(modelInfo.modelData);
+ }
+
+ modelInfo.captureAudioMs = Integer.parseInt((String) properties.getOrDefault(
+ "captureAudioDurationMs", "5000"));
+
+ // TODO: Add property support for keyphrase models when they're exposed by the
+ // service.
+
+ // Update our maps containing the button -> id and id -> modelInfo.
+ mModelInfoMap.put(modelInfo.modelUuid, modelInfo);
+ if (mUserActivity != null) {
+ mUserActivity.addModel(modelInfo.modelUuid, modelInfo.name);
+ mUserActivity.setModelState(modelInfo.modelUuid, modelInfo.state);
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Error parsing properties for " + properties.getProperty("name"), e);
+ }
+ }
+
+ private class CaptureAudioRecorder implements Runnable {
+ private final ModelInfo mModelInfo;
+ private final SoundTriggerDetector.EventPayload mEvent;
+
+ public CaptureAudioRecorder(ModelInfo modelInfo, SoundTriggerDetector.EventPayload event) {
+ mModelInfo = modelInfo;
+ mEvent = event;
+ }
+
+ @Override
+ public void run() {
+ AudioFormat format = mEvent.getCaptureAudioFormat();
+ if (format == null) {
+ postErrorToast("No audio format in recognition event.");
+ return;
+ }
+
+ AudioRecord audioRecord = null;
+ AudioTrack playbackTrack = null;
+ try {
+ // Inform the audio flinger that we really do want the stream from the soundtrigger.
+ AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder();
+ attributesBuilder.setInternalCapturePreset(1999);
+ AudioAttributes attributes = attributesBuilder.build();
+
+ // Make sure we understand this kind of playback so we know how many bytes to read.
+ String encoding;
+ int bytesPerSample;
+ switch (format.getEncoding()) {
+ case AudioFormat.ENCODING_PCM_8BIT:
+ encoding = "8bit";
+ bytesPerSample = 1;
+ break;
+ case AudioFormat.ENCODING_PCM_16BIT:
+ encoding = "16bit";
+ bytesPerSample = 2;
+ break;
+ case AudioFormat.ENCODING_PCM_FLOAT:
+ encoding = "float";
+ bytesPerSample = 4;
+ break;
+ default:
+ throw new RuntimeException("Unhandled audio format in event");
+ }
+
+ int bytesRequired = format.getSampleRate() * format.getChannelCount() *
+ bytesPerSample * mModelInfo.captureAudioMs / 1000;
+ int minBufferSize = AudioRecord.getMinBufferSize(
+ format.getSampleRate(), format.getChannelMask(), format.getEncoding());
+ if (minBufferSize > bytesRequired) {
+ bytesRequired = minBufferSize;
+ }
+
+ // Make an AudioTrack so we can play the data back out after it's finished
+ // recording.
+ try {
+ int channelConfig = AudioFormat.CHANNEL_OUT_MONO;
+ if (format.getChannelCount() == 2) {
+ channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
+ } else if (format.getChannelCount() >= 3) {
+ throw new RuntimeException(
+ "Too many channels in captured audio for playback");
+ }
+
+ playbackTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
+ format.getSampleRate(), channelConfig, format.getEncoding(),
+ bytesRequired, AudioTrack.MODE_STATIC);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception creating playback track", e);
+ postErrorToast("Failed to create playback track: " + e.getMessage());
+ }
+
+ audioRecord = new AudioRecord(attributes, format, bytesRequired,
+ mEvent.getCaptureSession());
+
+ byte[] buffer = new byte[bytesRequired];
+
+ // Create a file so we can save the output data there for analysis later.
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream( new File(
+ getFilesDir() + File.separator + mModelInfo.name.replace(' ', '_') +
+ "_capture_" + format.getChannelCount() + "ch_" +
+ format.getSampleRate() + "hz_" + encoding + ".pcm"));
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to open output for saving PCM data", e);
+ postErrorToast("Failed to open output for saving PCM data: " + e.getMessage());
+ }
+
+ // Inform the user we're recording.
+ setModelState(mModelInfo, "Recording");
+ audioRecord.startRecording();
+ while (bytesRequired > 0) {
+ int bytesRead = audioRecord.read(buffer, 0, buffer.length);
+ if (bytesRead == -1) {
+ break;
+ }
+ if (fos != null) {
+ fos.write(buffer, 0, bytesRead);
+ }
+ if (playbackTrack != null) {
+ playbackTrack.write(buffer, 0, bytesRead);
+ }
+ bytesRequired -= bytesRead;
+ }
+ audioRecord.stop();
+ } catch (Exception e) {
+ Log.e(TAG, "Error recording trigger audio", e);
+ postErrorToast("Error recording trigger audio: " + e.getMessage());
+ } finally {
+ if (audioRecord != null) {
+ audioRecord.release();
+ }
+ synchronized (SoundTriggerTestService.this) {
+ if (mModelInfo.captureAudioTrack != null) {
+ mModelInfo.captureAudioTrack.release();
+ }
+ mModelInfo.captureAudioTrack = playbackTrack;
+ }
+ setModelState(mModelInfo, "Recording finished");
+ }
+ }
+ }
+
+ // Implementation of SoundTriggerDetector.Callback.
+ private class DetectorCallback extends SoundTriggerDetector.Callback {
+ private final ModelInfo mModelInfo;
+
+ public DetectorCallback(ModelInfo modelInfo) {
+ mModelInfo = modelInfo;
+ }
+
+ public void onAvailabilityChanged(int status) {
+ postMessage(mModelInfo.name + " availability changed to: " + status);
+ }
+
+ public void onDetected(SoundTriggerDetector.EventPayload event) {
+ postMessage(mModelInfo.name + " onDetected(): " + eventPayloadToString(event));
+ synchronized (SoundTriggerTestService.this) {
+ if (mUserActivity != null) {
+ mUserActivity.handleDetection(mModelInfo.modelUuid);
+ }
+ if (mModelInfo.captureAudio) {
+ new Thread(new CaptureAudioRecorder(mModelInfo, event)).start();
+ }
+ }
+ }
+
+ public void onError() {
+ postMessage(mModelInfo.name + " onError()");
+ setModelState(mModelInfo, "Error");
+ }
+
+ public void onRecognitionPaused() {
+ postMessage(mModelInfo.name + " onRecognitionPaused()");
+ setModelState(mModelInfo, "Paused");
+ }
+
+ public void onRecognitionResumed() {
+ postMessage(mModelInfo.name + " onRecognitionResumed()");
+ setModelState(mModelInfo, "Resumed");
+ }
+ }
+
+ private String eventPayloadToString(SoundTriggerDetector.EventPayload event) {
+ String result = "EventPayload(";
+ AudioFormat format = event.getCaptureAudioFormat();
+ result = result + "AudioFormat: " + ((format == null) ? "null" : format.toString());
+ byte[] triggerAudio = event.getTriggerAudio();
+ result = result + "TriggerAudio: " + (triggerAudio == null ? "null" : triggerAudio.length);
+ result = result + "CaptureSession: " + event.getCaptureSession();
+ result += " )";
+ return result;
+ }
+
+ private void postMessage(String msg) {
+ showMessage(msg, Log.INFO, false);
+ }
+
+ private void postError(String msg) {
+ showMessage(msg, Log.ERROR, false);
+ }
+
+ private void postToast(String msg) {
+ showMessage(msg, Log.INFO, true);
+ }
+
+ private void postErrorToast(String msg) {
+ showMessage(msg, Log.ERROR, true);
+ }
+
+ /** Logs the message at the specified level, then forwards it to the activity if present. */
+ private synchronized void showMessage(String msg, int logLevel, boolean showToast) {
+ Log.println(logLevel, TAG, msg);
+ if (mUserActivity != null) {
+ mUserActivity.showMessage(msg, showToast);
+ }
+ }
+
+ private synchronized void setModelState(ModelInfo modelInfo, String state) {
+ modelInfo.state = state;
+ if (mUserActivity != null) {
+ mUserActivity.setModelState(modelInfo.modelUuid, modelInfo.state);
+ }
+ }
+}
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java
index 1c95c25370d2..8e5ed3210ab0 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerUtil.java
@@ -18,7 +18,6 @@ package com.android.test.soundtrigger;
import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.soundtrigger.SoundTrigger;
import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
import android.media.soundtrigger.SoundTriggerDetector;
import android.media.soundtrigger.SoundTriggerManager;
@@ -36,7 +35,7 @@ import java.util.UUID;
* Utility class for the managing sound trigger sound models.
*/
public class SoundTriggerUtil {
- private static final String TAG = "TestSoundTriggerUtil:Hotsound";
+ private static final String TAG = "SoundTriggerTestUtil";
private final ISoundTriggerService mSoundTriggerService;
private final SoundTriggerManager mSoundTriggerManager;
@@ -68,10 +67,6 @@ public class SoundTriggerUtil {
return true;
}
- public void addOrUpdateSoundModel(SoundTriggerManager.Model soundModel) {
- mSoundTriggerManager.updateModel(soundModel);
- }
-
/**
* Gets the sound model for the given keyphrase, null if none exists.
* If a sound model for a given keyphrase exists, and it needs to be updated,
@@ -91,7 +86,7 @@ public class SoundTriggerUtil {
}
if (model == null) {
- Log.w(TAG, "No models present for the gien keyphrase ID");
+ Log.w(TAG, "No models present for the given keyphrase ID");
return null;
} else {
return model;
@@ -109,18 +104,14 @@ public class SoundTriggerUtil {
try {
mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelId));
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in updateSoundModel");
+ Log.e(TAG, "RemoteException in deleteSoundModel");
+ return false;
}
return true;
}
- public void deleteSoundModelUsingManager(UUID modelId) {
- mSoundTriggerManager.deleteModel(modelId);
- }
-
public SoundTriggerDetector createSoundTriggerDetector(UUID modelId,
SoundTriggerDetector.Callback callback) {
return mSoundTriggerManager.createSoundTriggerDetector(modelId, callback, null);
}
-
}
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
deleted file mode 100644
index 5fd38e953fda..000000000000
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.test.soundtrigger;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Random;
-import java.util.UUID;
-
-import android.app.Activity;
-import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
-import android.hardware.soundtrigger.SoundTrigger;
-import android.media.AudioFormat;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.media.soundtrigger.SoundTriggerDetector;
-import android.media.soundtrigger.SoundTriggerManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.PowerManager;
-import android.os.UserManager;
-import android.text.Editable;
-import android.text.method.ScrollingMovementMethod;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-import android.widget.RadioButton;
-import android.widget.RadioButton;
-import android.widget.RadioGroup;
-import android.widget.ScrollView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-public class TestSoundTriggerActivity extends Activity {
- private static final String TAG = "TestSoundTriggerActivity";
- private static final boolean DBG = false;
-
- private SoundTriggerUtil mSoundTriggerUtil;
- private Random mRandom;
-
- private Map<Integer, ModelInfo> mModelInfoMap;
- private Map<View, Integer> mModelIdMap;
-
- private TextView mDebugView = null;
- private int mSelectedModelId = -1;
- private ScrollView mScrollView = null;
- private Button mPlayTriggerButton = null;
- private PowerManager.WakeLock mScreenWakelock;
- private Handler mHandler;
- private RadioGroup mRadioGroup;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- if (DBG) Log.d(TAG, "onCreate");
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- mDebugView = (TextView) findViewById(R.id.console);
- mScrollView = (ScrollView) findViewById(R.id.scroller_id);
- mRadioGroup = (RadioGroup) findViewById(R.id.model_group_id);
- mPlayTriggerButton = (Button) findViewById(R.id.play_trigger_id);
- mDebugView.setText(mDebugView.getText(), TextView.BufferType.EDITABLE);
- mDebugView.setMovementMethod(new ScrollingMovementMethod());
- mSoundTriggerUtil = new SoundTriggerUtil(this);
- mRandom = new Random();
- mHandler = new Handler();
-
- mModelInfoMap = new HashMap();
- mModelIdMap = new HashMap();
-
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
-
- // Load all the models in the data dir.
- for (File file : getFilesDir().listFiles()) {
- // Find meta-data in .properties files, ignore everything else.
- if (!file.getName().endsWith(".properties")) {
- continue;
- }
- try {
- Properties properties = new Properties();
- properties.load(new FileInputStream(file));
- createModelInfoAndWidget(properties);
- } catch (Exception e) {
- Log.e(TAG, "Failed to load properties file " + file.getName());
- }
- }
-
- // Create a few dummy models if we didn't load anything.
- if (mModelIdMap.isEmpty()) {
- Properties dummyModelProperties = new Properties();
- for (String name : new String[]{"One", "Two", "Three"}) {
- dummyModelProperties.setProperty("name", "Model " + name);
- createModelInfoAndWidget(dummyModelProperties);
- }
- }
- }
-
- private void createModelInfoAndWidget(Properties properties) {
- try {
- ModelInfo modelInfo = new ModelInfo();
-
- if (!properties.containsKey("name")) {
- throw new RuntimeException("must have a 'name' property");
- }
- modelInfo.name = properties.getProperty("name");
-
- if (properties.containsKey("modelUuid")) {
- modelInfo.modelUuid = UUID.fromString(properties.getProperty("modelUuid"));
- } else {
- modelInfo.modelUuid = UUID.randomUUID();
- }
-
- if (properties.containsKey("vendorUuid")) {
- modelInfo.vendorUuid = UUID.fromString(properties.getProperty("vendorUuid"));
- } else {
- modelInfo.vendorUuid = UUID.randomUUID();
- }
-
- if (properties.containsKey("triggerAudio")) {
- modelInfo.triggerAudioPlayer = MediaPlayer.create(this, Uri.parse(
- getFilesDir().getPath() + "/" + properties.getProperty("triggerAudio")));
- }
-
- if (properties.containsKey("dataFile")) {
- File modelDataFile = new File(
- getFilesDir().getPath() + "/" + properties.getProperty("dataFile"));
- modelInfo.modelData = new byte[(int) modelDataFile.length()];
- FileInputStream input = new FileInputStream(modelDataFile);
- input.read(modelInfo.modelData, 0, modelInfo.modelData.length);
- } else {
- modelInfo.modelData = new byte[1024];
- mRandom.nextBytes(modelInfo.modelData);
- }
-
- // TODO: Add property support for keyphrase models when they're exposed by the
- // service. Also things like how much audio they should record with the capture session
- // provided in the callback.
-
- // Add a widget into the radio group.
- RadioButton button = new RadioButton(this);
- mRadioGroup.addView(button);
- button.setText(modelInfo.name);
- button.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- onRadioButtonClicked(v);
- }
- });
-
- // Update our maps containing the button -> id and id -> modelInfo.
- int newModelId = mModelIdMap.size() + 1;
- mModelIdMap.put(button, newModelId);
- mModelInfoMap.put(newModelId, modelInfo);
-
- // If we don't have something selected, select this first thing.
- if (mSelectedModelId < 0) {
- button.setChecked(true);
- onRadioButtonClicked(button);
- }
- } catch (IOException e) {
- Log.e(TAG, "Error parsing properties for " + properties.getProperty("name"), e);
- }
- }
-
- private void postMessage(String msg) {
- Log.i(TAG, "Posted: " + msg);
- ((Editable) mDebugView.getText()).append(msg + "\n");
- if ((mDebugView.getMeasuredHeight() - mScrollView.getScrollY()) <=
- (mScrollView.getHeight() + mDebugView.getLineHeight())) {
- scrollToBottom();
- }
- }
-
- private void scrollToBottom() {
- mScrollView.post(new Runnable() {
- public void run() {
- mScrollView.smoothScrollTo(0, mDebugView.getBottom());
- }
- });
- }
-
- private synchronized UUID getSelectedUuid() {
- return mModelInfoMap.get(mSelectedModelId).modelUuid;
- }
-
- private synchronized void setDetector(SoundTriggerDetector detector) {
- mModelInfoMap.get(mSelectedModelId).detector = detector;
- }
-
- private synchronized SoundTriggerDetector getDetector() {
- return mModelInfoMap.get(mSelectedModelId).detector;
- }
-
- private void screenWakeup() {
- PowerManager pm = ((PowerManager)getSystemService(POWER_SERVICE));
- if (mScreenWakelock == null) {
- mScreenWakelock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG");
- }
- mScreenWakelock.acquire();
- }
-
- private void screenRelease() {
- PowerManager pm = ((PowerManager)getSystemService(POWER_SERVICE));
- mScreenWakelock.release();
- }
-
- /** TODO: Should return the abstract sound model that can be then sent to the service. */
- private GenericSoundModel createNewSoundModel() {
- ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId);
- return new GenericSoundModel(modelInfo.modelUuid, modelInfo.vendorUuid,
- modelInfo.modelData);
- }
-
- /**
- * Called when the user clicks the enroll button.
- * Performs a fresh enrollment.
- */
- public void onEnrollButtonClicked(View v) {
- postMessage("Loading model: " + mSelectedModelId);
-
- GenericSoundModel model = createNewSoundModel();
-
- boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(model);
- if (status) {
- Toast.makeText(
- this, "Successfully created sound trigger model UUID=" + model.uuid,
- Toast.LENGTH_SHORT).show();
- } else {
- Toast.makeText(this, "Failed to enroll!!!" + model.uuid, Toast.LENGTH_SHORT).show();
- }
-
- // Test the SoundManager API.
- }
-
- /**
- * Called when the user clicks the un-enroll button.
- * Clears the enrollment information for the user.
- */
- public void onUnEnrollButtonClicked(View v) {
- postMessage("Unloading model: " + mSelectedModelId);
- UUID modelUuid = getSelectedUuid();
- GenericSoundModel soundModel = mSoundTriggerUtil.getSoundModel(modelUuid);
- if (soundModel == null) {
- Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show();
- return;
- }
- boolean status = mSoundTriggerUtil.deleteSoundModel(modelUuid);
- if (status) {
- Toast.makeText(this, "Successfully deleted model UUID=" + soundModel.uuid,
- Toast.LENGTH_SHORT)
- .show();
- } else {
- Toast.makeText(this, "Failed to delete sound model!!!", Toast.LENGTH_SHORT).show();
- }
- }
-
- /**
- * Called when the user clicks the re-enroll button.
- * Uses the previously enrolled sound model and makes changes to it before pushing it back.
- */
- public void onReEnrollButtonClicked(View v) {
- postMessage("Re-loading model: " + mSelectedModelId);
- UUID modelUuid = getSelectedUuid();
- GenericSoundModel soundModel = mSoundTriggerUtil.getSoundModel(modelUuid);
- if (soundModel == null) {
- Toast.makeText(this, "Sound model not found!!!", Toast.LENGTH_SHORT).show();
- return;
- }
- GenericSoundModel updated = createNewSoundModel();
- boolean status = mSoundTriggerUtil.addOrUpdateSoundModel(updated);
- if (status) {
- Toast.makeText(this, "Successfully re-enrolled, model UUID=" + updated.uuid,
- Toast.LENGTH_SHORT)
- .show();
- } else {
- Toast.makeText(this, "Failed to re-enroll!!!", Toast.LENGTH_SHORT).show();
- }
- }
-
- public void onStartRecognitionButtonClicked(View v) {
- UUID modelUuid = getSelectedUuid();
- SoundTriggerDetector detector = getDetector();
- if (detector == null) {
- Log.i(TAG, "Created an instance of the SoundTriggerDetector for model #" +
- mSelectedModelId);
- postMessage("Created an instance of the SoundTriggerDetector for model #" +
- mSelectedModelId);
- detector = mSoundTriggerUtil.createSoundTriggerDetector(modelUuid,
- new DetectorCallback());
- setDetector(detector);
- }
- postMessage("Triggering start recognition for model: " + mSelectedModelId);
- if (!detector.startRecognition(
- SoundTriggerDetector.RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS)) {
- Log.e(TAG, "Fast failure attempting to start recognition.");
- postMessage("Fast failure attempting to start recognition:" + mSelectedModelId);
- }
- }
-
- public void onStopRecognitionButtonClicked(View v) {
- SoundTriggerDetector detector = getDetector();
- if (detector == null) {
- Log.e(TAG, "Stop called on null detector.");
- postMessage("Error: Stop called on null detector.");
- return;
- }
- postMessage("Triggering stop recognition for model: " + mSelectedModelId);
- if (!detector.stopRecognition()) {
- Log.e(TAG, "Fast failure attempting to stop recognition.");
- postMessage("Fast failure attempting to stop recognition: " + mSelectedModelId);
- }
- }
-
- public synchronized void onRadioButtonClicked(View view) {
- // Is the button now checked?
- boolean checked = ((RadioButton) view).isChecked();
- if (checked) {
- mSelectedModelId = mModelIdMap.get(view);
- ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId);
- postMessage("Selected " + modelInfo.name);
-
- // Set the play trigger button to be enabled only if we actually have some audio.
- mPlayTriggerButton.setEnabled(modelInfo.triggerAudioPlayer != null);
- }
- }
-
- public synchronized void onPlayTriggerButtonClicked(View v) {
- ModelInfo modelInfo = mModelInfoMap.get(mSelectedModelId);
- modelInfo.triggerAudioPlayer.start();
- postMessage("Playing trigger audio for " + modelInfo.name);
- }
-
- // Helper struct for holding information about a model.
- private static class ModelInfo {
- public String name;
- public UUID modelUuid;
- public UUID vendorUuid;
- public MediaPlayer triggerAudioPlayer;
- public SoundTriggerDetector detector;
- public byte modelData[];
- };
-
- // Implementation of SoundTriggerDetector.Callback.
- public class DetectorCallback extends SoundTriggerDetector.Callback {
- public void onAvailabilityChanged(int status) {
- postMessage("Availability changed to: " + status);
- }
-
- public void onDetected(SoundTriggerDetector.EventPayload event) {
- postMessage("onDetected(): " + eventPayloadToString(event));
- screenWakeup();
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- screenRelease();
- }
- }, 1000L);
- }
-
- public void onError() {
- postMessage("onError()");
- }
-
- public void onRecognitionPaused() {
- postMessage("onRecognitionPaused()");
- }
-
- public void onRecognitionResumed() {
- postMessage("onRecognitionResumed()");
- }
- }
-
- private String eventPayloadToString(SoundTriggerDetector.EventPayload event) {
- String result = "EventPayload(";
- AudioFormat format = event.getCaptureAudioFormat();
- result = result + "AudioFormat: " + ((format == null) ? "null" : format.toString());
- byte[] triggerAudio = event.getTriggerAudio();
- result = result + "TriggerAudio: " + (triggerAudio == null ? "null" : triggerAudio.length);
- result = result + "CaptureSession: " + event.getCaptureSession();
- result += " )";
- return result;
- }
-}
diff --git a/tests/UiBench/src/com/android/test/uibench/MainActivity.java b/tests/UiBench/src/com/android/test/uibench/MainActivity.java
index 2111274a93c0..79837b6ea250 100644
--- a/tests/UiBench/src/com/android/test/uibench/MainActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/MainActivity.java
@@ -38,6 +38,23 @@ public class MainActivity extends AppCompatActivity {
private static final String EXTRA_PATH = "activity_path";
private static final String CATEGORY_HWUI_TEST = "com.android.test.uibench.TEST";
+ public static class TestListFragment extends ListFragment {
+ @Override
+ @SuppressWarnings("unchecked")
+ public void onListItemClick(ListView l, View v, int position, long id) {
+ Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position);
+
+ Intent intent = (Intent) map.get("intent");
+ startActivity(intent);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ getListView().setTextFilterEnabled(true);
+ }
+ }
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -54,22 +71,7 @@ public class MainActivity extends AppCompatActivity {
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentById(android.R.id.content) == null) {
- ListFragment listFragment = new ListFragment() {
- @Override
- @SuppressWarnings("unchecked")
- public void onListItemClick(ListView l, View v, int position, long id) {
- Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position);
-
- Intent intent = (Intent) map.get("intent");
- startActivity(intent);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- getListView().setTextFilterEnabled(true);
- }
- };
+ ListFragment listFragment = new TestListFragment();
listFragment.setListAdapter(new SimpleAdapter(this, getData(path),
android.R.layout.simple_list_item_1, new String[] { "title" },
new int[] { android.R.id.text1 }));
diff --git a/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java b/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java
index d32f0716fe98..88847eed17fa 100644
--- a/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java
+++ b/tests/UiBench/src/com/android/test/uibench/ShadowGridActivity.java
@@ -23,19 +23,22 @@ import android.view.View;
import android.widget.ArrayAdapter;
public class ShadowGridActivity extends AppCompatActivity {
+ public static class NoDividerListFragment extends ListFragment {
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ getListView().setDivider(null);
+ }
+ };
+
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentById(android.R.id.content) == null) {
- ListFragment listFragment = new ListFragment() {
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- getListView().setDivider(null);
- }
- };
+ ListFragment listFragment = new NoDividerListFragment();
listFragment.setListAdapter(new ArrayAdapter<>(this,
R.layout.card_row, R.id.card_text, TextUtils.buildSimpleStringList()));
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index b7014454771c..2a490d1097ef 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -57,8 +57,8 @@ aaptTests := \
aaptHostStaticLibs := \
libandroidfw \
libpng \
- liblog \
libutils \
+ liblog \
libcutils \
libexpat \
libziparchive-host \
diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp
index 7b0c71d93bb5..5a87c334c59e 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -441,8 +441,10 @@ std::string utf16ToUtf8(const StringPiece16& utf16) {
}
std::string utf8;
+ // Make room for '\0' explicitly.
+ utf8.resize(utf8Length + 1);
+ utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8Length + 1);
utf8.resize(utf8Length);
- utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin());
return utf8;
}
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index ea36e2cb0d6a..2956d87f247c 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -256,23 +256,33 @@ def parse_fonts_xml(fonts_xml_path):
def check_emoji_coverage(all_emoji, equivalent_emoji):
+ emoji_font = get_emoji_font()
+ check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji)
+
+
+def get_emoji_font():
emoji_fonts = [
record.font for record in _fallback_chain
if 'Zsye' in record.scripts]
assert len(emoji_fonts) == 1, 'There are %d emoji fonts.' % len(emoji_fonts)
- emoji_font = emoji_fonts[0]
- coverage = get_emoji_map(emoji_font)
+ return emoji_fonts[0]
+
+def check_emoji_font_coverage(emoji_font, all_emoji, equivalent_emoji):
+ coverage = get_emoji_map(emoji_font)
for sequence in all_emoji:
assert sequence in coverage, (
'%s is not supported in the emoji font.' % printable(sequence))
+ # disable temporarily - we cover more than this
+ """
for sequence in coverage:
if sequence in {0x0000, 0x000D, 0x0020}:
# The font needs to support a few extra characters, which is OK
continue
assert sequence in all_emoji, (
'Emoji font should not support %s.' % printable(sequence))
+ """
for first, second in sorted(equivalent_emoji.items()):
assert coverage[first] == coverage[second], (
@@ -280,6 +290,8 @@ def check_emoji_coverage(all_emoji, equivalent_emoji):
printable(first),
printable(second)))
+ # disable temporarily - some equivalent sequences we don't even know about
+ """
for glyph in set(coverage.values()):
maps_to_glyph = [seq for seq in coverage if coverage[seq] == glyph]
if len(maps_to_glyph) > 1:
@@ -295,7 +307,7 @@ def check_emoji_coverage(all_emoji, equivalent_emoji):
'The sequences %s should not result in the same glyph %s' % (
printable(equivalent_seqs),
glyph))
-
+ """
def check_emoji_defaults(default_emoji):
missing_text_chars = _emoji_properties['Emoji'] - default_emoji
@@ -427,6 +439,11 @@ def parse_ucd(ucd_path):
_emoji_sequences = dict(
(t, v) for (t, v) in _emoji_sequences.items() if not contains_excluded(t))
+ # add in UN flag
+ UN_seq = flag_sequence('UN')
+ _emoji_sequences[UN_seq] = 'Emoji_Flag_Sequence'
+
+
def flag_sequence(territory_code):
return tuple(0x1F1E6 + ord(ch) - ord('A') for ch in territory_code)
@@ -483,6 +500,11 @@ ZWJ_IDENTICALS = {
(0x1F468, 0x200D, 0x1F469, 0x200D, 0x1F466): 0x1F46A,
}
+
+def is_fitzpatrick_modifier(cp):
+ return 0x1f3fb <= cp <= 0x1f3ff
+
+
def compute_expected_emoji():
equivalent_emoji = {}
sequence_pieces = set()
@@ -500,7 +522,15 @@ def compute_expected_emoji():
sequence_pieces.update(sequence)
# Add reverse of all emoji ZWJ sequences, which are added to the fonts
# as a workaround to get the sequences work in RTL text.
- reversed_seq = tuple(reversed(sequence))
+ reversed_seq = list(reversed(sequence))
+ # if there are fitzpatrick modifiers in the sequence, keep them after
+ # the emoji they modify
+ for i in xrange(1, len(reversed_seq)):
+ if is_fitzpatrick_modifier(reversed_seq[i - 1]):
+ tmp = reversed_seq[i]
+ reversed_seq[i] = reversed_seq[i-1]
+ reversed_seq[i-1] = tmp
+ reversed_seq = tuple(reversed_seq)
all_sequences.add(reversed_seq)
equivalent_emoji[reversed_seq] = sequence
@@ -536,8 +566,8 @@ def compute_expected_emoji():
def main():
- target_out = sys.argv[1]
global _fonts_dir
+ target_out = sys.argv[1]
_fonts_dir = path.join(target_out, 'fonts')
fonts_xml_path = path.join(target_out, 'etc', 'fonts.xml')
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 4e4da8bb3f08..49ab9f911833 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -590,4 +590,9 @@ public class IWindowManagerImpl implements IWindowManager {
@Override
public void removeWallpaperInputConsumer() throws RemoteException {}
+
+ @Override
+ public Bitmap screenshotWallpaper() throws RemoteException {
+ return null;
+ }
}
diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk
index 239bed589412..863abae1e0fb 100644
--- a/tools/split-select/Android.mk
+++ b/tools/split-select/Android.mk
@@ -47,8 +47,8 @@ hostStaticLibs := \
libaapt \
libandroidfw \
libpng \
- liblog \
libutils \
+ liblog \
libcutils \
libexpat \
libziparchive-host \