summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/am/src/com/android/commands/am/Instrument.java1
-rw-r--r--cmds/screencap/screencap.cpp4
-rw-r--r--core/java/android/app/Activity.java32
-rw-r--r--core/java/android/app/ActivityManager.java7
-rw-r--r--core/java/android/app/ActivityThread.java68
-rw-r--r--core/java/android/app/Application.java82
-rw-r--r--core/java/android/app/ContextImpl.java36
-rw-r--r--core/java/android/app/LoadedApk.java23
-rw-r--r--core/java/android/app/PendingIntent.java2
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java9
-rw-r--r--core/java/android/app/assist/AssistStructure.java3
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeAdvertiser.java2
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeScanner.java5
-rw-r--r--core/java/android/companion/CompanionDeviceManager.java7
-rw-r--r--core/java/android/content/Context.java6
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--core/java/android/content/Intent.java9
-rw-r--r--core/java/android/content/SyncStatusInfo.java56
-rw-r--r--core/java/android/content/pm/LauncherActivityInfo.java10
-rw-r--r--core/java/android/content/pm/PackageParser.java4
-rw-r--r--core/java/android/content/res/Configuration.java25
-rw-r--r--core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java226
-rw-r--r--core/java/android/hardware/display/DisplayManager.java9
-rw-r--r--core/java/android/hardware/usb/UsbManager.java1
-rw-r--r--core/java/android/net/ConnectivityManager.java24
-rw-r--r--core/java/android/os/Debug.java4
-rw-r--r--core/java/android/os/FileUtils.java10
-rw-r--r--core/java/android/os/RecoverySystem.java99
-rw-r--r--core/java/android/os/StrictMode.java13
-rw-r--r--core/java/android/provider/AlarmClock.java22
-rwxr-xr-xcore/java/android/provider/Settings.java24
-rw-r--r--core/java/android/service/autofill/AutofillService.java262
-rw-r--r--core/java/android/service/autofill/Dataset.java50
-rw-r--r--core/java/android/service/autofill/FillContext.java1
-rw-r--r--core/java/android/service/autofill/FillEventHistory.java36
-rw-r--r--core/java/android/service/autofill/FillRequest.java38
-rw-r--r--core/java/android/service/autofill/FillResponse.java121
-rw-r--r--core/java/android/service/autofill/SaveInfo.java102
-rw-r--r--core/java/android/service/euicc/EuiccService.java4
-rw-r--r--core/java/android/view/Display.java4
-rw-r--r--core/java/android/view/DisplayEventReceiver.java9
-rw-r--r--core/java/android/view/HapticFeedbackConstants.java6
-rw-r--r--core/java/android/view/MotionEvent.java8
-rw-r--r--core/java/android/view/SurfaceView.java5
-rw-r--r--core/java/android/view/View.java3
-rw-r--r--core/java/android/view/ViewRootImpl.java30
-rw-r--r--core/java/android/view/WindowManagerInternal.java5
-rw-r--r--core/java/android/widget/ListPopupWindow.java11
-rw-r--r--core/java/android/widget/TextView.java6
-rw-r--r--core/java/com/android/internal/app/NightDisplayController.java4
-rw-r--r--core/java/com/android/internal/util/NotificationColorUtil.java4
-rw-r--r--core/java/com/android/internal/view/TooltipPopup.java4
-rw-r--r--core/jni/android/graphics/ColorFilter.cpp11
-rw-r--r--core/jni/android_os_HwBinder.cpp58
-rw-r--r--core/jni/android_os_HwBinder.h9
-rw-r--r--core/jni/android_os_HwParcel.cpp6
-rw-r--r--core/jni/android_os_HwParcel.h1
-rw-r--r--core/jni/android_os_HwRemoteBinder.cpp4
-rw-r--r--core/jni/android_os_HwRemoteBinder.h1
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/res/res/layout-land/time_picker_material.xml2
-rw-r--r--core/res/res/values-af/strings.xml9
-rw-r--r--core/res/res/values-am/strings.xml9
-rw-r--r--core/res/res/values-ar/strings.xml9
-rw-r--r--core/res/res/values-az/strings.xml9
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml9
-rw-r--r--core/res/res/values-be/strings.xml9
-rw-r--r--core/res/res/values-bg/strings.xml9
-rw-r--r--core/res/res/values-bn/strings.xml11
-rw-r--r--core/res/res/values-bs/strings.xml9
-rw-r--r--core/res/res/values-ca/strings.xml25
-rw-r--r--core/res/res/values-cs/strings.xml9
-rw-r--r--core/res/res/values-da/strings.xml9
-rw-r--r--core/res/res/values-de/strings.xml9
-rw-r--r--core/res/res/values-el/strings.xml9
-rw-r--r--core/res/res/values-en-rAU/strings.xml9
-rw-r--r--core/res/res/values-en-rGB/strings.xml9
-rw-r--r--core/res/res/values-en-rIN/strings.xml9
-rw-r--r--core/res/res/values-es-rUS/strings.xml9
-rw-r--r--core/res/res/values-es/strings.xml9
-rw-r--r--core/res/res/values-et/strings.xml9
-rw-r--r--core/res/res/values-eu/strings.xml11
-rw-r--r--core/res/res/values-fa/strings.xml9
-rw-r--r--core/res/res/values-fi/strings.xml9
-rw-r--r--core/res/res/values-fr-rCA/strings.xml9
-rw-r--r--core/res/res/values-fr/strings.xml9
-rw-r--r--core/res/res/values-gl/strings.xml9
-rw-r--r--core/res/res/values-gu/strings.xml9
-rw-r--r--core/res/res/values-hi/strings.xml9
-rw-r--r--core/res/res/values-hr/strings.xml9
-rw-r--r--core/res/res/values-hu/strings.xml15
-rw-r--r--core/res/res/values-hy/strings.xml13
-rw-r--r--core/res/res/values-in/strings.xml9
-rw-r--r--core/res/res/values-is/strings.xml9
-rw-r--r--core/res/res/values-it/strings.xml11
-rw-r--r--core/res/res/values-iw/strings.xml9
-rw-r--r--core/res/res/values-ja/strings.xml9
-rw-r--r--core/res/res/values-ka/strings.xml9
-rw-r--r--core/res/res/values-kk/strings.xml9
-rw-r--r--core/res/res/values-km/strings.xml9
-rw-r--r--core/res/res/values-kn/strings.xml9
-rw-r--r--core/res/res/values-ko/strings.xml9
-rw-r--r--core/res/res/values-ky/strings.xml9
-rw-r--r--core/res/res/values-lo/strings.xml9
-rw-r--r--core/res/res/values-lt/strings.xml9
-rw-r--r--core/res/res/values-lv/strings.xml9
-rw-r--r--core/res/res/values-mcc302-mnc370-af/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-am/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ar/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-az/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-b+sr+Latn/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-be/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-bg/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-bn/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-bs/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ca/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-cs/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-da/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-de/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-el/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-en-rAU/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-en-rGB/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-en-rIN/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-es-rUS/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-es/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-et/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-eu/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-fa/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-fi/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-fr-rCA/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-fr/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-gl/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-gu/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-hi/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-hr/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-hu/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-hy/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-in/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-is/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-it/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-iw/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ja/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ka/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-kk/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-km/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-kn/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ko/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ky/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-lo/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-lt/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-lv/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-mk/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ml/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-mn/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-mr/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ms/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-my/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-nb/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ne/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-nl/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-pa/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-pl/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-pt-rBR/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-pt-rPT/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-pt/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ro/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ru/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-si/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-sk/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-sl/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-sq/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-sr/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-sv/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-sw/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ta/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-te/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-th/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-tl/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-tr/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-uk/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-ur/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-uz/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-vi/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-zh-rCN/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-zh-rHK/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-zh-rTW/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370-zu/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc370/strings.xml25
-rw-r--r--core/res/res/values-mcc302-mnc720-af/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-am/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ar/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-az/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-b+sr+Latn/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-be/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-bg/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-bn/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-bs/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ca/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-cs/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-da/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-de/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-el/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-en-rAU/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-en-rGB/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-en-rIN/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-es-rUS/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-es/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-et/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-eu/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-fa/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-fi/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-fr-rCA/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-fr/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-gl/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-gu/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-hi/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-hr/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-hu/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-hy/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-in/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-is/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-it/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-iw/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ja/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ka/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-kk/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-km/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-kn/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ko/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ky/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-lo/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-lt/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-lv/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-mk/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ml/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-mn/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-mr/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ms/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-my/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-nb/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ne/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-nl/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-pa/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-pl/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-pt-rBR/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-pt-rPT/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-pt/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ro/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ru/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-si/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-sk/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-sl/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-sq/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-sr/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-sv/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-sw/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ta/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-te/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-th/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-tl/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-tr/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-uk/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-ur/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-uz/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-vi/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-zh-rCN/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-zh-rHK/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-zh-rTW/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720-zu/strings.xml26
-rw-r--r--core/res/res/values-mcc302-mnc720/strings.xml25
-rw-r--r--core/res/res/values-mcc404/config.xml2
-rw-r--r--core/res/res/values-mcc724/config.xml23
-rw-r--r--core/res/res/values-mk/strings.xml11
-rw-r--r--core/res/res/values-ml/strings.xml9
-rw-r--r--core/res/res/values-mn/strings.xml9
-rw-r--r--core/res/res/values-mr/strings.xml9
-rw-r--r--core/res/res/values-ms/strings.xml9
-rw-r--r--core/res/res/values-my/strings.xml9
-rw-r--r--core/res/res/values-nb/strings.xml9
-rw-r--r--core/res/res/values-ne/strings.xml9
-rw-r--r--core/res/res/values-nl/strings.xml9
-rw-r--r--core/res/res/values-pa/strings.xml11
-rw-r--r--core/res/res/values-pl/strings.xml9
-rw-r--r--core/res/res/values-pt-rBR/strings.xml11
-rw-r--r--core/res/res/values-pt-rPT/strings.xml9
-rw-r--r--core/res/res/values-pt/strings.xml11
-rw-r--r--core/res/res/values-ro/strings.xml9
-rw-r--r--core/res/res/values-ru/strings.xml11
-rw-r--r--core/res/res/values-si/strings.xml9
-rw-r--r--core/res/res/values-sk/strings.xml9
-rw-r--r--core/res/res/values-sl/strings.xml11
-rw-r--r--core/res/res/values-sq/strings.xml9
-rw-r--r--core/res/res/values-sr/strings.xml9
-rw-r--r--core/res/res/values-sv/strings.xml9
-rw-r--r--core/res/res/values-sw/strings.xml9
-rw-r--r--core/res/res/values-ta/strings.xml9
-rw-r--r--core/res/res/values-te/strings.xml9
-rw-r--r--core/res/res/values-th/strings.xml9
-rw-r--r--core/res/res/values-tl/strings.xml9
-rw-r--r--core/res/res/values-tr/strings.xml9
-rw-r--r--core/res/res/values-uk/strings.xml9
-rw-r--r--core/res/res/values-ur/strings.xml11
-rw-r--r--core/res/res/values-uz/strings.xml11
-rw-r--r--core/res/res/values-vi/strings.xml9
-rw-r--r--core/res/res/values-zh-rCN/strings.xml9
-rw-r--r--core/res/res/values-zh-rHK/strings.xml9
-rw-r--r--core/res/res/values-zh-rTW/strings.xml11
-rw-r--r--core/res/res/values-zu/strings.xml9
-rw-r--r--core/res/res/values/config.xml5
-rw-r--r--core/res/res/values/strings.xml17
-rw-r--r--core/res/res/values/symbols.xml12
-rw-r--r--graphics/java/android/graphics/ColorFilter.java46
-rw-r--r--libs/hwui/OpenGLReadback.cpp16
-rw-r--r--media/java/android/media/AudioAttributes.java8
-rw-r--r--media/java/android/media/AudioSystem.java6
-rw-r--r--media/java/android/media/session/MediaSession.java78
-rw-r--r--media/jni/soundpool/SoundPoolThread.cpp29
-rw-r--r--media/jni/soundpool/SoundPoolThread.h1
-rw-r--r--packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java16
-rw-r--r--packages/SettingsLib/res/drawable/ic_mode_edit.xml (renamed from packages/SystemUI/res/drawable/ic_mode_edit.xml)0
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ko/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml10
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml12
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java112
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java119
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java16
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java8
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java49
-rwxr-xr-xpackages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java45
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java3
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java33
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java13
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java113
-rw-r--r--packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java300
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationSwipeActionHelper.java27
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values/attrs.xml3
-rw-r--r--packages/SystemUI/res-keyguard/values/dimens.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values/styles.xml6
-rw-r--r--packages/SystemUI/res/color/qs_background_dark.xml2
-rw-r--r--packages/SystemUI/res/drawable/pip_icon.xml25
-rw-r--r--packages/SystemUI/res/drawable/qs_background_primary.xml2
-rw-r--r--packages/SystemUI/res/layout/navigation_bar_window.xml4
-rw-r--r--packages/SystemUI/res/layout/notification_snooze.xml3
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml6
-rw-r--r--packages/SystemUI/res/values-el/strings.xml6
-rw-r--r--packages/SystemUI/res/values-mcc311-mnc480/config.xml26
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml2
-rw-r--r--packages/SystemUI/res/values/config.xml4
-rw-r--r--packages/SystemUI/res/values/dimens.xml5
-rw-r--r--packages/SystemUI/res/values/ids.xml8
-rw-r--r--packages/SystemUI/res/values/styles.xml2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java49
-rw-r--r--packages/SystemUI/src/com/android/keyguard/PasswordTextView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/BatteryMeterView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/RoundedCorners.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java74
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java168
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFrame.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java125
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java85
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java2
-rw-r--r--packages/SystemUI/tests/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java68
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java82
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java73
-rw-r--r--packages/overlays/SysuiDarkThemeOverlay/Android.mk (renamed from packages/SysuiDarkThemeOverlay/Android.mk)0
-rw-r--r--packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml (renamed from packages/SysuiDarkThemeOverlay/AndroidManifest.xml)0
-rw-r--r--packages/overlays/SysuiDarkThemeOverlay/res/values/strings.xml (renamed from packages/SysuiDarkThemeOverlay/res/values/strings.xml)0
-rw-r--r--packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml (renamed from packages/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml)9
-rw-r--r--packages/overlays/SysuiLightWallpaperThemeOverlay/Android.mk13
-rw-r--r--packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml8
-rw-r--r--packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/strings.xml24
-rw-r--r--packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml7
-rw-r--r--proto/src/metrics_constants.proto64
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java6
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java57
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteFillService.java1
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java12
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java1
-rw-r--r--services/core/Android.mk1
-rw-r--r--services/core/java/com/android/server/ContextHubSystemService.java15
-rw-r--r--services/core/java/com/android/server/GestureLauncherService.java38
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java82
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java27
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java115
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java2
-rw-r--r--services/core/java/com/android/server/am/KeyguardController.java40
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java2
-rw-r--r--services/core/java/com/android/server/audio/PlaybackActivityMonitor.java16
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java47
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java10
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/OffloadController.java3
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java113
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java39
-rw-r--r--services/core/java/com/android/server/content/ContentService.java9
-rw-r--r--services/core/java/com/android/server/content/SyncJobService.java16
-rw-r--r--services/core/java/com/android/server/content/SyncLogger.java252
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java303
-rw-r--r--services/core/java/com/android/server/content/SyncOperation.java65
-rw-r--r--services/core/java/com/android/server/content/SyncStorageEngine.java10
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java12
-rw-r--r--services/core/java/com/android/server/display/VirtualDisplayAdapter.java5
-rw-r--r--services/core/java/com/android/server/job/JobPackageTracker.java24
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java7
-rw-r--r--services/core/java/com/android/server/job/JobServiceContext.java36
-rw-r--r--services/core/java/com/android/server/job/JobStore.java16
-rw-r--r--services/core/java/com/android/server/job/controllers/JobStatus.java55
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java42
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java74
-rw-r--r--services/core/java/com/android/server/notification/RankingHelper.java29
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java47
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java5
-rw-r--r--services/core/java/com/android/server/vr/Vr2dDisplay.java1
-rw-r--r--services/core/java/com/android/server/wm/AppWindowContainerController.java10
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java2
-rw-r--r--services/core/java/com/android/server/wm/Session.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java130
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java4
-rw-r--r--services/core/jni/com_android_server_power_PowerManagerService.cpp6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java13
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java83
-rw-r--r--services/print/java/com/android/server/print/UserState.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java61
-rw-r--r--services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java11
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java27
-rw-r--r--services/tests/servicestests/src/com/android/server/job/JobStoreTest.java3
-rw-r--r--telecomm/java/android/telecom/Call.java13
-rw-r--r--telephony/java/android/telephony/euicc/EuiccManager.java6
-rw-r--r--telephony/java/com/android/ims/ImsConfig.java7
-rw-r--r--telephony/java/com/android/internal/telephony/NetworkScanResult.java7
-rw-r--r--telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl5
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java4
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SmsMessage.java12
-rw-r--r--test-runner/src/android/test/mock/MockContext.java6
-rw-r--r--tests/net/java/com/android/server/connectivity/TetheringTest.java46
-rw-r--r--tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java3
-rw-r--r--tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java48
-rw-r--r--tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java60
-rw-r--r--tests/testables/src/android/testing/BaseFragmentTest.java8
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java9
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java38
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java22
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pManager.java22
-rw-r--r--wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java25
493 files changed, 10081 insertions, 1562 deletions
diff --git a/cmds/am/src/com/android/commands/am/Instrument.java b/cmds/am/src/com/android/commands/am/Instrument.java
index 8eefd256a69d..4966b4380d9b 100644
--- a/cmds/am/src/com/android/commands/am/Instrument.java
+++ b/cmds/am/src/com/android/commands/am/Instrument.java
@@ -382,6 +382,7 @@ public class Instrument {
oldAnims = mWm.getAnimationScales();
mWm.setAnimationScale(0, 0.0f);
mWm.setAnimationScale(1, 0.0f);
+ mWm.setAnimationScale(2, 0.0f);
}
// Figure out which component we are tring to do.
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 607e6e0186e7..23668786abee 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -251,5 +251,7 @@ int main(int argc, char** argv)
if (mapbase != MAP_FAILED) {
munmap((void *)mapbase, mapsize);
}
- return 0;
+
+ // b/36066697: Avoid running static destructors.
+ _exit(0);
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 24c144c89ad2..bc6e9cd0ab7e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -16,17 +16,9 @@
package android.app;
-import android.graphics.Rect;
-import android.view.ViewRootImpl.ActivityConfigCallback;
-import android.view.autofill.AutofillManager;
-import android.view.autofill.AutofillPopupWindow;
-import android.view.autofill.IAutofillWindowPresenter;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.IVoiceInteractor;
-import com.android.internal.app.ToolbarActionBar;
-import com.android.internal.app.WindowDecorActionBar;
-import com.android.internal.policy.DecorView;
-import com.android.internal.policy.PhoneWindow;
+import static android.os.Build.VERSION_CODES.O;
+
+import static java.lang.Character.MIN_VALUE;
import android.annotation.CallSuper;
import android.annotation.DrawableRes;
@@ -62,6 +54,7 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.session.MediaController;
@@ -114,15 +107,26 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewManager;
import android.view.ViewRootImpl;
+import android.view.ViewRootImpl.ActivityConfigCallback;
import android.view.Window;
import android.view.Window.WindowControllerCallback;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
+import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillPopupWindow;
+import android.view.autofill.IAutofillWindowPresenter;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.app.ToolbarActionBar;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.policy.DecorView;
+import com.android.internal.policy.PhoneWindow;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -131,9 +135,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-import static android.os.Build.VERSION_CODES.O;
-import static java.lang.Character.MIN_VALUE;
-
/**
* An activity is a single, focused thing that the user can do. Almost all
* activities interact with the user, so the Activity class takes care of
@@ -999,7 +1000,8 @@ public class Activity extends ContextThemeWrapper
}
if (savedInstanceState != null) {
mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
- mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID, View.NO_ID);
+ mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
+ View.LAST_APP_AUTOFILL_ID);
if (mAutoFillResetNeeded) {
getAutofillManager().onCreate(savedInstanceState);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 199e856e7a22..06dbe8218450 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -360,6 +360,13 @@ public class ActivityManager {
FIRST_START_NON_FATAL_ERROR_CODE + 1;
/**
+ * Result for IActivityManaqer.startActivity: a new activity start was aborted. Never returned
+ * externally.
+ * @hide
+ */
+ public static final int START_ABORTED = FIRST_START_NON_FATAL_ERROR_CODE + 2;
+
+ /**
* Flag for IActivityManaqer.startActivity: do special start mode where
* a new activity is launched only if it is needed.
* @hide
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index df550807dd30..204df63f600d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2391,13 +2391,13 @@ public final class ActivityThread {
memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
memInfo.nativePrivateClean, memInfo.hasSwappedOutPss ?
- memInfo.nativeSwappedOut : memInfo.nativeSwappedOutPss,
+ memInfo.nativeSwappedOutPss : memInfo.nativeSwappedOut,
nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss ?
- memInfo.dalvikSwappedOut : memInfo.dalvikSwappedOutPss,
+ memInfo.dalvikSwappedOutPss : memInfo.dalvikSwappedOut,
dalvikMax, dalvikAllocated, dalvikFree);
} else {
printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
@@ -2708,8 +2708,14 @@ public final class ActivityThread {
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
- activity = mInstrumentation.newActivity(
- cl, component.getClassName(), r.intent);
+ if (appContext.getApplicationContext() instanceof Application) {
+ activity = ((Application) appContext.getApplicationContext())
+ .instantiateActivity(cl, component.getClassName(), r.intent);
+ }
+ if (activity == null) {
+ activity = mInstrumentation.newActivity(
+ cl, component.getClassName(), r.intent);
+ }
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
@@ -3234,7 +3240,8 @@ public final class ActivityThread {
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
- receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
+ receiver = instantiate(cl, component, data.intent, app,
+ Application::instantiateReceiver);
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
"Finishing failed broadcast to " + data.intent.getComponent());
@@ -3322,12 +3329,13 @@ public final class ActivityThread {
} else {
try {
if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
+ ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
- agent = (BackupAgent) cl.loadClass(classname).newInstance();
+ agent = instantiate(cl, classname, context,
+ Application::instantiateBackupAgent);
// set up the agent's context
- ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(agent);
agent.attach(context);
@@ -3387,9 +3395,12 @@ public final class ActivityThread {
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
+ Application app = null;
try {
+ app = packageInfo.makeApplication(false, mInstrumentation);
java.lang.ClassLoader cl = packageInfo.getClassLoader();
- service = (Service) cl.loadClass(data.info.name).newInstance();
+ service = instantiate(cl, data.info.name, data.intent, app,
+ Application::instantiateService);
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
@@ -3404,7 +3415,6 @@ public final class ActivityThread {
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
- Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
@@ -5721,8 +5731,8 @@ public final class ActivityThread {
try {
final ClassLoader cl = instrContext.getClassLoader();
- mInstrumentation = (Instrumentation)
- cl.loadClass(data.instrumentationName.getClassName()).newInstance();
+ mInstrumentation = instantiate(cl, data.instrumentationName.getClassName(),
+ instrContext, Application::instantiateInstrumentation);
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
@@ -6267,8 +6277,8 @@ public final class ActivityThread {
try {
final java.lang.ClassLoader cl = c.getClassLoader();
- localProvider = (ContentProvider)cl.
- loadClass(info.name).newInstance();
+ localProvider = instantiate(cl, info.name, context,
+ Application::instantiateProvider);
provider = localProvider.getIContentProvider();
if (provider == null) {
Slog.e(TAG, "Failed to instantiate class " +
@@ -6467,6 +6477,38 @@ public final class ActivityThread {
}
}
+ private <T> T instantiate(ClassLoader cl, String className, Context c,
+ Instantiator<T> instantiator)
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ if (c.getApplicationContext() instanceof Application) {
+ T a = instantiator.instantiate((Application) c.getApplicationContext(),
+ cl, className);
+ if (a != null) return a;
+ }
+ return (T) cl.loadClass(className).newInstance();
+ }
+
+ private <T> T instantiate(ClassLoader cl, String className, Intent intent, Context c,
+ IntentInstantiator<T> instantiator)
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException {
+ if (c.getApplicationContext() instanceof Application) {
+ T a = instantiator.instantiate((Application) c.getApplicationContext(),
+ cl, className, intent);
+ if (a != null) return a;
+ }
+ return (T) cl.loadClass(className).newInstance();
+ }
+
+ private interface Instantiator<T> {
+ T instantiate(Application app, ClassLoader cl, String className)
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException;
+ }
+
+ private interface IntentInstantiator<T> {
+ T instantiate(Application app, ClassLoader cl, String className, Intent intent)
+ throws ClassNotFoundException, IllegalAccessException, InstantiationException;
+ }
+
private static class EventLoggingReporter implements EventLogger.Reporter {
@Override
public void report (int code, Object... list) {
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 156df36a600c..7fb5e2e7e442 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -16,17 +16,20 @@
package android.app;
-import java.util.ArrayList;
-
import android.annotation.CallSuper;
+import android.app.backup.BackupAgent;
+import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
+import android.content.ContentProvider;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
+import java.util.ArrayList;
+
/**
* Base class for maintaining global application state. You can provide your own
* implementation by creating a subclass and specifying the fully-qualified name
@@ -289,4 +292,79 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {
}
}
}
+
+ /**
+ * Allows application to override the creation of activities. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @param intent Intent creating the class.
+ * @hide
+ */
+ public Activity instantiateActivity(ClassLoader cl, String className, Intent intent) {
+ return null;
+ }
+
+ /**
+ * Allows application to override the creation of receivers. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @param intent Intent creating the class.
+ * @hide
+ */
+ public BroadcastReceiver instantiateReceiver(ClassLoader cl, String className, Intent intent) {
+ return null;
+ }
+
+ /**
+ * Allows application to override the creation of services. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @param intent Intent creating the class.
+ * @hide
+ */
+ public Service instantiateService(ClassLoader cl, String className, Intent intent) {
+ return null;
+ }
+
+ /**
+ * Allows application to override the creation of providers. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @hide
+ */
+ public ContentProvider instantiateProvider(ClassLoader cl, String className) {
+ return null;
+ }
+
+ /**
+ * Allows application to override the creation of backup agents. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @hide
+ */
+ public BackupAgent instantiateBackupAgent(ClassLoader cl, String className) {
+ return null;
+ }
+
+ /**
+ * Allows application to override the creation of instrumentation. This can be used to
+ * perform things such as dependency injection or class loader changes to these
+ * classes. Return null to use the default creation flow.
+ * @param cl The default classloader to use for instantiation.
+ * @param className The class to be instantiated.
+ * @hide
+ */
+ public Instrumentation instantiateInstrumentation(ClassLoader cl, String className) {
+ return null;
+ }
} \ No newline at end of file
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 8c6412998572..318c7ac31522 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -256,28 +256,34 @@ class ContextImpl extends Context {
@Override
public void setTheme(int resId) {
- if (mThemeResource != resId) {
- mThemeResource = resId;
- initializeTheme();
+ synchronized (mSync) {
+ if (mThemeResource != resId) {
+ mThemeResource = resId;
+ initializeTheme();
+ }
}
}
@Override
public int getThemeResId() {
- return mThemeResource;
+ synchronized (mSync) {
+ return mThemeResource;
+ }
}
@Override
public Resources.Theme getTheme() {
- if (mTheme != null) {
- return mTheme;
- }
+ synchronized (mSync) {
+ if (mTheme != null) {
+ return mTheme;
+ }
- mThemeResource = Resources.selectDefaultTheme(mThemeResource,
- getOuterContext().getApplicationInfo().targetSdkVersion);
- initializeTheme();
+ mThemeResource = Resources.selectDefaultTheme(mThemeResource,
+ getOuterContext().getApplicationInfo().targetSdkVersion);
+ initializeTheme();
- return mTheme;
+ return mTheme;
+ }
}
private void initializeTheme() {
@@ -2151,6 +2157,14 @@ class ContextImpl extends Context {
}
@Override
+ public boolean canLoadUnsafeResources() {
+ if (getPackageName().equals(getOpPackageName())) {
+ return true;
+ }
+ return (mFlags & Context.CONTEXT_IGNORE_SECURITY) != 0;
+ }
+
+ @Override
public Display getDisplay() {
if (mDisplay == null) {
return mResourcesManager.getAdjustedDisplay(Display.DEFAULT_DISPLAY,
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 46f115f9491b..79e5407a17d3 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -455,6 +455,7 @@ public final class LoadedApk {
if (!outZipPaths.contains(lib)) {
outZipPaths.add(index, lib);
index++;
+ appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
}
}
}
@@ -463,11 +464,33 @@ public final class LoadedApk {
for (String lib : instrumentationLibs) {
if (!outZipPaths.contains(lib)) {
outZipPaths.add(0, lib);
+ appendApkLibPathIfNeeded(lib, aInfo, outLibPaths);
}
}
}
}
+ /**
+ * This method appends a path to the appropriate native library folder of a
+ * library if this library is hosted in an APK. This allows support for native
+ * shared libraries. The library API is determined based on the application
+ * ABI.
+ *
+ * @param path Path to the library.
+ * @param applicationInfo The application depending on the library.
+ * @param outLibPaths List to which to add the native lib path if needed.
+ */
+ private static void appendApkLibPathIfNeeded(@NonNull String path,
+ @NonNull ApplicationInfo applicationInfo, @Nullable List<String> outLibPaths) {
+ // Looking at the suffix is a little hacky but a safe and simple solution.
+ // We will be revisiting code in the next release and clean this up.
+ if (outLibPaths != null && applicationInfo.primaryCpuAbi != null && path.endsWith(".apk")) {
+ if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
+ outLibPaths.add(path + "!/lib/" + applicationInfo.primaryCpuAbi);
+ }
+ }
+ }
+
/*
* All indices received by the super class should be shifted by 1 when accessing mSplitNames,
* etc. The super class assumes the base APK is index 0, while the PackageManager APIs don't
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 042eece68b53..b7d3f578df27 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -604,7 +604,7 @@ public final class PendingIntent implements Parcelable {
/**
* Retrieve a PendingIntent that will start a foreground service, like calling
- * {@link Context#startService Context.startForegroundService()}. The start
+ * {@link Context#startForegroundService Context.startForegroundService()}. The start
* arguments given to the service will come from the extras of the Intent.
*
* <p class="note">For security reasons, the {@link android.content.Intent}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9eacd2166bfd..ea0829f2ef2d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -55,7 +55,6 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.ContactsContract.Directory;
-import android.provider.Settings;
import android.security.Credentials;
import android.service.restrictions.RestrictionsReceiver;
import android.telephony.TelephonyManager;
@@ -3134,6 +3133,14 @@ public class DevicePolicyManager {
public static final int WIPE_RESET_PROTECTION_DATA = 0x0002;
/**
+ * Flag for {@link #wipeData(int)}: also erase the device's eUICC data.
+ *
+ * TODO(b/35851809): make this public.
+ * @hide
+ */
+ public static final int WIPE_EUICC = 0x0004;
+
+ /**
* Ask that all user data be wiped. If called as a secondary user, the user will be removed and
* other users will remain unaffected. Calling from the primary user will cause the device to
* reboot, erasing all device data - including all the secondary users and their data - while
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 266fa7e24b2c..4e8277c388de 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -1051,6 +1051,9 @@ public class AssistStructure implements Parcelable {
public void updateAutofillValue(AutofillValue value) {
mAutofillValue = value;
if (value.isText()) {
+ if (mText == null) {
+ mText = new ViewNodeText();
+ }
mText.mText = value.getTextValue();
}
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 67d56d5060e9..dfd5996c6a00 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -208,6 +208,8 @@ public final class BluetoothLeAdvertiser {
if (wrapper == null) return;
stopAdvertisingSet(wrapper);
+
+ mLegacyAdvertisers.remove(callback);
}
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index f3f0ae5cd959..1eac395bd06c 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -136,6 +136,11 @@ public final class BluetoothLeScanner {
* Start Bluetooth LE scan using a {@link PendingIntent}. The scan results will be delivered via
* the PendingIntent. Use this method of scanning if your process is not always running and it
* should be started when scan results are available.
+ * <p>
+ * When the PendingIntent is delivered, the Intent passed to the receiver or activity
+ * will contain one or more of the extras {@link #EXTRA_CALLBACK_TYPE},
+ * {@link #EXTRA_ERROR_CODE} and {@link #EXTRA_LIST_SCAN_RESULT} to indicate the result of
+ * the scan.
*
* @param filters Optional list of ScanFilters for finding exact BLE devices.
* @param settings Optional settings for the scan.
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index dabe608c038f..86a30cf0c846 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -214,10 +214,12 @@ public final class CompanionDeviceManager {
return;
}
try {
- mService.requestNotificationAccess(component).send();
+ IntentSender intentSender = mService.requestNotificationAccess(component)
+ .getIntentSender();
+ mContext.startIntentSender(intentSender, null, 0, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
- } catch (PendingIntent.CanceledException e) {
+ } catch (IntentSender.SendIntentException e) {
throw new RuntimeException(e);
}
}
@@ -288,6 +290,7 @@ public final class CompanionDeviceManager {
@Override
public void onActivityDestroyed(Activity activity) {
+ if (activity != getActivity()) return;
try {
mService.stopScan(mRequest, this, getCallingPackage());
} catch (RemoteException e) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5929aca0a38f..ef6170359dda 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4681,6 +4681,12 @@ public abstract class Context {
public abstract boolean isCredentialProtectedStorage();
/**
+ * Returns true if the context can load unsafe resources, e.g. fonts.
+ * @hide
+ */
+ public abstract boolean canLoadUnsafeResources();
+
+ /**
* @hide
*/
public IBinder getActivityToken() {
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index c719c6474cf1..a9fd58bc950c 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -925,6 +925,12 @@ public class ContextWrapper extends Context {
return mBase.isCredentialProtectedStorage();
}
+ /** {@hide} */
+ @Override
+ public boolean canLoadUnsafeResources() {
+ return mBase.canLoadUnsafeResources();
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 852e5f708ec3..f70215b46a5e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -16,6 +16,8 @@
package android.content;
+import static android.content.ContentProvider.maybeAddUserId;
+
import android.annotation.AnyRes;
import android.annotation.BroadcastBehavior;
import android.annotation.IntDef;
@@ -43,7 +45,7 @@ import android.os.ResultReceiver;
import android.os.ShellCommand;
import android.os.StrictMode;
import android.os.UserHandle;
-import android.os.storage.StorageManager;
+import android.provider.ContactsContract.QuickContact;
import android.provider.DocumentsContract;
import android.provider.DocumentsProvider;
import android.provider.MediaStore;
@@ -51,7 +53,9 @@ import android.provider.OpenableColumns;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
+
import com.android.internal.util.XmlUtils;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -69,8 +73,6 @@ import java.util.Locale;
import java.util.Objects;
import java.util.Set;
-import static android.content.ContentProvider.maybeAddUserId;
-
/**
* An intent is an abstract description of an operation to be performed. It
* can be used with {@link Context#startActivity(Intent) startActivity} to
@@ -9782,6 +9784,7 @@ public class Intent implements Parcelable, Cloneable {
&& leavingPackage) {
switch (mAction) {
case ACTION_PROVIDER_CHANGED:
+ case QuickContact.ACTION_QUICK_CONTACT:
// Ignore actions that don't need to grant
break;
default:
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index bb24ccd5a5ed..663e6e476c5a 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -24,7 +24,11 @@ import java.util.ArrayList;
/** @hide */
public class SyncStatusInfo implements Parcelable {
- static final int VERSION = 2;
+ private static final String TAG = "Sync";
+
+ static final int VERSION = 3;
+
+ private static final int MAX_EVENT_COUNT = 10;
public final int authorityId;
public long totalElapsedTime;
@@ -47,7 +51,8 @@ public class SyncStatusInfo implements Parcelable {
// no race conditions when accessing this list
private ArrayList<Long> periodicSyncTimes;
- private static final String TAG = "Sync";
+ private final ArrayList<Long> mLastEventTimes = new ArrayList<>();
+ private final ArrayList<String> mLastEvents = new ArrayList<>();
public SyncStatusInfo(int authorityId) {
this.authorityId = authorityId;
@@ -92,6 +97,11 @@ public class SyncStatusInfo implements Parcelable {
} else {
parcel.writeInt(-1);
}
+ parcel.writeInt(mLastEventTimes.size());
+ for (int i = 0; i < mLastEventTimes.size(); i++) {
+ parcel.writeLong(mLastEventTimes.get(i));
+ parcel.writeString(mLastEvents.get(i));
+ }
}
public SyncStatusInfo(Parcel parcel) {
@@ -117,15 +127,24 @@ public class SyncStatusInfo implements Parcelable {
if (version == 1) {
periodicSyncTimes = null;
} else {
- int N = parcel.readInt();
- if (N < 0) {
+ final int count = parcel.readInt();
+ if (count < 0) {
periodicSyncTimes = null;
} else {
periodicSyncTimes = new ArrayList<Long>();
- for (int i=0; i<N; i++) {
+ for (int i = 0; i < count; i++) {
periodicSyncTimes.add(parcel.readLong());
}
}
+ if (version >= 3) {
+ mLastEventTimes.clear();
+ mLastEvents.clear();
+ final int nEvents = parcel.readInt();
+ for (int i = 0; i < nEvents; i++) {
+ mLastEventTimes.add(parcel.readLong());
+ mLastEvents.add(parcel.readString());
+ }
+ }
}
}
@@ -149,6 +168,8 @@ public class SyncStatusInfo implements Parcelable {
if (other.periodicSyncTimes != null) {
periodicSyncTimes = new ArrayList<Long>(other.periodicSyncTimes);
}
+ mLastEventTimes.addAll(other.mLastEventTimes);
+ mLastEvents.addAll(other.mLastEvents);
}
public void setPeriodicSyncTime(int index, long when) {
@@ -172,6 +193,31 @@ public class SyncStatusInfo implements Parcelable {
}
}
+ /** */
+ public void addEvent(String message) {
+ if (mLastEventTimes.size() >= MAX_EVENT_COUNT) {
+ mLastEventTimes.remove(MAX_EVENT_COUNT - 1);
+ mLastEvents.remove(MAX_EVENT_COUNT - 1);
+ }
+ mLastEventTimes.add(0, System.currentTimeMillis());
+ mLastEvents.add(0, message);
+ }
+
+ /** */
+ public int getEventCount() {
+ return mLastEventTimes.size();
+ }
+
+ /** */
+ public long getEventTime(int i) {
+ return mLastEventTimes.get(i);
+ }
+
+ /** */
+ public String getEvent(int i) {
+ return mLastEvents.get(i);
+ }
+
public static final Creator<SyncStatusInfo> CREATOR = new Creator<SyncStatusInfo>() {
public SyncStatusInfo createFromParcel(Parcel in) {
return new SyncStatusInfo(in);
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 358787e66428..e9c958857d5c 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -20,12 +20,10 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.DisplayMetrics;
-import android.util.Log;
/**
* A representation of an activity that can belong to this user or a managed
@@ -173,12 +171,6 @@ public class LauncherActivityInfo {
public Drawable getBadgedIcon(int density) {
Drawable originalIcon = getIcon(density);
- if (originalIcon instanceof BitmapDrawable) {
- // TODO: Go through LauncherAppsService
- return mPm.getUserBadgedIcon(originalIcon, mUser);
- } else {
- Log.e(TAG, "Unable to create badged icon for " + mActivityInfo);
- }
- return originalIcon;
+ return mPm.getUserBadgedIcon(originalIcon, mUser);
}
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index fdb0f2bae64b..c67376c25885 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -5989,6 +5989,10 @@ public class PackageParser {
}
}
+ public boolean isLibrary() {
+ return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
+ }
+
public List<String> getAllCodePaths() {
ArrayList<String> paths = new ArrayList<>();
paths.add(baseCodePath);
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 88c1627f955b..6834ba816910 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -16,29 +16,26 @@
package android.content.res;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.DisplayInfo;
-import com.android.internal.util.XmlUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.Config;
+import android.graphics.Rect;
import android.os.Build;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import android.view.DisplayInfo;
import android.view.View;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1818,9 +1815,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
}
/**
- * Return whether the screen has a wide color gamut.
+ * Return whether the screen has a wide color gamut and wide color gamut rendering
+ * is supported by this device.
*
- * @return true if the screen has a wide color gamut, false otherwise
+ * @return true if the screen has a wide color gamut and wide color gamut rendering
+ * is supported, false otherwise
*/
public boolean isScreenWideColorGamut() {
return (colorMode & COLOR_MODE_WIDE_COLOR_GAMUT_MASK) == COLOR_MODE_WIDE_COLOR_GAMUT_YES;
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index b3938cbc3bc9..6825d363b918 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -158,7 +158,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
}
@Override
- public synchronized int capture(CaptureRequest request, CaptureCallback callback,
+ public int capture(CaptureRequest request, CaptureCallback callback,
Handler handler) throws CameraAccessException {
if (request == null) {
throw new IllegalArgumentException("request must not be null");
@@ -169,21 +169,23 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
throw new IllegalArgumentException("capture request was created for another session");
}
- checkNotClosed();
+ synchronized (mDeviceImpl.mInterfaceLock) {
+ checkNotClosed();
- handler = checkHandler(handler, callback);
+ handler = checkHandler(handler, callback);
- if (DEBUG) {
- Log.v(TAG, mIdString + "capture - request " + request + ", callback " + callback +
- " handler " + handler);
- }
+ if (DEBUG) {
+ Log.v(TAG, mIdString + "capture - request " + request + ", callback " + callback +
+ " handler " + handler);
+ }
- return addPendingSequence(mDeviceImpl.capture(request,
- createCaptureCallbackProxy(handler, callback), mDeviceHandler));
+ return addPendingSequence(mDeviceImpl.capture(request,
+ createCaptureCallbackProxy(handler, callback), mDeviceHandler));
+ }
}
@Override
- public synchronized int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
+ public int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
Handler handler) throws CameraAccessException {
if (requests == null) {
throw new IllegalArgumentException("Requests must not be null");
@@ -203,22 +205,24 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
}
}
- checkNotClosed();
+ synchronized (mDeviceImpl.mInterfaceLock) {
+ checkNotClosed();
- handler = checkHandler(handler, callback);
+ handler = checkHandler(handler, callback);
- if (DEBUG) {
- CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
- Log.v(TAG, mIdString + "captureBurst - requests " + Arrays.toString(requestArray) +
- ", callback " + callback + " handler " + handler);
- }
+ if (DEBUG) {
+ CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
+ Log.v(TAG, mIdString + "captureBurst - requests " + Arrays.toString(requestArray) +
+ ", callback " + callback + " handler " + handler);
+ }
- return addPendingSequence(mDeviceImpl.captureBurst(requests,
- createCaptureCallbackProxy(handler, callback), mDeviceHandler));
+ return addPendingSequence(mDeviceImpl.captureBurst(requests,
+ createCaptureCallbackProxy(handler, callback), mDeviceHandler));
+ }
}
@Override
- public synchronized int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
+ public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
Handler handler) throws CameraAccessException {
if (request == null) {
throw new IllegalArgumentException("request must not be null");
@@ -226,21 +230,23 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
throw new IllegalArgumentException("repeating reprocess requests are not supported");
}
- checkNotClosed();
+ synchronized (mDeviceImpl.mInterfaceLock) {
+ checkNotClosed();
- handler = checkHandler(handler, callback);
+ handler = checkHandler(handler, callback);
- if (DEBUG) {
- Log.v(TAG, mIdString + "setRepeatingRequest - request " + request + ", callback " +
- callback + " handler" + " " + handler);
- }
+ if (DEBUG) {
+ Log.v(TAG, mIdString + "setRepeatingRequest - request " + request + ", callback " +
+ callback + " handler" + " " + handler);
+ }
- return addPendingSequence(mDeviceImpl.setRepeatingRequest(request,
- createCaptureCallbackProxy(handler, callback), mDeviceHandler));
+ return addPendingSequence(mDeviceImpl.setRepeatingRequest(request,
+ createCaptureCallbackProxy(handler, callback), mDeviceHandler));
+ }
}
@Override
- public synchronized int setRepeatingBurst(List<CaptureRequest> requests,
+ public int setRepeatingBurst(List<CaptureRequest> requests,
CaptureCallback callback, Handler handler) throws CameraAccessException {
if (requests == null) {
throw new IllegalArgumentException("requests must not be null");
@@ -255,34 +261,39 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
}
}
- checkNotClosed();
+ synchronized (mDeviceImpl.mInterfaceLock) {
+ checkNotClosed();
- handler = checkHandler(handler, callback);
+ handler = checkHandler(handler, callback);
- if (DEBUG) {
- CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
- Log.v(TAG, mIdString + "setRepeatingBurst - requests " + Arrays.toString(requestArray) +
- ", callback " + callback + " handler" + "" + handler);
- }
+ if (DEBUG) {
+ CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
+ Log.v(TAG, mIdString + "setRepeatingBurst - requests " +
+ Arrays.toString(requestArray) + ", callback " + callback +
+ " handler" + "" + handler);
+ }
- return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests,
- createCaptureCallbackProxy(handler, callback), mDeviceHandler));
+ return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests,
+ createCaptureCallbackProxy(handler, callback), mDeviceHandler));
+ }
}
@Override
- public synchronized void stopRepeating() throws CameraAccessException {
- checkNotClosed();
+ public void stopRepeating() throws CameraAccessException {
+ synchronized (mDeviceImpl.mInterfaceLock) {
+ checkNotClosed();
- if (DEBUG) {
- Log.v(TAG, mIdString + "stopRepeating");
- }
+ if (DEBUG) {
+ Log.v(TAG, mIdString + "stopRepeating");
+ }
- mDeviceImpl.stopRepeating();
+ mDeviceImpl.stopRepeating();
+ }
}
@Override
public void abortCaptures() throws CameraAccessException {
- synchronized (this) {
+ synchronized (mDeviceImpl.mInterfaceLock) {
checkNotClosed();
if (DEBUG) {
@@ -296,13 +307,9 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
mAborting = true;
mAbortDrainer.taskStarted();
- }
- synchronized (mDeviceImpl.mInterfaceLock) {
- synchronized (this) {
- mDeviceImpl.flush();
- // The next BUSY -> IDLE set of transitions will mark the end of the abort.
- }
+ mDeviceImpl.flush();
+ // The next BUSY -> IDLE set of transitions will mark the end of the abort.
}
}
@@ -332,7 +339,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
*/
@Override
public void replaceSessionClose() {
- synchronized (this) {
+ synchronized (mDeviceImpl.mInterfaceLock) {
/*
* In order for creating new sessions to be fast, the new session should be created
* before the old session is closed.
@@ -357,13 +364,13 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
// configuration for the new session. If it was already called, then we don't care,
// since it won't get called again.
mSkipUnconfigure = true;
+ close();
}
- close();
}
@Override
public void close() {
- synchronized (this) {
+ synchronized (mDeviceImpl.mInterfaceLock) {
if (mClosed) {
if (DEBUG) Log.v(TAG, mIdString + "close - reentering");
return;
@@ -372,42 +379,36 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
if (DEBUG) Log.v(TAG, mIdString + "close - first time");
mClosed = true;
- }
- synchronized (mDeviceImpl.mInterfaceLock) {
- synchronized (this) {
- /*
- * Flush out any repeating request. Since camera is closed, no new requests
- * can be queued, and eventually the entire request queue will be drained.
- *
- * If the camera device was already closed, short circuit and do nothing; since
- * no more internal device callbacks will fire anyway.
- *
- * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure
- * the camera. Once that's done, fire #onClosed.
- */
- try {
- mDeviceImpl.stopRepeating();
- } catch (IllegalStateException e) {
- // OK: Camera device may already be closed, nothing else to do
+ /*
+ * Flush out any repeating request. Since camera is closed, no new requests
+ * can be queued, and eventually the entire request queue will be drained.
+ *
+ * If the camera device was already closed, short circuit and do nothing; since
+ * no more internal device callbacks will fire anyway.
+ *
+ * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure
+ * the camera. Once that's done, fire #onClosed.
+ */
+ try {
+ mDeviceImpl.stopRepeating();
+ } catch (IllegalStateException e) {
+ // OK: Camera device may already be closed, nothing else to do
- // TODO: Fire onClosed anytime we get the device onClosed or the ISE?
- // or just suppress the ISE only and rely onClosed.
- // Also skip any of the draining work if this is already closed.
+ // TODO: Fire onClosed anytime we get the device onClosed or the ISE?
+ // or just suppress the ISE only and rely onClosed.
+ // Also skip any of the draining work if this is already closed.
- // Short-circuit; queue callback immediately and return
- mStateCallback.onClosed(this);
- return;
- } catch (CameraAccessException e) {
- // OK: close does not throw checked exceptions.
- Log.e(TAG, mIdString + "Exception while stopping repeating: ", e);
+ // Short-circuit; queue callback immediately and return
+ mStateCallback.onClosed(this);
+ return;
+ } catch (CameraAccessException e) {
+ // OK: close does not throw checked exceptions.
+ Log.e(TAG, mIdString + "Exception while stopping repeating: ", e);
- // TODO: call onError instead of onClosed if this happens
- }
+ // TODO: call onError instead of onClosed if this happens
}
- }
- synchronized (this) {
// If no sequences are pending, fire #onClosed immediately
mSequenceDrainer.beginDrain();
}
@@ -552,6 +553,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
@Override
public CameraDeviceImpl.StateCallbackKK getDeviceStateCallback() {
final CameraCaptureSession session = this;
+ final Object interfaceLock = mDeviceImpl.mInterfaceLock;
+
return new CameraDeviceImpl.StateCallbackKK() {
private boolean mBusy = false;
@@ -588,7 +591,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
boolean isAborting;
if (DEBUG) Log.v(TAG, mIdString + "onIdle");
- synchronized (session) {
+ synchronized (interfaceLock) {
isAborting = mAborting;
}
@@ -606,7 +609,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
if (mBusy && isAborting) {
mAbortDrainer.taskFinished();
- synchronized (session) {
+ synchronized (interfaceLock) {
mAborting = false;
}
}
@@ -729,7 +732,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
@Override
public void onDrained() {
if (DEBUG) Log.v(TAG, mIdString + "onAbortDrained");
- synchronized (CameraCaptureSessionImpl.this) {
+ synchronized (mDeviceImpl.mInterfaceLock) {
/*
* Any queued aborts have now completed.
*
@@ -757,7 +760,6 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
// Take device lock before session lock so that we can call back into device
// without causing a deadlock
synchronized (mDeviceImpl.mInterfaceLock) {
- synchronized (CameraCaptureSessionImpl.this) {
/*
* The device is now IDLE, and has settled. It will not transition to
* ACTIVE or BUSY again by itself.
@@ -766,33 +768,31 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
*
* This operation is idempotent; a session will not be closed twice.
*/
- if (DEBUG)
- Log.v(TAG, mIdString + "Session drain complete, skip unconfigure: " +
- mSkipUnconfigure);
-
- // Fast path: A new capture session has replaced this one; don't wait for idle
- // as we won't get state updates any more anyway.
- if (mSkipUnconfigure) {
- return;
- }
+ if (DEBUG)
+ Log.v(TAG, mIdString + "Session drain complete, skip unconfigure: " +
+ mSkipUnconfigure);
- // Final slow path: unconfigure the camera, no session has replaced us and
- // everything is idle.
- try {
- // begin transition to unconfigured
- mDeviceImpl.configureStreamsChecked(/*inputConfig*/null, /*outputs*/null,
- /*operatingMode*/ ICameraDeviceUser.NORMAL_MODE);
- } catch (CameraAccessException e) {
- // OK: do not throw checked exceptions.
- Log.e(TAG, mIdString + "Exception while unconfiguring outputs: ", e);
-
- // TODO: call onError instead of onClosed if this happens
- } catch (IllegalStateException e) {
- // Camera is already closed, so nothing left to do
- if (DEBUG) Log.v(TAG, mIdString +
- "Camera was already closed or busy, skipping unconfigure");
- }
+ // Fast path: A new capture session has replaced this one; don't wait for idle
+ // as we won't get state updates any more anyway.
+ if (mSkipUnconfigure) {
+ return;
+ }
+
+ // Final slow path: unconfigure the camera, no session has replaced us and
+ // everything is idle.
+ try {
+ // begin transition to unconfigured
+ mDeviceImpl.configureStreamsChecked(/*inputConfig*/null, /*outputs*/null,
+ /*operatingMode*/ ICameraDeviceUser.NORMAL_MODE);
+ } catch (CameraAccessException e) {
+ // OK: do not throw checked exceptions.
+ Log.e(TAG, mIdString + "Exception while unconfiguring outputs: ", e);
+ // TODO: call onError instead of onClosed if this happens
+ } catch (IllegalStateException e) {
+ // Camera is already closed, so nothing left to do
+ if (DEBUG) Log.v(TAG, mIdString +
+ "Camera was already closed or busy, skipping unconfigure");
}
}
}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 6a02b6b2e6e7..bda80390a614 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -256,6 +256,15 @@ public final class DisplayManager {
*/
public static final int VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH = 1 << 6;
+ /**
+ * Virtual display flag: Indicates that the orientation of this display device is coupled to
+ * the rotation of its associated logical display.
+ *
+ * @see #createVirtualDisplay
+ * @hide
+ */
+ public static final int VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT = 1 << 7;
+
/** @hide */
public DisplayManager(Context context) {
mContext = context;
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 004530837206..d73d3d8b04cf 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -654,6 +654,7 @@ public class UsbManager {
Preconditions.checkNotNull(port, "port must not be null");
UsbPort.checkRoles(powerRole, dataRole);
+ Log.d(TAG, "setPortRoles Package:" + mContext.getPackageName());
try {
mService.setPortRoles(port.getId(), powerRole, dataRole);
} catch (RemoteException e) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index fcb99b167d1e..f47807142376 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -602,6 +602,15 @@ public class ConnectivityManager {
public final static int REQUEST_ID_UNSET = 0;
/**
+ * Static unique request used as a tombstone for NetworkCallbacks that have been unregistered.
+ * This allows to distinguish when unregistering NetworkCallbacks those that were never
+ * registered and those that were already unregistered.
+ * @hide
+ */
+ private final static NetworkRequest ALREADY_UNREGISTERED =
+ new NetworkRequest.Builder().clearCapabilities().build();
+
+ /**
* A NetID indicating no Network is selected.
* Keep in sync with bionic/libc/dns/include/resolv_netid.h
* @hide
@@ -2686,10 +2695,6 @@ public class ConnectivityManager {
public void onNetworkResumed(Network network) {}
private NetworkRequest networkRequest;
-
- private boolean isRegistered() {
- return (networkRequest != null) && (networkRequest.requestId != REQUEST_ID_UNSET);
- }
}
/**
@@ -2856,7 +2861,8 @@ public class ConnectivityManager {
final NetworkRequest request;
try {
synchronized(sCallbacks) {
- if (callback.isRegistered()) {
+ if (callback.networkRequest != null
+ && callback.networkRequest != ALREADY_UNREGISTERED) {
// TODO: throw exception instead and enforce 1:1 mapping of callbacks
// and requests (http://b/20701525).
Log.e(TAG, "NetworkCallback was already registered");
@@ -3302,8 +3308,10 @@ public class ConnectivityManager {
// Find all requests associated to this callback and stop callback triggers immediately.
// Callback is reusable immediately. http://b/20701525, http://b/35921499.
synchronized (sCallbacks) {
- Preconditions.checkArgument(
- networkCallback.isRegistered(), "NetworkCallback was not registered");
+ Preconditions.checkArgument(networkCallback.networkRequest != null,
+ "NetworkCallback was not registered");
+ Preconditions.checkArgument(networkCallback.networkRequest != ALREADY_UNREGISTERED,
+ "NetworkCallback was already unregistered");
for (Map.Entry<NetworkRequest, NetworkCallback> e : sCallbacks.entrySet()) {
if (e.getValue() == networkCallback) {
reqs.add(e.getKey());
@@ -3319,7 +3327,7 @@ public class ConnectivityManager {
// Only remove mapping if rpc was successful.
sCallbacks.remove(r);
}
- networkCallback.networkRequest = null;
+ networkCallback.networkRequest = ALREADY_UNREGISTERED;
}
}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index fa854b078292..f243f377cb56 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -699,6 +699,7 @@ public final class Debug
dest.writeInt(dalvikPrivateClean);
dest.writeInt(dalvikSharedClean);
dest.writeInt(dalvikSwappedOut);
+ dest.writeInt(dalvikSwappedOutPss);
dest.writeInt(nativePss);
dest.writeInt(nativeSwappablePss);
dest.writeInt(nativePrivateDirty);
@@ -706,6 +707,7 @@ public final class Debug
dest.writeInt(nativePrivateClean);
dest.writeInt(nativeSharedClean);
dest.writeInt(nativeSwappedOut);
+ dest.writeInt(nativeSwappedOutPss);
dest.writeInt(otherPss);
dest.writeInt(otherSwappablePss);
dest.writeInt(otherPrivateDirty);
@@ -726,6 +728,7 @@ public final class Debug
dalvikPrivateClean = source.readInt();
dalvikSharedClean = source.readInt();
dalvikSwappedOut = source.readInt();
+ dalvikSwappedOutPss = source.readInt();
nativePss = source.readInt();
nativeSwappablePss = source.readInt();
nativePrivateDirty = source.readInt();
@@ -733,6 +736,7 @@ public final class Debug
nativePrivateClean = source.readInt();
nativeSharedClean = source.readInt();
nativeSwappedOut = source.readInt();
+ nativeSwappedOutPss = source.readInt();
otherPss = source.readInt();
otherSwappablePss = source.readInt();
otherPrivateDirty = source.readInt();
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 50b4f8c7facf..56d6e0a62f94 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -369,11 +369,11 @@ public class FileUtils {
* constraints remain.
*
* @param minCount Always keep at least this many files.
- * @param minAge Always keep files younger than this age.
+ * @param minAgeMs Always keep files younger than this age, in milliseconds.
* @return if any files were deleted.
*/
- public static boolean deleteOlderFiles(File dir, int minCount, long minAge) {
- if (minCount < 0 || minAge < 0) {
+ public static boolean deleteOlderFiles(File dir, int minCount, long minAgeMs) {
+ if (minCount < 0 || minAgeMs < 0) {
throw new IllegalArgumentException("Constraints must be positive or 0");
}
@@ -393,9 +393,9 @@ public class FileUtils {
for (int i = minCount; i < files.length; i++) {
final File file = files[i];
- // Keep files newer than minAge
+ // Keep files newer than minAgeMs
final long age = System.currentTimeMillis() - file.lastModified();
- if (age > minAge) {
+ if (age > minAgeMs) {
if (file.delete()) {
Log.d(TAG, "Deleted old file " + file);
deleted = true;
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index db9f28b77288..6f458e084a42 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -22,20 +22,26 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.UserManager;
+import android.provider.Settings;
+import android.telephony.euicc.EuiccManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
+import com.android.internal.logging.MetricsLogger;
+
import libcore.io.Streams;
-import java.io.ByteArrayInputStream;
import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -46,22 +52,19 @@ import java.io.InputStream;
import java.io.RandomAccessFile;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
-import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
import java.util.Locale;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
-import com.android.internal.logging.MetricsLogger;
-
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
@@ -84,11 +87,19 @@ public class RecoverySystem {
/** Send progress to listeners no more often than this (in ms). */
private static final long PUBLISH_PROGRESS_INTERVAL_MS = 500;
+ private static final long DEFAULT_EUICC_WIPING_TIMEOUT_MILLIS = 30000L; // 30 s
+
+ private static final long MIN_EUICC_WIPING_TIMEOUT_MILLIS = 5000L; // 5 s
+
+ private static final long MAX_EUICC_WIPING_TIMEOUT_MILLIS = 60000L; // 60 s
+
/** Used to communicate with recovery. See bootable/recovery/recovery.cpp. */
private static final File RECOVERY_DIR = new File("/cache/recovery");
private static final File LOG_FILE = new File(RECOVERY_DIR, "log");
private static final File LAST_INSTALL_FILE = new File(RECOVERY_DIR, "last_install");
private static final String LAST_PREFIX = "last_";
+ private static final String ACTION_WIPE_EUICC_DATA =
+ "com.android.internal.action.WIPE_EUICC_DATA";
/**
* The recovery image uses this file to identify the location (i.e. blocks)
@@ -673,18 +684,26 @@ public class RecoverySystem {
*/
public static void rebootWipeUserData(Context context) throws IOException {
rebootWipeUserData(context, false /* shutdown */, context.getPackageName(),
- false /* force */);
+ false /* force */, false /* wipeEuicc */);
}
/** {@hide} */
public static void rebootWipeUserData(Context context, String reason) throws IOException {
- rebootWipeUserData(context, false /* shutdown */, reason, false /* force */);
+ rebootWipeUserData(context, false /* shutdown */, reason, false /* force */,
+ false /* wipeEuicc */);
}
/** {@hide} */
public static void rebootWipeUserData(Context context, boolean shutdown)
throws IOException {
- rebootWipeUserData(context, shutdown, context.getPackageName(), false /* force */);
+ rebootWipeUserData(context, shutdown, context.getPackageName(), false /* force */,
+ false /* wipeEuicc */);
+ }
+
+ /** {@hide} */
+ public static void rebootWipeUserData(Context context, boolean shutdown, String reason,
+ boolean force) throws IOException {
+ rebootWipeUserData(context, shutdown, reason, force, false /* wipeEuicc */);
}
/**
@@ -701,6 +720,7 @@ public class RecoverySystem {
* @param reason the reason for the wipe that is visible in the logs
* @param force whether the {@link UserManager.DISALLOW_FACTORY_RESET} user restriction
* should be ignored
+ * @param wipeEuicc whether wipe the euicc data
*
* @throws IOException if writing the recovery command file
* fails, or if the reboot itself fails.
@@ -709,7 +729,7 @@ public class RecoverySystem {
* @hide
*/
public static void rebootWipeUserData(Context context, boolean shutdown, String reason,
- boolean force) throws IOException {
+ boolean force, boolean wipeEuicc) throws IOException {
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
if (!force && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
throw new SecurityException("Wiping data is not allowed for this user.");
@@ -731,6 +751,10 @@ public class RecoverySystem {
// Block until the ordered broadcast has completed.
condition.block();
+ if (wipeEuicc) {
+ wipeEuiccData(context);
+ }
+
String shutdownArg = null;
if (shutdown) {
shutdownArg = "--shutdown_after";
@@ -745,6 +769,61 @@ public class RecoverySystem {
bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg);
}
+ private static void wipeEuiccData(Context context) {
+ EuiccManager euiccManager = (EuiccManager) context.getSystemService(
+ Context.EUICC_SERVICE);
+ if (euiccManager != null && euiccManager.isEnabled()) {
+ CountDownLatch euiccFactoryResetLatch = new CountDownLatch(1);
+
+ BroadcastReceiver euiccWipeFinishReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_WIPE_EUICC_DATA.equals(intent.getAction())) {
+ if (getResultCode() != EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK) {
+ int detailedCode = intent.getIntExtra(
+ EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 0);
+ Log.e(TAG, "Error wiping euicc data, Detailed code = "
+ + detailedCode);
+ } else {
+ Log.d(TAG, "Successfully wiped euicc data.");
+ }
+ euiccFactoryResetLatch.countDown();
+ }
+ }
+ };
+
+ Intent intent = new Intent(ACTION_WIPE_EUICC_DATA);
+ intent.setPackage("android");
+ PendingIntent callbackIntent = PendingIntent.getBroadcastAsUser(
+ context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, UserHandle.SYSTEM);
+ IntentFilter filterConsent = new IntentFilter();
+ filterConsent.addAction(ACTION_WIPE_EUICC_DATA);
+ HandlerThread euiccHandlerThread = new HandlerThread("euiccWipeFinishReceiverThread");
+ euiccHandlerThread.start();
+ Handler euiccHandler = new Handler(euiccHandlerThread.getLooper());
+ context.registerReceiver(euiccWipeFinishReceiver, filterConsent, null, euiccHandler);
+ euiccManager.eraseSubscriptions(callbackIntent);
+ try {
+ long waitingTimeMillis = Settings.Global.getLong(
+ context.getContentResolver(),
+ Settings.Global.EUICC_WIPING_TIMEOUT_MILLIS,
+ DEFAULT_EUICC_WIPING_TIMEOUT_MILLIS);
+ if (waitingTimeMillis < MIN_EUICC_WIPING_TIMEOUT_MILLIS) {
+ waitingTimeMillis = MIN_EUICC_WIPING_TIMEOUT_MILLIS;
+ } else if (waitingTimeMillis > MAX_EUICC_WIPING_TIMEOUT_MILLIS) {
+ waitingTimeMillis = MAX_EUICC_WIPING_TIMEOUT_MILLIS;
+ }
+ if (!euiccFactoryResetLatch.await(waitingTimeMillis, TimeUnit.MILLISECONDS)) {
+ Log.e(TAG, "Timeout wiping eUICC data.");
+ }
+ context.unregisterReceiver(euiccWipeFinishReceiver);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ Log.e(TAG, "Wiping eUICC data interrupted", e);
+ }
+ }
+ }
+
/** {@hide} */
public static void rebootPromptAndWipeUserData(Context context, String reason)
throws IOException {
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 0611f175e809..2b82c77d5909 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -936,6 +936,11 @@ public final class StrictMode {
return this;
}
+ Builder disable(int bit) {
+ mMask &= ~bit;
+ return this;
+ }
+
/**
* Construct the VmPolicy instance.
*
@@ -1214,7 +1219,13 @@ public final class StrictMode {
if (IS_USER_BUILD) {
setCloseGuardEnabled(false);
} else {
- VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll().penaltyDropBox();
+ VmPolicy.Builder policyBuilder = new VmPolicy.Builder().detectAll();
+ if (!IS_ENG_BUILD) {
+ // Activity leak detection causes too much slowdown for userdebug because of the
+ // GCs.
+ policyBuilder = policyBuilder.disable(DETECT_VM_ACTIVITY_LEAKS);
+ }
+ policyBuilder = policyBuilder.penaltyDropBox();
if (IS_ENG_BUILD) {
policyBuilder.penaltyLog();
}
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index d921ed409d6c..f9030124cc63 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -82,7 +82,8 @@ public final class AlarmClock {
* If neither of the above are given then:
* <ul>
* <li>If exactly one active alarm exists, it is dismissed.
- * <li>If more than one active alarm exists, the user is prompted to choose the alarm to dismiss.
+ * <li>If more than one active alarm exists, the user is prompted to choose the alarm to
+ * dismiss.
* </ul>
* </p><p>
* If the extra {@link #EXTRA_ALARM_SEARCH_MODE} is used, and the search results contain two or
@@ -104,8 +105,7 @@ public final class AlarmClock {
* @see #EXTRA_ALARM_SEARCH_MODE
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_DISMISS_ALARM =
- "android.intent.action.DISMISS_ALARM";
+ public static final String ACTION_DISMISS_ALARM = "android.intent.action.DISMISS_ALARM";
/**
* Activity Action: Snooze a currently ringing alarm.
@@ -124,8 +124,7 @@ public final class AlarmClock {
* @see #EXTRA_ALARM_SNOOZE_DURATION
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_SNOOZE_ALARM =
- "android.intent.action.SNOOZE_ALARM";
+ public static final String ACTION_SNOOZE_ALARM = "android.intent.action.SNOOZE_ALARM";
/**
* Activity Action: Set a timer.
@@ -155,6 +154,16 @@ public final class AlarmClock {
public static final String ACTION_SET_TIMER = "android.intent.action.SET_TIMER";
/**
+ * Activity Action: Dismiss timers.
+ * <p>
+ * Dismiss all currently expired timers. If there are no expired timers, then this is a no-op.
+ * </p>
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_DISMISS_TIMER = "android.intent.action.DISMISS_TIMER";
+
+ /**
* Activity Action: Show the timers.
* <p>
* This action opens the timers page.
@@ -200,8 +209,7 @@ public final class AlarmClock {
* @see #ALARM_SEARCH_MODE_LABEL
* @see #ACTION_DISMISS_ALARM
*/
- public static final String EXTRA_ALARM_SEARCH_MODE =
- "android.intent.extra.alarm.SEARCH_MODE";
+ public static final String EXTRA_ALARM_SEARCH_MODE = "android.intent.extra.alarm.SEARCH_MODE";
/**
* Search for the alarm that is most closely matched by the search parameters
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bdc27f269427..de69df559ac2 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -410,6 +410,21 @@ public final class Settings {
"android.settings.BLUETOOTH_SETTINGS";
/**
+ * Activity Action: Show settings to allow configuration of Assist Gesture.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_ASSIST_GESTURE_SETTINGS =
+ "android.settings.ASSIST_GESTURE_SETTINGS";
+
+ /**
* Activity Action: Show settings to allow configuration of cast endpoints.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
@@ -5216,6 +5231,15 @@ public final class Settings {
public static final String USER_SETUP_COMPLETE = "user_setup_complete";
/**
+ * Whether the current user has been set up via setup wizard (0 = false, 1 = true)
+ * This value differs from USER_SETUP_COMPLETE in that it can be reset back to 0
+ * in case SetupWizard has been re-enabled on TV devices.
+ *
+ * @hide
+ */
+ public static final String TV_USER_SETUP_COMPLETE = "tv_user_setup_complete";
+
+ /**
* Prefix for category name that marks whether a suggested action from that category was
* completed.
* @hide
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 9df315b7deab..a80ef032e68f 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -19,29 +19,230 @@ import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.RemoteException;
+import android.provider.Settings;
+
import com.android.internal.os.HandlerCaller;
import android.annotation.SdkConstant;
-import android.app.Activity;
-import android.app.Service;
-import android.app.assist.AssistStructure;
-import android.content.Intent;
-import android.os.Bundle;
+import android.app.Service;import android.content.Intent;
import android.os.CancellationSignal;
import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.Looper;
import android.util.Log;
+import android.view.View;
+import android.view.ViewStructure;
+import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
+import android.view.autofill.AutofillValue;
import com.android.internal.os.SomeArgs;
-import java.util.ArrayList;
-import java.util.List;
-
/**
- * Top-level service of the current autofill service for a given user.
+ * An {@code AutofillService} is a service used to automatically fill the contents of the screen
+ * on behalf of a given user - for more information about autofill, read
+ * <a href="{@docRoot}preview/features/autofill.html">Autofill Framework</a>.
+ *
+ * <p>An {@code AutofillService} is only bound to the Android System for autofill purposes if:
+ * <ol>
+ * <li>It requires the {@code android.permission.BIND_AUTOFILL_SERVICE} permission in its
+ * manifest.
+ * <li>The user explicitly enables it using Android Settings (the
+ * {@link Settings#ACTION_REQUEST_SET_AUTOFILL_SERVICE} intent can be used to launch such
+ * Settings screen).
+ * </ol>
+ *
+ * <h3>Basic usage</h3>
+ *
+ * <p>The basic autofill process is defined by the workflow below:
+ * <ol>
+ * <li>User focus an editable {@link View}.
+ * <li>View calls {@link AutofillManager#notifyViewEntered(android.view.View)}.
+ * <li>A {@link ViewStructure} representing all views in the screen is created.
+ * <li>The Android System binds to the service and calls {@link #onConnected()}.
+ * <li>The service receives the view structure through the
+ * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)}.
+ * <li>The service replies through {@link FillCallback#onSuccess(FillResponse)}.
+ * <li>The Android System calls {@link #onDisconnected()} and unbinds from the
+ * {@code AutofillService}.
+ * <li>The Android System displays an UI affordance with the options sent by the service.
+ * <li>The user picks an option.
+ * <li>The proper views are autofilled.
+ * </ol>
+ *
+ * <p>This workflow was designed to minimize the time the Android System is bound to the service;
+ * for each call, it: binds to service, waits for the reply, and unbinds right away. Furthermore,
+ * those calls are considered stateless: if the service needs to keep state between calls, it must
+ * do its own state management (keeping in mind that the service's process might be killed by the
+ * Android System when unbound; for example, if the device is running low in memory).
+ *
+ * <p>Typically, the
+ * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} will:
+ * <ol>
+ * <li>Parse the view structure looking for autofillable views (for example, using
+ * {@link android.app.assist.AssistStructure.ViewNode#getAutofillHints()}.
+ * <li>Match the autofillable views with the user's data.
+ * <li>Create a {@link Dataset} for each set of user's data that match those fields.
+ * <li>Fill the dataset(s) with the proper {@link AutofillId}s and {@link AutofillValue}s.
+ * <li>Add the dataset(s) to the {@link FillResponse} passed to
+ * {@link FillCallback#onSuccess(FillResponse)}.
+ * </ol>
+ *
+ * <p>For example, for a login screen with username and password views where the user only has one
+ * account in the service, the response could be:
+ *
+ * <pre class="prettyprint">
+ * new FillResponse.Builder()
+ * .addDataset(new Dataset.Builder()
+ * .setValue(id1, AutofillValue.forText("homer"), createPresentation("homer"))
+ * .setValue(id2, AutofillValue.forText("D'OH!"), createPresentation("password for homer"))
+ * .build())
+ * .build();
+ * </pre>
+ *
+ * <p>But if the user had 2 accounts instead, the response could be:
+ *
+ * <pre class="prettyprint">
+ * new FillResponse.Builder()
+ * .addDataset(new Dataset.Builder()
+ * .setValue(id1, AutofillValue.forText("homer"), createPresentation("homer"))
+ * .setValue(id2, AutofillValue.forText("D'OH!"), createPresentation("password for homer"))
+ * .build())
+ * .addDataset(new Dataset.Builder()
+ * .setValue(id1, AutofillValue.forText("flanders"), createPresentation("flanders"))
+ * .setValue(id2, AutofillValue.forText("OkelyDokelyDo"), createPresentation("password for flanders"))
+ * .build())
+ * .build();
+ * </pre>
+ *
+ * <p>If the service does not find any autofillable view in the view structure, it should pass
+ * {@code null} to {@link FillCallback#onSuccess(FillResponse)}; if the service encountered an error
+ * processing the request, it should call {@link FillCallback#onFailure(CharSequence)}. For
+ * performance reasons, it's paramount that the service calls either
+ * {@link FillCallback#onSuccess(FillResponse)} or {@link FillCallback#onFailure(CharSequence)} for
+ * each {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} received - if it
+ * doesn't, the request will eventually time out and be discarded by the Android System.
+ *
+ * <h3>Saving user data</h3>
+ *
+ * <p>If the service is also interested on saving the data filled by the user, it must set a
+ * {@link SaveInfo} object in the {@link FillResponse}. See {@link SaveInfo} for more details and
+ * examples.
+ *
+ * <h3>User authentication</h3>
+ *
+ * <p>The service can provide an extra degree of security by requiring the user to authenticate
+ * before an app can be autofilled. The authentication is typically required in 2 scenarios:
+ * <ul>
+ * <li>To unlock the user data (for example, using a master password or fingerprint
+ * authentication) - see
+ * {@link FillResponse.Builder#setAuthentication(AutofillId[], android.content.IntentSender, android.widget.RemoteViews)}.
+ * <li>To unlock a specific dataset (for example, by providing a CVC for a credit card) - see
+ * {@link Dataset.Builder#setAuthentication(android.content.IntentSender)}.
+ * </ul>
+ *
+ * <p>When using authentication, it is recommended to encrypt only the sensitive data and leave
+ * labels unencrypted, so they can be used on presentation views. For example, if the user has a
+ * home and a work address, the {@code Home} and {@code Work} labels should be stored unencrypted
+ * (since they don't have any sensitive data) while the address data per se could be stored in an
+ * encrypted storage. Then when the user chooses the {@code Home} dataset, the platform starts
+ * the authentication flow, and the service can decrypt the sensitive data.
+ *
+ * <p>The authentication mechanism can also be used in scenarios where the service needs multiple
+ * steps to determine the datasets that can fill a screen. For example, when autofilling a financial
+ * app where the user has accounts for multiple banks, the workflow could be:
*
- * <p>Apps providing autofill capabilities must extend this service.
+ * <ol>
+ * <li>The first {@link FillResponse} contains datasets with the credentials for the financial
+ * app, plus a "fake" dataset whose presentation says "Tap here for banking apps credentials".
+ * <li>When the user selects the fake dataset, the service displays a dialog with available
+ * banking apps.
+ * <li>When the user select a banking app, the service replies with a new {@link FillResponse}
+ * containing the datasets for that bank.
+ * </ol>
+ *
+ * <p>Another example of multiple-steps dataset selection is when the service stores the user
+ * credentials in "vaults": the first response would contain fake datasets with the vault names,
+ * and the subsequent response would contain the app credentials stored in that vault.
+ *
+ * <h3>Data partitioning</h3>
+ *
+ * <p>The autofillable views in a screen should be grouped in logical groups called "partitions".
+ * Typical partitions are:
+ * <ul>
+ * <li>Credentials (username/email address, password).
+ * <li>Address (street, city, state, zip code, etc).
+ * <li>Payment info (credit card number, expiration date, and verification code).
+ * </ul>
+ * <p>For security reasons, when a screen has more than one partition, it's paramount that the
+ * contents of a dataset do not spawn multiple partitions, specially when one of the partitions
+ * contains data that is not specific to the application being autofilled. For example, a dataset
+ * should not contain fields for username, password, and credit card information. The reason for
+ * this rule is that a malicious app could draft a view structure where the credit card fields
+ * are not visible, so when the user selects a dataset from the username UI, the credit card info is
+ * released to the application without the user knowledge. Similar, it's recommended to always
+ * protect a dataset that contains sensitive information by requiring dataset authentication
+ * (see {@link Dataset.Builder#setAuthentication(android.content.IntentSender)}).
+ *
+ * <p>When the service detects that a screen have multiple partitions, it should return a
+ * {@link FillResponse} with just the datasets for the partition that originated the request (i.e.,
+ * the partition that has the {@link android.app.assist.AssistStructure.ViewNode} whose
+ * {@link android.app.assist.AssistStructure.ViewNode#isFocused()} returns {@code true}); then if
+ * the user selects a field from a different partition, the Android System will make another
+ * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} call for that partition,
+ * and so on.
+ *
+ * <p>Notice that when the user autofill a partition with the data provided by the service and the
+ * user did not change these fields, the autofilled value is sent back to the service in the
+ * subsequent calls (and can be obtained by calling
+ * {@link android.app.assist.AssistStructure.ViewNode#getAutofillValue()}). This is useful in the
+ * cases where the service must create datasets for a partition based on the choice made in a
+ * previous partition. For example, the 1st response for a screen that have credentials and address
+ * partitions could be:
+ *
+ * <pre class="prettyprint">
+ * new FillResponse.Builder()
+ * .addDataset(new Dataset.Builder() // partition 1 (credentials)
+ * .setValue(id1, AutofillValue.forText("homer"), createPresentation("homer"))
+ * .setValue(id2, AutofillValue.forText("D'OH!"), createPresentation("password for homer"))
+ * .build())
+ * .addDataset(new Dataset.Builder() // partition 1 (credentials)
+ * .setValue(id1, AutofillValue.forText("flanders"), createPresentation("flanders"))
+ * .setValue(id2, AutofillValue.forText("OkelyDokelyDo"), createPresentation("password for flanders"))
+ * .build())
+ * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_PASSWORD,
+ * new AutofillId[] { id1, id2 })
+ * .build())
+ * .build();
+ * </pre>
+ *
+ * <p>Then if the user selected {@code flanders}, the service would get a new
+ * {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} call, with the values of
+ * the fields {@code id1} and {@code id2} prepopulated, so the service could then fetch the address
+ * for the Flanders account and return the following {@link FillResponse} for the address partition:
+ *
+ * <pre class="prettyprint">
+ * new FillResponse.Builder()
+ * .addDataset(new Dataset.Builder() // partition 2 (address)
+ * .setValue(id3, AutofillValue.forText("744 Evergreen Terrace"), createPresentation("744 Evergreen Terrace")) // street
+ * .setValue(id4, AutofillValue.forText("Springfield"), createPresentation("Springfield")) // city
+ * .build())
+ * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_PASSWORD | SaveInfo.SAVE_DATA_TYPE_ADDRESS,
+ * new AutofillId[] { id1, id2 }) // username and password
+ * .setOptionalIds(new AutofillId[] { id3, id4 }) // state and zipcode
+ * .build())
+ * .build();
+ * </pre>
+ *
+ * <p>When the service returns multiple {@link FillResponse}, the last one overrides the previous;
+ * that's why the {@link SaveInfo} in the 2nd request above has the info for both partitions.
+ *
+ * <h3>Ignoring views</h3>
+ *
+ * <p>If the service find views that cannot be autofilled (for example, a text field representing
+ * the response to a Captcha challenge), it should mark those views as ignored by
+ * calling {@link FillResponse.Builder#setIgnoredIds(AutofillId...)} so the system does not trigger
+ * a new {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} when these views are
+ * focused.
*/
public abstract class AutofillService extends Service {
private static final String TAG = "AutofillService";
@@ -137,11 +338,6 @@ public abstract class AutofillService extends Service {
private HandlerCaller mHandlerCaller;
- /**
- * {@inheritDoc}
- *
- * <strong>NOTE: </strong>if overridden, it must call {@code super.onCreate()}.
- */
@CallSuper
@Override
public void onCreate() {
@@ -167,8 +363,7 @@ public abstract class AutofillService extends Service {
}
/**
- * Called by the Android system do decide if an {@link Activity} can be autofilled by the
- * service.
+ * Called by the Android system do decide if a screen can be autofilled by the service.
*
* <p>Service must call one of the {@link FillCallback} methods (like
* {@link FillCallback#onSuccess(FillResponse)}
@@ -186,12 +381,17 @@ public abstract class AutofillService extends Service {
@NonNull CancellationSignal cancellationSignal, @NonNull FillCallback callback);
/**
- * Called when user requests service to save the fields of an {@link Activity}.
+ * Called when user requests service to save the fields of a screen.
*
* <p>Service must call one of the {@link SaveCallback} methods (like
* {@link SaveCallback#onSuccess()} or {@link SaveCallback#onFailure(CharSequence)})
* to notify the result of the request.
*
+ * <p><b>NOTE: </b>to retrieve the actual value of the field, the service should call
+ * {@link android.app.assist.AssistStructure.ViewNode#getAutofillValue()}; if it calls
+ * {@link android.app.assist.AssistStructure.ViewNode#getText()} or other methods, there is no
+ * guarantee such method will return the most recent value of the field.
+ *
* @param request the {@link SaveRequest request} to handle.
* See {@link FillResponse} for examples of multiple-sections requests.
* @param callback object used to notify the result of the request.
@@ -207,22 +407,26 @@ public abstract class AutofillService extends Service {
public void onDisconnected() {
}
- /** @hide */
- @Deprecated
- public final void disableSelf() {
- getSystemService(AutofillManager.class).disableOwnedAutofillServices();
- }
-
/**
- * Returns the {@link FillEventHistory.Event events} since the last {@link FillResponse} was
- * returned.
+ * Gets the events that happened after the last
+ * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
+ * call.
+ *
+ * <p>This method is typically used to keep track of previous user actions to optimize further
+ * requests. For example, the service might return email addresses in alphabetical order by
+ * default, but change that order based on the address the user picked on previous requests.
*
- * <p>The history is not persisted over reboots.
+ * <p>The history is not persisted over reboots, and it's cleared every time the service
+ * replies to a {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} by calling
+ * {@link FillCallback#onSuccess(FillResponse)} or {@link FillCallback#onFailure(CharSequence)}
+ * (if the service doesn't call any of these methods, the history will clear out after some
+ * pre-defined time). Hence, the service should call {@link #getFillEventHistory()} before
+ * finishing the {@link FillCallback}.
*
- * @return The history or {@code null} if there are not events.
+ * @return The history or {@code null} if there are no events.
*/
@Nullable public final FillEventHistory getFillEventHistory() {
- AutofillManager afm = getSystemService(AutofillManager.class);
+ final AutofillManager afm = getSystemService(AutofillManager.class);
if (afm == null) {
return null;
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index af2eb34f8751..a2ec0993c2c9 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -31,17 +31,23 @@ import com.android.internal.util.Preconditions;
import java.util.ArrayList;
/**
- * A set of data that can be used to autofill an {@link android.app.Activity}.
+ * A dataset object represents a group of key/value pairs used to autofill parts of a screen.
*
- * <p>It contains:
+ * <p>In its simplest form, a dataset contains one or more key / value pairs (comprised of
+ * {@link AutofillId} and {@link AutofillValue} respectively); and one or more
+ * {@link RemoteViews presentation} for these pairs (a pair could have its own
+ * {@link RemoteViews presentation}, or use the default {@link RemoteViews presentation} associated
+ * with the whole dataset). When an autofill service returns datasets in a {@link FillResponse}
+ * and the screen input is focused in a view that is present in at least one of these datasets,
+ * the Android System displays a UI affordance containing the {@link RemoteViews presentation} of
+ * all datasets pairs that have that view's {@link AutofillId}. Then, when the user selects a
+ * dataset from the affordance, all views in that dataset are autofilled.
*
- * <ol>
- * <li>A list of values for input fields.
- * <li>A presentation view to visualize.
- * <li>An optional intent to authenticate.
- * </ol>
+ * <p>In a more sophisticated form, the dataset value can be protected until the user authenticates
+ * the dataset - see {@link Dataset.Builder#setAuthentication(IntentSender)}.
*
- * @see android.service.autofill.FillResponse for examples.
+ * @see android.service.autofill.AutofillService for more information and examples about the
+ * role of datasets in the autofill workflow.
*/
public final class Dataset implements Parcelable {
@@ -113,7 +119,7 @@ public final class Dataset implements Parcelable {
}
/**
- * A builder for {@link Dataset} objects. You must to provide at least
+ * A builder for {@link Dataset} objects. You must provide at least
* one value for a field or set an authentication intent.
*/
public static final class Builder {
@@ -175,9 +181,9 @@ public final class Dataset implements Parcelable {
* credit card information without the CVV for the data set in the {@link FillResponse
* response} then the returned data set should contain the CVV entry.
*
- * <p></><strong>Note:</strong> Do not make the provided pending intent
+ * <p><b>NOTE:</b> Do not make the provided pending intent
* immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
- * platform needs to fill in the authentication arguments.</p>
+ * platform needs to fill in the authentication arguments.
*
* @param authentication Intent to an activity with your authentication flow.
* @return This builder.
@@ -191,7 +197,7 @@ public final class Dataset implements Parcelable {
}
/**
- * Sets the id for the dataset.
+ * Sets the id for the dataset so its usage history can be retrieved later.
*
* <p>The id of the last selected dataset can be read from
* {@link AutofillService#getFillEventHistory()}. If the id is not set it will not be clear
@@ -214,13 +220,12 @@ public final class Dataset implements Parcelable {
*
* @param id id returned by {@link
* android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
- * @param value value to be auto filled. Pass {@code null} if you do not have the value
+ * @param value value to be autofilled. Pass {@code null} if you do not have the value
* but the target view is a logical part of the dataset. For example, if
* the dataset needs an authentication and you have no access to the value.
- * Filtering matches any user typed string to {@code null} values.
* @return This builder.
- * @throws IllegalStateException if the builder was constructed without a presentation
- * ({@link RemoteViews}).
+ * @throws IllegalStateException if the builder was constructed without a
+ * {@link RemoteViews presentation}.
*/
public @NonNull Builder setValue(@NonNull AutofillId id, @Nullable AutofillValue value) {
throwIfDestroyed();
@@ -232,7 +237,8 @@ public final class Dataset implements Parcelable {
}
/**
- * Sets the value of a field, using a custom presentation to visualize it.
+ * Sets the value of a field, using a custom {@link RemoteViews presentation} to
+ * visualize it.
*
* @param id id returned by {@link
* android.app.assist.AssistStructure.ViewNode#getAutofillId()}.
@@ -272,10 +278,12 @@ public final class Dataset implements Parcelable {
}
/**
- * Creates a new {@link Dataset} instance. You should not interact
- * with this builder once this method is called. It is required
- * that you specified at least one field. Also it is mandatory to
- * provide a presentation view to visualize the data set in the UI.
+ * Creates a new {@link Dataset} instance.
+ *
+ * <p>You should not interact with this builder once this method is called.
+ *
+ * <p>It is required that you specify at least one field before calling this method. It's
+ * also mandatory to provide a presentation view to visualize the data set in the UI.
*
* @return The built dataset.
*/
diff --git a/core/java/android/service/autofill/FillContext.java b/core/java/android/service/autofill/FillContext.java
index f8a87516854d..cda2f4a23c9a 100644
--- a/core/java/android/service/autofill/FillContext.java
+++ b/core/java/android/service/autofill/FillContext.java
@@ -30,7 +30,6 @@ import android.util.ArrayMap;
import android.util.SparseIntArray;
import android.view.autofill.AutofillId;
-import java.util.ArrayList;
import java.util.LinkedList;
/**
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
index 3d72fccece9c..f7dc1c58ade1 100644
--- a/core/java/android/service/autofill/FillEventHistory.java
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -33,7 +33,20 @@ import java.util.ArrayList;
import java.util.List;
/**
- * Describes what happened after the latest call to {@link FillCallback#onSuccess(FillResponse)}.
+ * Describes what happened after the last
+ * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
+ * call.
+ *
+ * <p>This history is typically used to keep track of previous user actions to optimize further
+ * requests. For example, the service might return email addresses in alphabetical order by
+ * default, but change that order based on the address the user picked on previous requests.
+ *
+ * <p>The history is not persisted over reboots, and it's cleared every time the service
+ * replies to a
+ * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
+ * by calling {@link FillCallback#onSuccess(FillResponse)} or
+ * {@link FillCallback#onFailure(CharSequence)} (if the service doesn't call any of these methods,
+ * the history will clear out after some pre-defined time).
*/
public final class FillEventHistory implements Parcelable {
/**
@@ -41,6 +54,11 @@ public final class FillEventHistory implements Parcelable {
*/
private final int mServiceUid;
+ /**
+ * Not in parcel. The ID of the autofill session that created the {@link FillResponse}.
+ */
+ private final int mSessionId;
+
@Nullable private final Bundle mClientState;
@Nullable List<Event> mEvents;
@@ -55,10 +73,17 @@ public final class FillEventHistory implements Parcelable {
return mServiceUid;
}
+ /** @hide */
+ public int getSessionId() {
+ return mSessionId;
+ }
+
/**
- * Returns the client state of the {@link FillResponse}.
+ * Returns the client state set in the previous {@link FillResponse}.
*
- * @return The client state set by the last {@link FillResponse}
+ * <p><b>NOTE: </b>the state is associated with the app that was autofilled in the previous
+ * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
+ * , which is not necessary the same app being autofilled now.
*/
@Nullable public Bundle getClientState() {
return mClientState;
@@ -87,9 +112,10 @@ public final class FillEventHistory implements Parcelable {
/**
* @hide
*/
- public FillEventHistory(int serviceUid, @Nullable Bundle clientState) {
+ public FillEventHistory(int serviceUid, int sessionId, @Nullable Bundle clientState) {
mClientState = clientState;
mServiceUid = serviceUid;
+ mSessionId = sessionId;
}
@Override
@@ -190,7 +216,7 @@ public final class FillEventHistory implements Parcelable {
new Parcelable.Creator<FillEventHistory>() {
@Override
public FillEventHistory createFromParcel(Parcel parcel) {
- FillEventHistory selection = new FillEventHistory(0, parcel.readBundle());
+ FillEventHistory selection = new FillEventHistory(0, 0, parcel.readBundle());
int numEvents = parcel.readInt();
for (int i = 0; i < numEvents; i++) {
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index b1145ee38929..fd6da05aa237 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -23,6 +23,7 @@ import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Parcel;
import android.os.Parcelable;
+import android.view.View;
import com.android.internal.util.Preconditions;
@@ -32,7 +33,7 @@ import java.util.ArrayList;
import java.util.List;
/**
- * This class represents a request to an {@link AutofillService autofill provider}
+ * This class represents a request to an autofill service
* to interpret the screen and provide information to the system which views are
* interesting for saving and what are the possible ways to fill the inputs on
* the screen if applicable.
@@ -40,8 +41,29 @@ import java.util.List;
* @see AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
*/
public final class FillRequest implements Parcelable {
+
/**
* Indicates autofill was explicitly requested by the user.
+ *
+ * <p>Users typically make an explicit request to autofill a screen in two situations:
+ * <ul>
+ * <li>The app disabled autofill (using {@link View#setImportantForAutofill(int)}.
+ * <li>The service could not figure out how to autofill a screen (but the user knows the
+ * service has data for that app).
+ * </ul>
+ *
+ * <p>This flag is particularly useful for the second case. For example, the service could offer
+ * a complex UI where the user can map which screen views belong to each user data, or it could
+ * offer a simpler UI where the user picks the data for just the view used to trigger the
+ * request (that would be the view whose
+ * {@link android.app.assist.AssistStructure.ViewNode#isFocused()} method returns {@code true}).
+ *
+ * <p>An explicit autofill request is triggered when the
+ * {@link android.view.autofill.AutofillManager#requestAutofill(View)} or
+ * {@link android.view.autofill.AutofillManager#requestAutofill(View, int, android.graphics.Rect)}
+ * is called. For example, standard {@link android.widget.TextView} views that use
+ * an {@link android.widget.Editor} shows an {@code AUTOFILL} option in the overflow menu that
+ * triggers such request.
*/
public static final int FLAG_MANUAL_REQUEST = 0x1;
@@ -79,14 +101,14 @@ public final class FillRequest implements Parcelable {
}
/**
- * @return The unique id of this request.
+ * Gets the unique id of this request.
*/
public int getId() {
return mId;
}
/**
- * @return The flags associated with this request.
+ * Gets the flags associated with this request.
*
* @see #FLAG_MANUAL_REQUEST
*/
@@ -95,7 +117,7 @@ public final class FillRequest implements Parcelable {
}
/**
- * @return The contexts associated with each previous fill request.
+ * Gets the contexts associated with each previous fill request.
*/
public @NonNull List<FillContext> getFillContexts() {
return mContexts;
@@ -104,10 +126,10 @@ public final class FillRequest implements Parcelable {
/**
* Gets the extra client state returned from the last {@link
* AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
- * fill request}.
- * <p>
- * Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
- * save request} is made the client state is cleared.
+ * fill request}, so the service can use it for state management.
+ *
+ * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
+ * save request} is made, the client state is cleared.
*
* @return The client state.
*/
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index fcf18eb5130e..e13fdf68c831 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -21,6 +21,7 @@ import static android.view.autofill.Helper.sDebug;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.Activity;
import android.content.IntentSender;
import android.os.Bundle;
import android.os.Parcel;
@@ -36,100 +37,7 @@ import java.util.Arrays;
* Response for a {@link
* AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}.
*
- * <p>The response typically contains one or more {@link Dataset}s, each representing a set of
- * fields that can be autofilled together, and the Android system displays a dataset picker UI
- * affordance that the user must use before the {@link android.app.Activity} is filled with
- * the dataset.
- *
- * <p>For example, for a login page with username/password where the user only has one account in
- * the response could be:
- *
- * <pre class="prettyprint">
- * new FillResponse.Builder()
- * .add(new Dataset.Builder(createPresentation())
- * .setValue(id1, AutofillValue.forText("homer"))
- * .setValue(id2, AutofillValue.forText("D'OH!"))
- * .build())
- * .build();
- * </pre>
- *
- * <p>If the user had 2 accounts, each with its own user-provided names, the response could be:
- *
- * <pre class="prettyprint">
- * new FillResponse.Builder()
- * .add(new Dataset.Builder(createFirstPresentation())
- * .setValue(id1, AutofillValue.forText("homer"))
- * .setValue(id2, AutofillValue.forText("D'OH!"))
- * .build())
- * .add(new Dataset.Builder(createSecondPresentation())
- * .setValue(id1, AutofillValue.forText("elbarto")
- * .setValue(id2, AutofillValue.forText("cowabonga")
- * .build())
- * .build();
- * </pre>
- *
- * If the service is interested on saving the user-edited data back, it must set a {@link SaveInfo}
- * in the {@link FillResponse}. Typically, the {@link SaveInfo} contains the same ids as the
- * {@link Dataset}, but other combinations are possible - see {@link SaveInfo} for more details
- *
- * <p>If the service has multiple {@link Dataset}s for different sections of the activity,
- * for example, a user section for which there are two datasets followed by an address
- * section for which there are two datasets for each user user, then it should "partition"
- * the activity in sections and populate the response with just a subset of the data that would
- * fulfill the first section (the name in our example); then once the user fills the first
- * section and taps a field from the next section (the address in our example), the Android
- * system would issue another request for that section, and so on. Note that if the user
- * chooses to populate the first section with a service provided dataset, the subsequent request
- * would contain the populated values so you don't try to provide suggestions for the first
- * section but ony for the second one based on the context of what was already filled. For
- * example, the first response could be:
- *
- * <pre class="prettyprint">
- * new FillResponse.Builder()
- * .add(new Dataset.Builder(createFirstPresentation())
- * .setValue(id1, AutofillValue.forText("Homer"))
- * .setValue(id2, AutofillValue.forText("Simpson"))
- * .build())
- * .add(new Dataset.Builder(createSecondPresentation())
- * .setValue(id1, AutofillValue.forText("Bart"))
- * .setValue(id2, AutofillValue.forText("Simpson"))
- * .build())
- * .build();
- * </pre>
- *
- * <p>Then after the user picks the second dataset and taps the street field to
- * trigger another autofill request, the second response could be:
- *
- * <pre class="prettyprint">
- * new FillResponse.Builder()
- * .add(new Dataset.Builder(createThirdPresentation())
- * .setValue(id3, AutofillValue.forText("742 Evergreen Terrace"))
- * .setValue(id4, AutofillValue.forText("Springfield"))
- * .build())
- * .add(new Dataset.Builder(createFourthPresentation())
- * .setValue(id3, AutofillValue.forText("Springfield Power Plant"))
- * .setValue(id4, AutofillValue.forText("Springfield"))
- * .build())
- * .build();
- * </pre>
- *
- * <p>The service could require user authentication at the {@link FillResponse} or the
- * {@link Dataset} level, prior to autofilling an activity - see
- * {@link FillResponse.Builder#setAuthentication(AutofillId[], IntentSender, RemoteViews)} and
- * {@link Dataset.Builder#setAuthentication(IntentSender)}.
- *
- * <p>It is recommended that you encrypt only the sensitive data but leave the labels unencrypted
- * which would allow you to provide a dataset presentation views with labels and if the user
- * chooses one of them challenge the user to authenticate. For example, if the user has a
- * home and a work address the Home and Work labels could be stored unencrypted as they don't
- * have any sensitive data while the address data is in an encrypted storage. If the user
- * chooses Home, then the platform will start your authentication flow. If you encrypt all
- * data and require auth at the response level the user will have to interact with the fill
- * UI to trigger a request for the datasets (as they don't see the presentation views for the
- * possible options) which will start your auth flow and after successfully authenticating
- * the user will be presented with the Home and Work options to pick one. Hence, you have
- * flexibility how to implement your auth while storing labels non-encrypted and data
- * encrypted provides a better user experience.
+ * <p>See the main {@link AutofillService} documentation for more details and examples.
*/
public final class FillResponse implements Parcelable {
@@ -221,7 +129,7 @@ public final class FillResponse implements Parcelable {
private boolean mDestroyed;
/**
- * Requires a fill response authentication before autofilling the activity with
+ * Requires a fill response authentication before autofilling the screen with
* any data set in this response.
*
* <p>This is typically useful when a user interaction is required to unlock their
@@ -230,16 +138,16 @@ public final class FillResponse implements Parcelable {
* auth on the data set level leading to a better user experience. Note that if you
* use sensitive data as a label, for example an email address, then it should also
* be encrypted. The provided {@link android.app.PendingIntent intent} must be an
- * activity which implements your authentication flow. Also if you provide an auth
+ * {@link Activity} which implements your authentication flow. Also if you provide an auth
* intent you also need to specify the presentation view to be shown in the fill UI
* for the user to trigger your authentication flow.
*
* <p>When a user triggers autofill, the system launches the provided intent
* whose extras will have the {@link AutofillManager#EXTRA_ASSIST_STRUCTURE screen
* content} and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE
- * client state}. Once you complete your authentication flow you should set the activity
- * result to {@link android.app.Activity#RESULT_OK} and provide the fully populated
- * {@link FillResponse response} by setting it to the {@link
+ * client state}. Once you complete your authentication flow you should set the
+ * {@link Activity} result to {@link android.app.Activity#RESULT_OK} and provide the fully
+ * populated {@link FillResponse response} by setting it to the {@link
* AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra.
* For example, if you provided an empty {@link FillResponse resppnse} because the
* user's data was locked and marked that the response needs an authentication then
@@ -286,8 +194,8 @@ public final class FillResponse implements Parcelable {
* {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal,
* FillCallback)} requests.
*
- * <p>This is typically used when the service cannot autofill the view; for example, an
- * {@code EditText} representing a captcha.
+ * <p>This is typically used when the service cannot autofill the view; for example, a
+ * text field representing the result of a Captcha challenge.
*/
public Builder setIgnoredIds(AutofillId...ids) {
mIgnoredIds = ids;
@@ -316,8 +224,6 @@ public final class FillResponse implements Parcelable {
/**
* Sets the {@link SaveInfo} associated with this response.
*
- * <p>See {@link FillResponse} for more info.
- *
* @return This builder.
*/
public @NonNull Builder setSaveInfo(@NonNull SaveInfo saveInfo) {
@@ -335,7 +241,7 @@ public final class FillResponse implements Parcelable {
* fill requests and the subsequent save request.
*
* <p>If this method is called on multiple {@link FillResponse} objects for the same
- * activity, just the latest bundle is passed back to the service.
+ * screen, just the latest bundle is passed back to the service.
*
* <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
* save request} is made the client state is cleared.
@@ -350,9 +256,10 @@ public final class FillResponse implements Parcelable {
}
/**
- * Builds a new {@link FillResponse} instance. You must provide at least
- * one dataset or some savable ids or an authentication with a presentation
- * view.
+ * Builds a new {@link FillResponse} instance.
+ *
+ * <p>You must provide at least one dataset or some savable ids or an authentication with a
+ * presentation view.
*
* @return A built response.
*/
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 6ea7d5edb496..95d393b0234c 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -21,6 +21,7 @@ import static android.view.autofill.Helper.sDebug;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.Activity;
import android.content.IntentSender;
import android.os.Parcel;
import android.os.Parcelable;
@@ -45,70 +46,91 @@ import java.util.Arrays;
* two pieces of information:
*
* <ol>
- * <li>The type of user data that would be saved (like passoword or credit card info).
+ * <li>The type(s) of user data (like password or credit card info) that would be saved.
* <li>The minimum set of views (represented by their {@link AutofillId}) that need to be changed
* to trigger a save request.
* </ol>
*
- * Typically, the {@link SaveInfo} contains the same {@code id}s as the {@link Dataset}:
+ * <p>Typically, the {@link SaveInfo} contains the same {@code id}s as the {@link Dataset}:
*
* <pre class="prettyprint">
- * new FillResponse.Builder()
- * .add(new Dataset.Builder(createPresentation())
- * .setValue(id1, AutofillValue.forText("homer"))
- * .setValue(id2, AutofillValue.forText("D'OH!"))
- * .build())
- * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_PASSWORD, new int[] {id1, id2})
- * .build())
- * .build();
+ * new FillResponse.Builder()
+ * .addDataset(new Dataset.Builder()
+ * .setValue(id1, AutofillValue.forText("homer"), createPresentation("homer")) // username
+ * .setValue(id2, AutofillValue.forText("D'OH!"), createPresentation("password for homer")) // password
+ * .build())
+ * .setSaveInfo(new SaveInfo.Builder(
+ * SaveInfo.SAVE_DATA_TYPE_USERNAME | SaveInfo.SAVE_DATA_TYPE_PASSWORD,
+ * new AutofillId[] { id1, id2 }).build())
+ * .build();
* </pre>
*
- * There might be cases where the {@link AutofillService} knows how to fill the
- * {@link android.app.Activity}, but the user has no data for it. In that case, the
- * {@link FillResponse} should contain just the {@link SaveInfo}, but no {@link Dataset}s:
+ * <p>The save type flags are used to display the appropriate strings in the save UI affordance.
+ * You can pass multiple values, but try to keep it short if possible. In the above example, just
+ * {@code SaveInfo.SAVE_DATA_TYPE_PASSWORD} would be enough.
+ *
+ * <p>There might be cases where the {@link AutofillService} knows how to fill the screen,
+ * but the user has no data for it. In that case, the {@link FillResponse} should contain just the
+ * {@link SaveInfo}, but no {@link Dataset Datasets}:
*
* <pre class="prettyprint">
- * new FillResponse.Builder()
- * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_PASSWORD, new int[] {id1, id2})
- * .build())
- * .build();
+ * new FillResponse.Builder()
+ * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_PASSWORD,
+ * new AutofillId[] { id1, id2 }).build())
+ * .build();
* </pre>
*
* <p>There might be cases where the user data in the {@link AutofillService} is enough
* to populate some fields but not all, and the service would still be interested on saving the
- * other fields. In this scenario, the service could set the
+ * other fields. In that case, the service could set the
* {@link SaveInfo.Builder#setOptionalIds(AutofillId[])} as well:
*
* <pre class="prettyprint">
* new FillResponse.Builder()
- * .add(new Dataset.Builder(createPresentation())
- * .setValue(id1, AutofillValue.forText("742 Evergreen Terrace")) // street
- * .setValue(id2, AutofillValue.forText("Springfield")) // city
- * .build())
- * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_ADDRESS, new int[] {id1, id2})
- * .setOptionalIds(new int[] {id3, id4}) // state and zipcode
- * .build())
+ * .addDataset(new Dataset.Builder()
+ * .setValue(id1, AutofillValue.forText("742 Evergreen Terrace"),
+ * createPresentation("742 Evergreen Terrace")) // street
+ * .setValue(id2, AutofillValue.forText("Springfield"),
+ * createPresentation("Springfield")) // city
+ * .build())
+ * .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_ADDRESS,
+ * new AutofillId[] { id1, id2 }) // street and city
+ * .setOptionalIds(new AutofillId[] { id3, id4 }) // state and zipcode
+ * .build())
* .build();
* </pre>
*
- * The
- * {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}
- * is triggered after a call to {@link AutofillManager#commit()}, but only when all conditions
- * below are met:
+ * <p>The {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)} can be triggered after
+ * any of the following events:
+ * <ul>
+ * <li>The {@link Activity} finishes.
+ * <li>The app explicitly called {@link AutofillManager#commit()}.
+ * <li>All required views became invisible (if the {@link SaveInfo} was created with the
+ * {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} flag).
+ * </ul>
*
- * <ol>
+ * <p>But it is only triggered when all conditions below are met:
+ * <ul>
* <li>The {@link SaveInfo} associated with the {@link FillResponse} is not {@code null}.
- * <li>The {@link AutofillValue} of all required views (as set by the {@code requiredIds} passed
- * to {@link SaveInfo.Builder} constructor are not empty.
+ * <li>The {@link AutofillValue}s of all required views (as set by the {@code requiredIds} passed
+ * to the {@link SaveInfo.Builder} constructor are not empty.
* <li>The {@link AutofillValue} of at least one view (be it required or optional) has changed
- * (i.e., it's not the same value passed in a {@link Dataset}).
- * <li>The user explicitly tapped the affordance asking to save data for autofill.
- * </ol>
+ * (i.e., it's neither the same value passed in a {@link Dataset}, nor the initial value
+ * presented in the view).
+ * <li>The user explicitly tapped the UI affordance asking to save data for autofill.
+ * </ul>
+ *
+ * <p>The service can also customize some aspects of the save UI affordance:
+ * <ul>
+ * <li>Add a subtitle by calling {@link Builder#setDescription(CharSequence)}.
+ * <li>Customize the button used to reject the save request by calling
+ * {@link Builder#setNegativeAction(int, IntentSender)}.
+ * </ul>
*/
public final class SaveInfo implements Parcelable {
/**
- * Type used on when the service can save the contents of an activity, but cannot describe what
+ * Type used when the service can save the contents of a screen, but cannot describe what
* the content is for.
*/
public static final int SAVE_DATA_TYPE_GENERIC = 0x0;
@@ -181,8 +203,8 @@ public final class SaveInfo implements Parcelable {
/**
* Usually {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)}
- * is called once the activity finishes. If this flag is set it is called once all saved views
- * become invisible.
+ * is called once the {@link Activity} finishes. If this flag is set it is called once all
+ * saved views become invisible.
*/
public static final int FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE = 0x1;
@@ -294,9 +316,9 @@ public final class SaveInfo implements Parcelable {
}
/**
- * Set flags changing the save behavior.
+ * Sets flags changing the save behavior.
*
- * @param flags {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} or 0.
+ * @param flags {@link #FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE} or {@code 0}.
* @return This builder.
*/
public @NonNull Builder setFlags(@SaveInfoFlags int flags) {
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index 875f286e1a6b..26f85288699a 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -97,6 +97,10 @@ public abstract class EuiccService extends Service {
public static final String ACTION_RESOLVE_NO_PRIVILEGES =
"android.service.euicc.action.RESOLVE_NO_PRIVILEGES";
+ /** Intent extra set for resolution requests containing the package name of the calling app. */
+ public static final String EXTRA_RESOLUTION_CALLING_PACKAGE =
+ "android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE";
+
/** Result code for a successful operation. */
public static final int RESULT_OK = 0;
/** Result code indicating that an active SIM must be deactivated to perform the operation. */
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 3e9fab1aee27..cdb9b8229314 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -21,6 +21,7 @@ import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE;
import android.annotation.IntDef;
import android.annotation.RequiresPermission;
import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Point;
@@ -854,6 +855,9 @@ public final class Display {
/**
* Returns whether this display can be used to display wide color gamut content.
+ * This does not necessarily mean the device itself can render wide color gamut
+ * content. To ensure wide color gamut content can be produced, refer to
+ * {@link Configuration#isScreenWideColorGamut()}.
*/
public boolean isWideColorGamut() {
synchronized (this) {
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index caadc364a3fb..cb98c8816281 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -72,6 +72,15 @@ public abstract class DisplayEventReceiver {
* Creates a display event receiver.
*
* @param looper The looper to use when invoking callbacks.
+ */
+ public DisplayEventReceiver(Looper looper) {
+ this(looper, VSYNC_SOURCE_APP);
+ }
+
+ /**
+ * Creates a display event receiver.
+ *
+ * @param looper The looper to use when invoking callbacks.
* @param vsyncSource The source of the vsync tick. Must be on of the VSYNC_SOURCE_* values.
*/
public DisplayEventReceiver(Looper looper, int vsyncSource) {
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index 31cece49c79d..0a73949ef17a 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -62,6 +62,12 @@ public class HapticFeedbackConstants {
public static final int VIRTUAL_KEY_RELEASE = 7;
/**
+ * The user has performed a selection/insertion handle move on text field.
+ * @hide
+ */
+ public static final int TEXT_HANDLE_MOVE = 8;
+
+ /**
* This is a private constant. Feel free to renumber as desired.
* @hide
*/
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 5f55bdc0e0d3..04fa637b72f2 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -224,6 +224,14 @@ public final class MotionEvent extends InputEvent implements Parcelable {
* Constant for {@link #getActionMasked}: A movement has happened outside of the
* normal bounds of the UI element. This does not provide a full gesture,
* but only the initial location of the movement/touch.
+ * <p>
+ * Note: Because the location of any event will be outside the
+ * bounds of the view hierarchy, it will not get dispatched to
+ * any children of a ViewGroup by default. Therefore,
+ * movements with ACTION_OUTSIDE should be handled in either the
+ * root {@link View} or in the appropriate {@link Window.Callback}
+ * (e.g. {@link android.app.Activity} or {@link android.app.Dialog}).
+ * </p>
*/
public static final int ACTION_OUTSIDE = 4;
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 34ceeb7bcc0d..b035b7fd53ed 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -641,7 +641,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
mSurface.copyFrom(mSurfaceControl);
}
- if (getContext().getApplicationInfo().targetSdkVersion
+ if (sizeChanged && getContext().getApplicationInfo().targetSdkVersion
< Build.VERSION_CODES.O) {
// Some legacy applications use the underlying native {@link Surface} object
// as a key to whether anything has changed. In these cases, updates to the
@@ -838,6 +838,8 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
System.identityHashCode(this), frameNumber));
}
+ mRTLastReportedPosition.setEmpty();
+
if (mSurfaceControl == null) {
return;
}
@@ -858,7 +860,6 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
Log.e(TAG, "Exception configuring surface", ex);
}
}
- mRTLastReportedPosition.setEmpty();
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 5b964544644f..c329db4ff3e1 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -26247,9 +26247,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
}
mTooltipInfo.mTooltipText = tooltipText;
- if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
- mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
- }
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 04da4f1235e9..e27eab92319b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -963,7 +963,8 @@ public final class ViewRootImpl implements ViewParent,
|| insets.top != 0 || insets.bottom != 0;
final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
final boolean wideGamut =
- attrs.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT;
+ mContext.getResources().getConfiguration().isScreenWideColorGamut()
+ && attrs.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT;
mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
attrs.getTitle().toString());
@@ -7894,9 +7895,14 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void run() {
- // mSource may be changed in calls below.
+ // Protect against re-entrant code and attempt to do the right thing in the case that
+ // we're multithreaded.
View source = mSource;
mSource = null;
+ if (source == null) {
+ Log.e(TAG, "Accessibility content change has no source");
+ return;
+ }
// The accessibility may be turned off while we were waiting so check again.
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
mLastEventTimeMillis = SystemClock.uptimeMillis();
@@ -7913,6 +7919,22 @@ public final class ViewRootImpl implements ViewParent,
}
public void runOrPost(View source, int changeType) {
+ if (mHandler.getLooper() != Looper.myLooper()) {
+ CalledFromWrongThreadException e = new CalledFromWrongThreadException("Only the "
+ + "original thread that created a view hierarchy can touch its views.");
+ // TODO: Throw the exception
+ Log.e(TAG, "Accessibility content change on non-UI thread. Future Android "
+ + "versions will throw an exception.", e);
+ // Attempt to recover. This code does not eliminate the thread safety issue, but
+ // it should force any issues to happen near the above log.
+ mHandler.removeCallbacks(this);
+ if (mSource != null) {
+ // Dispatch whatever was pending. It's still possible that the runnable started
+ // just before we removed the callbacks, and bad things will happen, but at
+ // least they should happen very close to the logged error.
+ run();
+ }
+ }
if (mSource != null) {
// If there is no common predecessor, then mSource points to
// a removed view, hence in this case always prefer the source.
@@ -7929,12 +7951,12 @@ public final class ViewRootImpl implements ViewParent,
if (timeSinceLastMillis >= minEventIntevalMillis) {
removeCallbacksAndRun();
} else {
- mSource.postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
+ mHandler.postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
}
}
public void removeCallbacksAndRun() {
- mSource.removeCallbacks(this);
+ mHandler.removeCallbacks(this);
run();
}
}
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 55aed529037d..4c9cf40beb8d 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -229,6 +229,11 @@ public abstract class WindowManagerInternal {
public abstract boolean isKeyguardGoingAway();
/**
+ * @return Whether the keyguard is showing and not occluded.
+ */
+ public abstract boolean isKeyguardShowingAndNotOccluded();
+
+ /**
* Gets the frame of a window given its token.
*
* @param token The token.
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 2e8faeec6f13..0d676153b288 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -25,6 +25,7 @@ import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
@@ -532,8 +533,14 @@ public class ListPopupWindow implements ShowableListMenu {
public void setHeight(int height) {
if (height < 0 && ViewGroup.LayoutParams.WRAP_CONTENT != height
&& ViewGroup.LayoutParams.MATCH_PARENT != height) {
- throw new IllegalArgumentException(
- "Invalid height. Must be a positive value, MATCH_PARENT, or WRAP_CONTENT.");
+ if (mContext.getApplicationInfo().targetSdkVersion
+ < Build.VERSION_CODES.O) {
+ Log.e(TAG, "Negative value " + height + " passed to ListPopupWindow#setHeight"
+ + " produces undefined results");
+ } else {
+ throw new IllegalArgumentException(
+ "Invalid height. Must be a positive value, MATCH_PARENT, or WRAP_CONTENT.");
+ }
}
mDropDownHeight = height;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6b328ea01997..9a924890fcd7 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -913,7 +913,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
break;
case com.android.internal.R.styleable.TextAppearance_fontFamily:
- if (!context.isRestricted()) {
+ if (!context.isRestricted() && context.canLoadUnsafeResources()) {
try {
fontTypeface = appearance.getFont(attr);
} catch (UnsupportedOperationException
@@ -1233,7 +1233,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
break;
case com.android.internal.R.styleable.TextView_fontFamily:
- if (!context.isRestricted()) {
+ if (!context.isRestricted() && context.canLoadUnsafeResources()) {
try {
fontTypeface = a.getFont(attr);
} catch (UnsupportedOperationException | Resources.NotFoundException e) {
@@ -3417,7 +3417,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Typeface fontTypeface = null;
String fontFamily = null;
- if (!context.isRestricted()) {
+ if (!context.isRestricted() && context.canLoadUnsafeResources()) {
try {
fontTypeface = ta.getFont(R.styleable.TextAppearance_fontFamily);
} catch (UnsupportedOperationException | Resources.NotFoundException e) {
diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java
index bb54085ac3bf..860c5c4c3d3b 100644
--- a/core/java/com/android/internal/app/NightDisplayController.java
+++ b/core/java/com/android/internal/app/NightDisplayController.java
@@ -182,6 +182,10 @@ public final class NightDisplayController {
throw new IllegalArgumentException("Invalid autoMode: " + autoMode);
}
+ if (getAutoMode() != autoMode) {
+ Secure.putLongForUser(mContext.getContentResolver(),
+ Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1L, mUserId);
+ }
return Secure.putIntForUser(mContext.getContentResolver(),
Secure.NIGHT_DISPLAY_AUTO_MODE, autoMode, mUserId);
}
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 1ba92bfb6a77..0c046a92020b 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -534,7 +534,7 @@ public class NotificationColorUtil {
}
public static boolean satisfiesTextContrast(int backgroundColor, int foregroundColor) {
- return NotificationColorUtil.calculateContrast(backgroundColor, foregroundColor) >= 4.5;
+ return NotificationColorUtil.calculateContrast(foregroundColor, backgroundColor) >= 4.5;
}
/**
@@ -613,7 +613,7 @@ public class NotificationColorUtil {
*/
public static double calculateContrast(@ColorInt int foreground, @ColorInt int background) {
if (Color.alpha(background) != 255) {
- throw new IllegalArgumentException("background can not be translucent: #"
+ Log.wtf(TAG, "background can not be translucent: #"
+ Integer.toHexString(background));
}
if (Color.alpha(foreground) < 255) {
diff --git a/core/java/com/android/internal/view/TooltipPopup.java b/core/java/com/android/internal/view/TooltipPopup.java
index 52357ac486c2..3930214ea286 100644
--- a/core/java/com/android/internal/view/TooltipPopup.java
+++ b/core/java/com/android/internal/view/TooltipPopup.java
@@ -91,10 +91,6 @@ public class TooltipPopup {
return mContentView.getParent() != null;
}
- public void updateContent(CharSequence tooltipText) {
- mMessageView.setText(tooltipText);
- }
-
private void computePosition(View anchorView, int anchorX, int anchorY, boolean fromTouch,
WindowManager.LayoutParams outParams) {
outParams.token = anchorView.getWindowToken();
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index 5553a3ed22c5..4b6578bdff7f 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -30,9 +30,12 @@ using namespace uirenderer;
class SkColorFilterGlue {
public:
- static void SafeUnref(JNIEnv* env, jobject clazz, jlong skFilterHandle) {
- SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(skFilterHandle);
- SkSafeUnref(filter);
+ static void SafeUnref(SkShader* shader) {
+ SkSafeUnref(shader);
+ }
+
+ static jlong GetNativeFinalizer(JNIEnv*, jobject) {
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(&SafeUnref));
}
static jlong CreatePorterDuffFilter(JNIEnv* env, jobject, jint srcColor, jint modeHandle) {
@@ -57,7 +60,7 @@ public:
};
static const JNINativeMethod colorfilter_methods[] = {
- {"nSafeUnref", "(J)V", (void*) SkColorFilterGlue::SafeUnref}
+ {"nativeGetFinalizer", "()J", (void*) SkColorFilterGlue::GetNativeFinalizer }
};
static const JNINativeMethod porterduff_methods[] = {
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 19f779f39b1d..cdd3c094e009 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -58,6 +58,29 @@ static struct fields_t {
jmethodID onTransactID;
} gFields;
+struct JHwBinderHolder : public RefBase {
+ JHwBinderHolder() {}
+
+ sp<JHwBinder> get(JNIEnv *env, jobject obj) {
+ Mutex::Autolock autoLock(mLock);
+
+ sp<JHwBinder> binder = mBinder.promote();
+
+ if (binder == NULL) {
+ binder = new JHwBinder(env, obj);
+ mBinder = binder;
+ }
+
+ return binder;
+ }
+
+private:
+ Mutex mLock;
+ wp<JHwBinder> mBinder;
+
+ DISALLOW_COPY_AND_ASSIGN(JHwBinderHolder);
+};
+
// static
void JHwBinder::InitClass(JNIEnv *env) {
ScopedLocalRef<jclass> clazz(
@@ -75,10 +98,10 @@ void JHwBinder::InitClass(JNIEnv *env) {
}
// static
-sp<JHwBinder> JHwBinder::SetNativeContext(
- JNIEnv *env, jobject thiz, const sp<JHwBinder> &context) {
- sp<JHwBinder> old =
- (JHwBinder *)env->GetLongField(thiz, gFields.contextID);
+sp<JHwBinderHolder> JHwBinder::SetNativeContext(
+ JNIEnv *env, jobject thiz, const sp<JHwBinderHolder> &context) {
+ sp<JHwBinderHolder> old =
+ (JHwBinderHolder *)env->GetLongField(thiz, gFields.contextID);
if (context != NULL) {
context->incStrong(NULL /* id */);
@@ -94,27 +117,27 @@ sp<JHwBinder> JHwBinder::SetNativeContext(
}
// static
-sp<JHwBinder> JHwBinder::GetNativeContext(
+sp<JHwBinder> JHwBinder::GetNativeBinder(
JNIEnv *env, jobject thiz) {
- return (JHwBinder *)env->GetLongField(thiz, gFields.contextID);
+ JHwBinderHolder *holder =
+ reinterpret_cast<JHwBinderHolder *>(
+ env->GetLongField(thiz, gFields.contextID));
+
+ return holder->get(env, thiz);
}
JHwBinder::JHwBinder(JNIEnv *env, jobject thiz) {
jclass clazz = env->GetObjectClass(thiz);
CHECK(clazz != NULL);
- mClass = (jclass)env->NewGlobalRef(clazz);
- mObject = env->NewWeakGlobalRef(thiz);
+ mObject = env->NewGlobalRef(thiz);
}
JHwBinder::~JHwBinder() {
JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->DeleteWeakGlobalRef(mObject);
+ env->DeleteGlobalRef(mObject);
mObject = NULL;
-
- env->DeleteGlobalRef(mClass);
- mClass = NULL;
}
status_t JHwBinder::onTransact(
@@ -203,10 +226,10 @@ status_t JHwBinder::onTransact(
using namespace android;
static void releaseNativeContext(void *nativeContext) {
- sp<JHwBinder> binder = (JHwBinder *)nativeContext;
+ sp<JHwBinderHolder> context = static_cast<JHwBinderHolder *>(nativeContext);
- if (binder != NULL) {
- binder->decStrong(NULL /* id */);
+ if (context != NULL) {
+ context->decStrong(NULL /* id */);
}
}
@@ -217,8 +240,7 @@ static jlong JHwBinder_native_init(JNIEnv *env) {
}
static void JHwBinder_native_setup(JNIEnv *env, jobject thiz) {
- sp<JHwBinder> context = new JHwBinder(env, thiz);
-
+ sp<JHwBinderHolder> context = new JHwBinderHolder;
JHwBinder::SetNativeContext(env, thiz, context);
}
@@ -246,7 +268,7 @@ static void JHwBinder_native_registerService(
return; // XXX exception already pending?
}
- sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
+ sp<hardware::IBinder> binder = JHwBinder::GetNativeBinder(env, thiz);
/* TODO(b/33440494) this is not right */
sp<hidl::base::V1_0::IBase> base = new hidl::base::V1_0::BpHwBase(binder);
diff --git a/core/jni/android_os_HwBinder.h b/core/jni/android_os_HwBinder.h
index fa8fe01d6e93..5352f1e607c2 100644
--- a/core/jni/android_os_HwBinder.h
+++ b/core/jni/android_os_HwBinder.h
@@ -24,13 +24,15 @@
namespace android {
+struct JHwBinderHolder;
+
struct JHwBinder : public hardware::BHwBinder {
static void InitClass(JNIEnv *env);
- static sp<JHwBinder> SetNativeContext(
- JNIEnv *env, jobject thiz, const sp<JHwBinder> &context);
+ static sp<JHwBinderHolder> SetNativeContext(
+ JNIEnv *env, jobject thiz, const sp<JHwBinderHolder> &context);
- static sp<JHwBinder> GetNativeContext(JNIEnv *env, jobject thiz);
+ static sp<JHwBinder> GetNativeBinder(JNIEnv *env, jobject thiz);
JHwBinder(JNIEnv *env, jobject thiz);
@@ -45,7 +47,6 @@ protected:
TransactCallback callback);
private:
- jclass mClass;
jobject mObject;
DISALLOW_COPY_AND_ASSIGN(JHwBinder);
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index b21ea828f2a4..6ea809aa95ad 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -169,7 +169,6 @@ JHwParcel::JHwParcel(JNIEnv *env, jobject thiz)
jclass clazz = env->GetObjectClass(thiz);
CHECK(clazz != NULL);
- mClass = (jclass)env->NewGlobalRef(clazz);
mObject = env->NewWeakGlobalRef(thiz);
}
@@ -182,9 +181,6 @@ JHwParcel::~JHwParcel() {
env->DeleteWeakGlobalRef(mObject);
mObject = NULL;
-
- env->DeleteGlobalRef(mClass);
- mClass = NULL;
}
hardware::Parcel *JHwParcel::getParcel() {
@@ -542,7 +538,7 @@ static void JHwParcel_native_writeStrongBinder(
env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
- binder = JHwBinder::GetNativeContext(env, binderObj);
+ binder = JHwBinder::GetNativeBinder(env, binderObj);
} else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
binder = JHwRemoteBinder::GetNativeContext(
env, binderObj)->getBinder();
diff --git a/core/jni/android_os_HwParcel.h b/core/jni/android_os_HwParcel.h
index f81de9bf30b7..f6e61004b0e3 100644
--- a/core/jni/android_os_HwParcel.h
+++ b/core/jni/android_os_HwParcel.h
@@ -53,7 +53,6 @@ protected:
virtual ~JHwParcel();
private:
- jclass mClass;
jobject mObject;
hardware::Parcel *mParcel;
diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index f2f8e52db9f5..9c2ee9cfec45 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -272,7 +272,6 @@ JHwRemoteBinder::JHwRemoteBinder(
jclass clazz = env->GetObjectClass(thiz);
CHECK(clazz != NULL);
- mClass = (jclass)env->NewGlobalRef(clazz);
mObject = env->NewWeakGlobalRef(thiz);
}
@@ -281,9 +280,6 @@ JHwRemoteBinder::~JHwRemoteBinder() {
env->DeleteWeakGlobalRef(mObject);
mObject = NULL;
-
- env->DeleteGlobalRef(mClass);
- mClass = NULL;
}
sp<hardware::IBinder> JHwRemoteBinder::getBinder() const {
diff --git a/core/jni/android_os_HwRemoteBinder.h b/core/jni/android_os_HwRemoteBinder.h
index 77a02784926d..63aad0ab2923 100644
--- a/core/jni/android_os_HwRemoteBinder.h
+++ b/core/jni/android_os_HwRemoteBinder.h
@@ -68,7 +68,6 @@ protected:
virtual ~JHwRemoteBinder();
private:
- jclass mClass;
jobject mObject;
sp<hardware::IBinder> mBinder;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b4c5025e2f64..b72f8c5567c3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -302,6 +302,7 @@
<protected-broadcast android:name="com.android.server.WifiManager.action.DEVICE_IDLE" />
<protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
<protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
+ <protected-broadcast android:name="com.android.server.action.WIPE_EUICC_DATA" />
<protected-broadcast android:name="com.android.server.usb.ACTION_OPEN_IN_APPS" />
<protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
<protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index 863efef5c661..d83ccb23f64f 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -17,6 +17,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layoutDirection="ltr"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -30,6 +31,7 @@
<LinearLayout
android:id="@+id/time_layout"
+ android:layoutDirection="ltr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/timepicker_radial_picker_top_margin"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 12ae0a252150..b0b6404f1382 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Soek vir diens"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-oproepe"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Om oproepe te maak en boodskappe oor Wi-Fi te stuur, vra jou diensverskaffer eers om hierdie diens op te stel. Skakel Wi-Fi-oproepe dan weer in Instellings aan."</item>
+ <item msgid="3910386316304772394">"Om oproepe te maak en boodskappe oor Wi-Fi te stuur, vra eers jou diensverskaffer om hierdie diens op te stel. Skakel Wi-Fi-oproepe dan weer in Instellings aan. (Foutkode: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registreer by jou diensverskaffer"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Oop Wi-Fi-netwerke beskikbaar</item>
<item quantity="one">Oop Wi-Fi-netwerk beskikbaar</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Koppel aan oop Wi-Fi-netwerk"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Koppel tans aan oop Wi‑Fi-netwerk"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Aan Wi-Fi-netwerk gekoppel"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Kon nie aan Wi-Fi-netwerk koppel nie"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tik om alle netwerke te sien"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Koppel"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle netwerke"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Meld aan by Wi-Fi-netwerk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Meld by netwerk aan"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index e2dc03608e07..28889fecc7e0 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -131,7 +131,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="3910386316304772394">"በWi-Fi ላይ ጥሪዎችን ለማድረግ እና መልዕክቶችን ለመላክ መጀመሪያ የአገልግሎት አቅራቢዎ ይህን አገልግሎት እንዲያዘጋጅልዎ መጠየቅ አለብዎት። ከዚያ ከቅንብሮች ሆነው እንደገና የWi-Fi ጥሪን ያብሩ። (የስህተት ኮድ፦ <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"የአገልግሎት አቅራቢዎ ጋር ይመዝገቡ"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">የሚገኙ የWi-Fi አውታረ መረቦችን ክፈት</item>
<item quantity="other">የሚገኙ የWi-Fi አውታረ መረቦችን ክፈት</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"ከክፍት የWi‑Fi አውታረ መረብ ጋር ያገናኙ"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ከክፍት የWi‑Fi አውታረ መረብ ጋር በመገናኘት ላይ"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"ከWi‑Fi አውታረ መረብ ጋር ተገናኝቷል"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ከWi‑Fi አውታረ መረብ ጋር መገናኘት አልተቻለም"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ሁሉንም አውታረ መረቦችን ለማየት መታ ያድርጉ"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"አገናኝ"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ሁሉም አውታረ መረቦች"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ወደ Wi-Fi አውታረ መረብ በመለያ ግባ"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ወደ አውታረ መረብ በመለያ ይግቡ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index f14a0e447ea8..39348f209b4b 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -135,7 +135,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="3910386316304772394">"‏لإجراء مكالمات وإرسال رسائل عبر Wi-Fi، اطلب من مشغّل شبكة الجوّال أولاً إعداد هذه الخدمة، ثم شغّل الاتصال عبر Wi-Fi مرة أخرى من خلال الإعدادات. (رمز الخطأ: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"التسجيل لدى مشغّل شبكة الجوّال"</item>
@@ -1194,6 +1194,13 @@
<item quantity="other">‏تتوفر شبكات Wi-Fi مفتوحة</item>
<item quantity="one">‏تتوفر شبكة Wi-Fi واحدة مفتوحة</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"‏الاتصال بشبكة Wi-Fi المفتوحة"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"‏جارٍ الاتصال بشبكة Wi-Fi المفتوحة"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"‏تم الاتصال بشبكة Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"‏تعذَّر الاتصال بشبكة Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"انقر للاطلاع على جميع الشبكات"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"اتصال"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"جميع الشبكات"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"‏تسجيل الدخول إلى شبكة Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"تسجيل الدخول إلى الشبكة"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index c354f5f9beb9..6f39f7bf2aee 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Xidmət axtarılır"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi zəngi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Wi-Fi üzərindən zəng etmək və mesaj göndərmək üçün ilk öncə operatordan bu xidməti ayarlamağı tələb edin. Sonra Ayarlardan Wi-Fi çağrısını aktivləşdirin."</item>
+ <item msgid="3910386316304772394">"Zəng etmək və Wi-Fi üzərindən mesaj göndərmək üçün əvvəlcə operatordan bu cihazı quraşdırmağı tələb edin. Sonra Ayarlardan Wi-Fi zəngini deaktiv edin. (Xəta kodu: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Operatorla qeydiyyatdan keçin"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Əlçatan açıq Wi-Fi şəbəkələri</item>
<item quantity="one">Əlçatan açıq Wi-Fi şəbəkəsi</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Açıq Wi‑Fi şəbəkəsinə qoşulun"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Açıq Wi‑Fi şəbəkəsinə qoşulur"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi şəbəkəsinə qoşuldu"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi şəbəkəsinə qoşulmaq mümkün deyil"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Bütün şəbəkələri görmək üçün klikləyin"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Qoşulun"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Bütün Şəbəkələr"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi şəbəkəsinə daxil ol"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Şəbəkəyə daxil olun"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 0cd6c4b769b9..0be7892f79dc 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -132,7 +132,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Pretraživanje usluge"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Pozivanje preko Wi-Fi-ja"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Da biste upućivali pozive i slali poruke preko Wi-Fi-ja, prvo zatražite od mobilnog operatera da vam omogući ovu uslugu. Zatim u Podešavanjima ponovo uključite Pozivanje preko Wi-Fi-ja."</item>
+ <item msgid="3910386316304772394">"Da biste upućivali pozive i slali poruke preko Wi-Fi-ja, prvo zatražite od mobilnog operatera da vam omogući ovu uslugu. Zatim u Podešavanjima ponovo uključite Pozivanje preko Wi-Fi-ja. (kôd greške: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registrujte se kod mobilnog operatera"</item>
@@ -1128,6 +1128,13 @@
<item quantity="few">Otvorene Wi-Fi mreže su dostupne</item>
<item quantity="other">Otvorene Wi-Fi mreže su dostupne</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Povežite se sa otvorenom Wi‑Fi mrežom"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Povezujete se sa otvorenom Wi‑Fi mrežom"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Povezali ste se sa Wi‑Fi mrežom"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Povezivanje sa Wi‑Fi mrežom nije uspelo"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Dodirnite da biste videli sve mreže"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Poveži"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Sve mreže"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijavljivanje na Wi-Fi mrežu"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijavite se na mrežu"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 9ecdf830a991..5f1cad3da261 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -133,7 +133,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="3910386316304772394">"Каб рабіць выклікі і адпраўляць паведамленні па Wi-Fi, спачатку папрасіце свайго аператара наладзіць гэту паслугу. Затым зноў уключыце Wi-Fi-тэлефанію ў меню Налады. (Код памылкі: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Зарэгіструйцеся ў свайго аператара"</item>
@@ -1150,6 +1150,13 @@
<item quantity="many">адкрытых сетак Wi-Fi даступна</item>
<item quantity="other">адкрытай сеткі Wi-Fi даступна</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Падключыцеся да адкрытай сеткі Wi-Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ідзе падключэнне да адкрытай сеткі Wi‑Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Выканана падключэнне да адкрытай сеткі Wi‑Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не атрымалася падключыцца да адкрытай сеткі Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Дакраніцеся, каб убачыць усе сеткі"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Падключыцца"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Усе сеткі"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Уваход у сетку Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Увайдзіце ў сетку"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index f1f634578555..301805441040 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -131,7 +131,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="3910386316304772394">"За да извършвате обаждания и да изпращате съобщения през Wi-Fi, първо, помолете оператора си да настрои тази услуга. След това включете отново функцията за обаждания през Wi-Fi от настройките. (Код на грешката: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Регистриране с оператора ви"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Има достъпни отворени Wi-Fi мрежи</item>
<item quantity="one">Има достъпна отворена Wi-Fi мрежа</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Свързване с отворена Wi‑Fi мрежа"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Установява се връзка с отворена Wi‑Fi мрежа"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Установихте връзка с Wi-Fi мрежата"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не можа да се установи връзка с Wi‑Fi мрежата"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Докоснете, за да видите всички мрежи"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Свързване"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Всички мрежи"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Влизане в Wi-Fi мрежа"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Вход в мрежата"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index c936a2d5111d..77ea9214c6f0 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -130,9 +130,7 @@
<string name="roamingText12" msgid="1189071119992726320">"রোমিং ব্যানার বন্ধ আছে"</string>
<string name="roamingTextSearching" msgid="8360141885972279963">"পরিষেবা অনুসন্ধান করা হচ্ছে"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"ওয়াই-ফাই কলিং"</string>
- <string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"ওয়াই-ফাই এর মাধ্যমে কল করতে ও বার্তা পাঠাতে, প্রথমে আপনার পরিষেবা প্রদানকারীকে এই পরিষেবার সেট আপ করার বিষয়ে জিজ্ঞাসা করুন। তারপরে আবার সেটিংস থেকে ওয়াই-ফাই কলিং চালু করুন।"</item>
- </string-array>
+ <!-- no translation found for wfcOperatorErrorAlertMessages:0 (3910386316304772394) -->
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"আপনার পরিষেবা প্রদানকারীকে নথিভুক্ত করুন"</item>
</string-array>
@@ -1106,6 +1104,13 @@
<item quantity="one">খোলা ওয়াই-ফাই নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
<item quantity="other">খোলা ওয়াই-ফাই নেটওয়ার্কগুলি উপলব্ধ রয়েছে</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"উন্মুক্ত ওয়াই-ফাই নেটওয়ার্কে সংযোগ করুন"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"উন্মুক্ত ওয়াই-ফাই নেটওয়ার্কে সংযোগ করা হচ্ছে"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"উন্মুক্ত ওয়াই-ফাই নেটওয়ার্কে সংযুক্ত করা হয়েছে"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ওয়াই-ফাই নেটওয়ার্কে সংযোগ করা গেল না"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"সমস্ত নেটওয়ার্ক দেখতে ট্যাপ করুন"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"সংযুক্ত করুন"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"সমস্ত নেটওয়ার্ক"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ওয়াই-ফাই নেটওয়ার্কে প্রবেশ করুন"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"নেটওয়ার্কে প্রবেশ করুন"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index a055c15db80d..5188743457c1 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -132,7 +132,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Traženje usluge"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi pozivanje"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Da biste pozivali i slali poruke preko Wi-Fi-ja, prvo zatražite od operatera da postavi tu uslugu. Potom u Postavkama ponovo uključite Wi-Fi pozivanje."</item>
+ <item msgid="3910386316304772394">"Da biste pozivali i slali poruke koristeći Wi-Fi mrežu, prvo zatražite od operatera da postavi tu uslugu. Zatim ponovo uključite Wi-Fi pozivanje u Postavkama. (Kôd greške: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registrirajte se kod svog operatera"</item>
@@ -1130,6 +1130,13 @@
<item quantity="few">Otvorene Wi-Fi mreže su dostupne</item>
<item quantity="other">Otvorene Wi-Fi mreže su dostupne</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Povežite se na otvorenu Wi‑Fi mrežu"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Povezivanje na otvorenu Wi‑Fi mrežu"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Povezani ste na Wi‑Fi mrežu"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nije se moguće povezati na Wi‑Fi mrežu"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Dodirnite da vidite sve mreže"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Povežite se"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Sve mreže"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijavljivanje na Wi-Fi mrežu"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijava na mrežu"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index aa80ba5950a9..fc86c878d62c 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"S\'està cercant el servei"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Trucades per Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Per fer trucades i enviar missatges per Wi-Fi, primer has de demanar a l\'operador de telefonia mòbil que configuri aquest servei. Després, torna a activar les trucades per Wi-Fi des de Configuració."</item>
+ <item msgid="3910386316304772394">"Per fer trucades i enviar missatges per Wi-Fi, primer has de demanar a l\'operador de telefonia mòbil que configuri aquest servei. Després, torna a activar les trucades per Wi-Fi a Configuració. (Codi d\'error: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registra\'t amb el teu operador de telefonia mòbil"</item>
@@ -471,7 +471,7 @@
<string name="permlab_nfc" msgid="4423351274757876953">"controlar Comunicació de camp proper (NFC)"</string>
<string name="permdesc_nfc" msgid="7120611819401789907">"Permet que l\'aplicació es comuniqui amb les etiquetes, les targetes i els lectors de Comunicació de camp proper (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"desactivació del bloqueig de pantalla"</string>
- <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permet que l\'aplicació desactivi el bloqueig del teclat i qualsevol element de seguretat de contrasenyes associat. Per exemple, el telèfon desactiva el bloqueig del teclat en rebre una trucada telefònica entrant i, a continuació, reactiva el bloqueig del teclat quan finalitza la trucada."</string>
+ <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permet que l\'aplicació desactivi el bloqueig del teclat i qualsevol element de seguretat de contrasenyes associat. Per exemple, el telèfon desactiva el bloqueig del teclat en rebre una trucada entrant i, a continuació, reactiva el bloqueig del teclat quan finalitza la trucada."</string>
<string name="permlab_manageFingerprint" msgid="5640858826254575638">"Gestionar el maquinari d\'empremtes digitals"</string>
<string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permet que l\'aplicació invoqui mètodes per afegir i suprimir plantilles d\'empremtes digitals que es puguin fer servir."</string>
<string name="permlab_useFingerprint" msgid="3150478619915124905">"Utilitzar el maquinari d\'empremtes digitals"</string>
@@ -788,13 +788,13 @@
<string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"Ha finalitzat la reorganització del widget."</string>
<string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"S\'ha suprimit el widget de <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>."</string>
<string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"Desplega l\'àrea de desbloqueig."</string>
- <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Desbloqueig lliscant el dit"</string>
+ <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"Desbloqueig lliscant"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueig mitjançant patró"</string>
<string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Desbloqueig facial"</string>
<string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueig mitjançant PIN"</string>
<string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueig mitjançant contrasenya"</string>
<string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Àrea de patró"</string>
- <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Àrea per lliscar el dit"</string>
+ <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Àrea per lliscar"</string>
<string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
<string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
<string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
@@ -1075,7 +1075,7 @@
<string name="dump_heap_notification" msgid="2618183274836056542">"<xliff:g id="PROC">%1$s</xliff:g> ha superat el límit de memòria"</string>
<string name="dump_heap_notification_detail" msgid="6901391084243999274">"S\'ha recopilat un procés \"heap dump\"; toca per compartir-lo"</string>
<string name="dump_heap_title" msgid="5864292264307651673">"Vols compartir el \"heap dump\"?"</string>
- <string name="dump_heap_text" msgid="4809417337240334941">"El procés <xliff:g id="PROC">%1$s</xliff:g> ha superat el límit de <xliff:g id="SIZE">%2$s</xliff:g> de memòria del procés. Hi ha un procés \"heap dump\" disponible perquè el comparteixis amb el desenvolupador. Vés amb compte: aquest \"heap dump\" pot contenir les dades personals a les quals l\'aplicació tingui accés."</string>
+ <string name="dump_heap_text" msgid="4809417337240334941">"El procés <xliff:g id="PROC">%1$s</xliff:g> ha superat el límit de <xliff:g id="SIZE">%2$s</xliff:g> de memòria del procés. Hi ha un procés \"heap dump\" disponible perquè el comparteixis amb el desenvolupador. Ves amb compte: aquest \"heap dump\" pot contenir les dades personals a les quals l\'aplicació tingui accés."</string>
<string name="sendText" msgid="5209874571959469142">"Tria una acció per al text"</string>
<string name="volume_ringtone" msgid="6885421406845734650">"Volum del timbre"</string>
<string name="volume_music" msgid="5421651157138628171">"Volum de multimèdia"</string>
@@ -1106,6 +1106,13 @@
<item quantity="other">Xarxes Wi-Fi obertes disponibles</item>
<item quantity="one">Xarxa Wi-Fi oberta disponible</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Connecta\'t a una xarxa Wi-Fi oberta"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"S\'està connectant a una xarxa Wi-Fi oberta"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"S\'ha connectat a la xarxa Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"No s\'ha pogut connectar a una xarxa Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toca per veure totes les xarxes"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connecta"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Totes les xarxes"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Inicia la sessió a la xarxa Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Inicia la sessió a la xarxa"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1259,7 +1266,7 @@
<string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Permet que una aplicació demani permís per ignorar les optimitzacions de bateria per a l\'aplicació."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Piqueu dos cops per controlar el zoom"</string>
<string name="gadget_host_error_inflating" msgid="4882004314906466162">"No s\'ha pogut afegir el widget."</string>
- <string name="ime_action_go" msgid="8320845651737369027">"Vés"</string>
+ <string name="ime_action_go" msgid="8320845651737369027">"Ves"</string>
<string name="ime_action_search" msgid="658110271822807811">"Cerca"</string>
<string name="ime_action_send" msgid="2316166556349314424">"Envia"</string>
<string name="ime_action_next" msgid="3138843904009813834">"Següent"</string>
@@ -1617,9 +1624,9 @@
<string name="lock_to_app_toast_locked" msgid="7849470948648628704">"No es pot deixar de fixar aquesta aplicació"</string>
<string name="lock_to_app_start" msgid="6643342070839862795">"Pantalla fixada"</string>
<string name="lock_to_app_exit" msgid="8598219838213787430">"Fixació de la pantalla anul·lada"</string>
- <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Sol·licita el codi PIN per anul·lar"</string>
- <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Sol·licita el patró de desbloqueig per anul·lar"</string>
- <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demana la contrasenya per anul·lar"</string>
+ <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Sol·licita el codi PIN per deixar de fixar"</string>
+ <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Sol·licita el patró de desbloqueig per deixar de fixar"</string>
+ <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Demana la contrasenya per deixar de fixar"</string>
<string name="package_installed_device_owner" msgid="6875717669960212648">"Instal·lat per l\'administrador"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"Actualitzat per l\'administrador"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"Suprimit per l\'administrador"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index f6858c2b7ea3..74c24740a6f8 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -133,7 +133,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Vyhledávání služby"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Volání přes Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Chcete-li volat a odesílat textové zprávy přes síť Wi-Fi, nejprve požádejte operátora, aby vám tuto službu nastavil. Poté volání přes Wi-Fi opět zapněte v Nastavení."</item>
+ <item msgid="3910386316304772394">"Chcete-li volat a odesílat SMS přes síť Wi-Fi, nejprve požádejte operátora, aby vám tuto službu nastavil. Poté volání přes Wi-Fi opět zapněte v Nastavení. (Kód chyby: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registrace u operátora"</item>
@@ -1150,6 +1150,13 @@
<item quantity="other">K dispozici jsou veřejné sítě Wi-Fi</item>
<item quantity="one">K dispozici je veřejná síť Wi-Fi</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Připojení k otevřené síti Wi-Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Připojování k otevřené síti Wi-Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Připojeno k síti Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Připojení k síti Wi-Fi se nezdařilo"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Klepnutím zobrazíte všechny sítě"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Připojit"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Všechny sítě"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Přihlásit se k síti Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Přihlásit se k síti"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index eab7b5d9f057..48a4f9e29592 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Søger efter tjeneste"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Opkald via Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Hvis du vil foretage opkald og sende beskeder via Wi-Fi, skal du først anmode dit mobilselskab om at konfigurere denne tjeneste. Derefter skal du slå Wi-Fi-opkald til igen fra Indstillinger."</item>
+ <item msgid="3910386316304772394">"Hvis du vil foretage opkald og sende beskeder via Wi-Fi, skal du først anmode dit mobilselskab om at konfigurere denne tjeneste. Derefter skal du aktivere Wi-Fi-opkald igen fra Indstillinger. (Fejlkode: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registrer dig hos dit mobilselskab"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">Åbne Wi-Fi-netværk er tilgængelige</item>
<item quantity="other">Åbne Wi-Fi-netværk er tilgængelige</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Opret forbindelse til et åbent Wi-Fi-netværk"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Opretter forbindelse til et åbent Wi‑Fi-netværk"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Forbundet til Wi-Fi-netværket"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Der kan ikke oprettes forbindelse til Wi-Fi-netværket"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tryk for at se alle netværk"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Opret forbindelse"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle netværk"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Log ind på Wi-Fi-netværk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Log ind på netværk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index e72e419a99e5..4b4a60402d61 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Suche nach Dienst"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Anrufe über WLAN"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Um über WLAN telefonieren und Nachrichten senden zu können, bitte zuerst deinen Mobilfunkanbieter, diesen Dienst einzurichten. Aktiviere die Option \"Anrufe über WLAN\" dann erneut über die Einstellungen."</item>
+ <item msgid="3910386316304772394">"Um über WLAN telefonieren und Nachrichten senden zu können, bitte zuerst deinen Mobilfunkanbieter, diesen Dienst einzurichten. Aktiviere die Option \"Anrufe über WLAN\" dann noch einmal über die Einstellungen. (Fehlercode: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registriere dich bei deinem Mobilfunkanbieter."</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Verfügbare WLAN-Netzwerke öffnen</item>
<item quantity="one">Verfügbares WLAN-Netzwerk öffnen</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Mit offenem WLAN verbinden"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Verbindung mit offenem WLAN wird hergestellt"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Mit WLAN verbunden"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"WLAN-Verbindung konnte nicht hergestellt werden"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tippen, um alle Netzwerke zu sehen"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Verbinden"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle Netzwerke"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"In WLAN-Netzwerk anmelden"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Im Netzwerk anmelden"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 97e85e16e906..969ef24af926 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Για να κάνετε κλήσεις και να στέλνετε μηνύματα μέσω Wi-Fi, ζητήστε πρώτα από την εταιρεία κινητής τηλεφωνίας να ρυθμίσει την υπηρεσία. Στη συνέχεια, ενεργοποιήστε ξανά την Κλήση Wi-Fi από τις Ρυθμίσεις. (Κωδικός σφάλματος: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Εγγραφείτε μέσω της εταιρείας κινητής τηλεφωνίας"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Υπάρχουν διαθέσιμα ανοικτά δίκτυα Wi-Fi</item>
<item quantity="one">Υπάρχει διαθέσιμο ανοικτό δίκτυο Wi-Fi</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Σύνδεση σε ανοιχτό δίκτυο Wi‑Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Σύνδεση σε ανοιχτό δίκτυο Wi‑Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Ολοκληρώθηκε η σύνδεση στο δίκτυο Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Δεν ήταν δυνατή η σύνδεση σε δίκτυο Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Πατήστε για να δείτε όλα τα δίκτυα"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Σύνδεση"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Όλα τα δίκτυα"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Συνδεθείτε στο δίκτυο Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Σύνδεση στο δίκτυο"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 8339fd56bd7d..fea0c6960ebb 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Searching for Service"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi Calling"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings."</item>
+ <item msgid="3910386316304772394">"To make calls and send messages over Wi-Fi, first ask your operator to set up this service. Then turn on Wi-Fi calling again from Settings. (Error code: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Register with your operator"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Open Wi-Fi networks available</item>
<item quantity="one">Open Wi-Fi network available</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Connect to open Wi‑Fi network"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connecting to open Wi‑Fi network"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Connected to Wi‑Fi network"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Could not connect to Wi‑Fi network"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"All Networks"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 8339fd56bd7d..fea0c6960ebb 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Searching for Service"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi Calling"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings."</item>
+ <item msgid="3910386316304772394">"To make calls and send messages over Wi-Fi, first ask your operator to set up this service. Then turn on Wi-Fi calling again from Settings. (Error code: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Register with your operator"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Open Wi-Fi networks available</item>
<item quantity="one">Open Wi-Fi network available</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Connect to open Wi‑Fi network"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connecting to open Wi‑Fi network"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Connected to Wi‑Fi network"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Could not connect to Wi‑Fi network"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"All Networks"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8339fd56bd7d..fea0c6960ebb 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Searching for Service"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi Calling"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings."</item>
+ <item msgid="3910386316304772394">"To make calls and send messages over Wi-Fi, first ask your operator to set up this service. Then turn on Wi-Fi calling again from Settings. (Error code: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Register with your operator"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Open Wi-Fi networks available</item>
<item quantity="one">Open Wi-Fi network available</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Connect to open Wi‑Fi network"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connecting to open Wi‑Fi network"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Connected to Wi‑Fi network"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Could not connect to Wi‑Fi network"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"All Networks"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Sign in to a Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Sign in to network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index faf53c2d9e17..e8d25c6df178 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Buscando servicio"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Llamada por Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Para realizar llamadas o enviar mensajes por Wi-Fi, primero solicítale al proveedor que instale el servicio. Luego, vuelve a activar las llamadas por Wi-Fi desde Configuración."</item>
+ <item msgid="3910386316304772394">"Para hacer llamadas y enviar mensajes mediante Wi-Fi, solicítale a tu proveedor que configure este servicio. Luego, vuelve a activar la Llamada con Wi-Fi en Configuración. (código de error: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Regístrate con tu proveedor."</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Abrir redes de Wi-Fi disponibles</item>
<item quantity="one">Abrir red de Wi-Fi disponible</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Conectarse a una red Wi-Fi abierta"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Conectándose a una red Wi-Fi abierta"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Se conectó a la red Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"No fue posible conectarse a la red Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Presiona para ver todas las redes"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectar"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas las redes"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Accede a una red Wi-Fi."</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Acceder a la red"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 3cdf001502c2..33bfa1affd12 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Buscando servicio"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Llamadas Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Para hacer llamadas y enviar mensajes por Wi-Fi, debes pedir antes a tu operador que configure este servicio. Una vez hecho esto, vuelva a activar las llamadas Wi-Fi en Ajustes."</item>
+ <item msgid="3910386316304772394">"Para hacer llamadas y enviar mensajes por Wi-Fi, pide antes a tu operador que configure este servicio. Una vez hecho esto, vuelva a activar la llamada por Wi-Fi en Ajustes. (Código de error: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Regístrate con tu operador"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Redes Wi-Fi abiertas disponibles</item>
<item quantity="one">Red Wi-Fi abierta disponible</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Conectarse a una red Wi-Fi abierta"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Conectándose a una red Wi-Fi abierta"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Conectado a la red Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"No se ha podido conectar a la red Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toca para ver todas las redes"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectarse"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas las redes"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Iniciar sesión en red Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Iniciar sesión en la red"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 8fd88a996810..070ce299f643 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Teenuse otsimine"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"WiFi-kõned"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Üle WiFi-võrgu helistamiseks ja sõnumite saatmiseks paluge operaatoril esmalt see teenus seadistada. Seejärel lülitage WiFi-kõned menüüs Seaded uuesti sisse."</item>
+ <item msgid="3910386316304772394">"WiFi-võrgu kaudu helistamiseks ja sõnumite saatmiseks paluge operaatoril esmalt see teenus seadistada. Seejärel lülitage WiFi-kõned menüüs Seaded uuesti sisse. (Veakood: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registreeruge operaatori juures"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Avatud WiFi-võrgud on saadaval</item>
<item quantity="one">Avatud WiFi-võrk on saadaval</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Looge ühendus avatud WiFi-võrguga"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ühenduse loomine avatud WiFi-võrguga"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Ühendatud WiFi-võrguga"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"WiFi-võrguga ei õnnestunud ühendust luua"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Puudutage kõikide võrkude nägemiseks"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Ühenda"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Kõik võrgud"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Logi sisse WiFi-võrku"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Võrku sisselogimine"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 01d50efd918b..cea36c14e932 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Zerbitzu bila"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi bidezko deiak"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Wi-Fi bidez deiak egiteko eta mezuak bidaltzeko, eskatu operadoreari zerbitzu hori gaitzeko. Ondoren, aktibatu Wi-Fi bidezko deiak Ezarpenak atalean."</item>
+ <item msgid="3910386316304772394">"Wi-Fi bidez deiak egiteko eta mezuak bidaltzeko, eskatu operadoreari zerbitzu hori gaitzeko. Ondoren, aktibatu Wi-Fi bidezko deiak Ezarpenak atalean. (Errore-kodea: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Erregistratu operadorearekin"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Wi-Fi sare irekiak erabilgarri</item>
<item quantity="one">Wi-Fi sare irekia erabilgarri</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Konektatu Wi‑Fi sare irekira"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Wi‑Fi sare irekira konektatzen"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi sare irekira konektatuta"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Ezin izan da konektatu Wi‑Fi sare irekira"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Sakatu hau sare guztiak ikusteko"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Konektatu"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Sare guztiak"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Hasi saioa Wi-Fi sarean"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Hasi saioa sarean"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1138,7 +1145,7 @@
<string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Gonbidapena bidali da"</string>
<string name="wifi_p2p_invitation_to_connect_title" msgid="4958803948658533637">"Konektatzeko gonbidapena"</string>
<string name="wifi_p2p_from_message" msgid="570389174731951769">"Igorlea:"</string>
- <string name="wifi_p2p_to_message" msgid="248968974522044099">"Nori:"</string>
+ <string name="wifi_p2p_to_message" msgid="248968974522044099">"Hartzailea:"</string>
<string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"Idatzi beharrezko PINa:"</string>
<string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PINa:"</string>
<string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"Tableta Wi-Fi saretik deskonektatuko da <xliff:g id="DEVICE_NAME">%1$s</xliff:g> gailura konektatuta dagoen bitartean"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index ffa21ff3dda8..edcfbc2419e4 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -131,7 +131,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="3910386316304772394">"‏برای برقراری تماس و ارسال پیام ازطریق Wi-Fi، ابتدا از شرکت مخابراتی خود بخواهید این سرویس را تنظیم کند. سپس در «تنظیمات»۷ دوباره «تماس ازطریق Wi-Fi» را روشن کنید. (کد خطا: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"ثبت‌نام با شرکت مخابراتی شما"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">‏شبکه Wi-Fi باز در دسترس</item>
<item quantity="other">‏شبکه‌ Wi-Fi باز در دسترس</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"‏اتصال به شبکه Wi‑Fi باز"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"‏درحال اتصال به شبکه Wi‑Fi باز"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"‏به شبکه Wi‑Fi متصل شد"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"‏به شبکه Wi-Fi متصل نشد"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"برای دیدن همه شبکه‌ها ضربه بزنید"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"اتصال"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"همه شبکه‌ها"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"‏ورود به شبکه Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ورود به سیستم شبکه"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 8556103453d2..6e8346b9b773 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Etsitään signaalia"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-puhelut"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Jos haluat soittaa puheluita ja lähettää viestejä Wi-Fin kautta, pyydä ensin operaattoriasi ottamaan tämä palvelu käyttöön. Ota sitten Wi-Fi-puhelut käyttöön asetuksissa."</item>
+ <item msgid="3910386316304772394">"Jos haluat soittaa puheluita ja lähettää viestejä Wi-Fin kautta, pyydä ensin operaattoriasi ottamaan tämä palvelu käyttöön. Ota sitten Wi-Fi-puhelut käyttöön asetuksissa. (Virhekoodi: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Rekisteröidy operaattorisi asiakkaaksi."</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Avoimia Wi-Fi-verkkoja käytettävissä</item>
<item quantity="one">Avoin Wi-Fi-verkko käytettävissä</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Yhdistä avoimeen Wi‑Fi-verkkoon"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Yhdistetään avoimeen Wi‑Fi-verkkoon"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Yhdistetty Wi-Fi-verkkoon"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi-verkkoon yhdistäminen epäonnistui"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Napauta, niin näet kaikki verkot."</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Yhdistä"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Kaikki verkot"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Kirjaudu Wi-Fi-verkkoon"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Kirjaudu verkkoon"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index daa56789549f..57e5fd19db11 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Recherche des services disponibles"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Appels Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Pour effectuer des appels et envoyer des messages par Wi-Fi, demandez tout d\'abord à votre fournisseur de services de configurer ce service. Réactivez ensuite les appels Wi-Fi dans les paramètres."</item>
+ <item msgid="3910386316304772394">"Pour effectuer des appels et envoyer des messages par Wi-Fi, demandez tout d\'abord à votre fournisseur de services de configurer ce service. Réactivez ensuite les appels Wi-Fi dans les paramètres. (Code d\'erreur : <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Inscrivez-vous auprès de votre fournisseur de services"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">Réseau Wi-Fi ouvert à proximité</item>
<item quantity="other">Réseaux Wi-Fi ouverts à proximité</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Connectez-vous pour ouvrir un réseau Wi-Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connexion en cours au réseau Wi-Fi ouvert…"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Connecté au réseau Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Impossible de se connecter au réseau Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Touchez pour afficher tous les réseaux"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connexion"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Tous les réseaux"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Connectez-vous au réseau Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Connectez-vous au réseau"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 494e85bffc02..b5fd4543a5ff 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Recherche des services disponibles"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Appels Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Pour effectuer des appels et envoyer des messages via le Wi-Fi, demandez tout d\'abord à votre opérateur de configurer ce service. Réactivez ensuite les appels Wi-Fi dans les paramètres."</item>
+ <item msgid="3910386316304772394">"Pour passer des appels et envoyer des messages via le Wi-Fi, demandez d\'abord à votre opérateur de configurer ce service. Ensuite, réactivez les appels Wi-Fi dans les paramètres. (Code d\'erreur : <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Inscrivez-vous auprès de votre opérateur."</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">Réseau Wi-Fi ouvert disponible</item>
<item quantity="other">Réseaux Wi-Fi ouverts disponibles</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Se connecter pour ouvrir le réseau Wi-Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connexion pour ouvrir un réseau Wi-Fi…"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Connecté au réseau Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Impossible de se connecter au réseau Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Appuyer pour afficher tous les réseaux"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Se connecter"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Tous les réseaux"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Connectez-vous au réseau Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Se connecter au réseau"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 6af6e1e56190..b62ca2d7fc0c 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Buscando servizo"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Chamadas por wifi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Para facer chamadas e enviar mensaxes a través da wifi, primeiro pídelle ao teu operador que configure este servizo. A continuación, activa de novo as chamadas wifi en Configuración."</item>
+ <item msgid="3910386316304772394">"Para facer chamadas e enviar mensaxes a través da wifi, primeiro solicítalle ao operador que configure este servizo. Despois, activa de novo as chamadas por wifi en Configuración. (Código de erro: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Rexístrate co teu operador"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Abrir redes wifi dispoñibles</item>
<item quantity="one">Abrir rede wifi dispoñible</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Conéctate a unha rede wifi aberta"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Conectándose á rede wifi aberta"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Conectouse á rede wifi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Non se puido conectar á rede wifi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toca para ver todas as redes"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectarse"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas as redes"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Inicia sesión na rede wifi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Inicia sesión na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index e92f31b157df..6dc0e0c69ee3 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Wi-Fi પરથી કૉલ કરવા અને સંદેશા મોકલવા માટે પહેલા તમારા કૅરિઅરને આ સેવા સેટ કરવા માટે કહો. પછી સેટિંગ્સમાંથી Wi-Fi કૉલિંગ ફરીથી ચાલુ કરો. (ભૂલ કોડ: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"તમારા કેરીઅર સાથે નોંધણી કરો"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">ખુલ્લા Wi-Fi નેટવર્ક્સ ઉપલબ્ધ છે</item>
<item quantity="other">ખુલ્લા Wi-Fi નેટવર્ક્સ ઉપલબ્ધ છે</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"ખુલ્લા Wi‑Fi નેટવર્ક સાથે કનેક્ટ કરો"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ખુલ્લા Wi‑Fi નેટવર્ક સાથે કનેક્ટ કરી રહ્યાં છીએ"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi નેટવર્ક સાથે કનેક્ટ કર્યુ"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi નેટવર્ક સાથે કનેક્ટ કરી શકાયું નથી"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"બધા નેટવર્ક જોવા ટૅપ કરો"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"કનેક્ટ કરો"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"બધા નેટવર્ક"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi નેટવર્ક પર સાઇન ઇન કરો"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"નેટવર્ક પર સાઇન ઇન કરો"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index af017a37e75f..e534488e26a8 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"सेवा खोज रहा है"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"वाई-फ़ाई कॉलिंग"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से पुन: वाई-फ़ाई कॉलिंग चालू करें."</item>
+ <item msgid="3910386316304772394">"वाई-फ़ाई से कॉल करने और संदेश भेजने के लिए, सबसे पहले अपने वाहक से इस सेवा को सेट करने के लिए कहें. उसके बाद सेटिंग से वाई-फ़ाई कॉलिंग को दोबारा चालू करें. (गड़बड़ी कोड: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"अपने वाहक के साथ पंजीकृत करें"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">खुले वाई-फ़ाई नेटवर्क उपलब्‍ध</item>
<item quantity="other">खुले वाई-फ़ाई नेटवर्क उपलब्‍ध</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"खुले वाई-फ़ाई नेटवर्क से कनेक्ट करें"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"खुले वाई-फ़ाई नेटवर्क से कनेक्ट हो रहा है"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"वाई-फ़ाई नेटवर्क से कनेक्‍ट हो गया है"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"वाई-फ़ाई नेटवर्क से कनेक्‍ट नहीं हो सका"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"सभी नेटवर्क देखने के लिए यहां पर टैप करें"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"कनेक्ट करें"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"सभी नेटवर्क"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"वाई-फ़ाई नेटवर्क में प्रवेश करें"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"नेटवर्क में प्रवेश करें"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index ead2d8c815af..ae5bdead36d6 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -132,7 +132,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Pretraživanje usluge"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi pozivi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Da biste telefonirali i slali pozive putem Wi-Fi-ja, morate tražiti od mobilnog operatera da vam postavi tu uslugu. Zatim ponovo uključite Wi-Fi pozive u Postavkama."</item>
+ <item msgid="3910386316304772394">"Da biste telefonirali i slali poruke putem Wi-Fi-ja, od mobilnog operatera morate tražiti da postavi tu uslugu. Zatim ponovo uključite Wi-Fi pozive u postavkama. (Kôd pogreške: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registrirajte se kod mobilnog operatera"</item>
@@ -1128,6 +1128,13 @@
<item quantity="few">Dostupne su otvorene Wi-Fi mreže</item>
<item quantity="other">Dostupne su otvorene Wi-Fi mreže</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Povezivanje s otvorenom Wi‑Fi mrežom"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Povezivanje s otvorenom Wi‑Fi mrežom"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Povezano s Wi-Fi mrežom"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nije uspjelo povezivanje s Wi-Fi mrežom"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Dodirnite za prikaz svih mreža"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Poveži"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Sve mreže"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijava na Wi-Fi mrežu"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijava na mrežu"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 8eb2b1910b90..cc71deff61d4 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -90,7 +90,7 @@
<string name="serviceNotProvisioned" msgid="8614830180508686666">"A szolgáltatás nincs biztosítva."</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"Nem tudja módosítani a hívó fél azonosítója beállítást."</string>
<string name="RestrictedOnDataTitle" msgid="1322504692764166532">"Adatszolgáltatás letiltva"</string>
- <string name="RestrictedOnEmergencyTitle" msgid="3646729271176394091">"Nincs vészhívás"</string>
+ <string name="RestrictedOnEmergencyTitle" msgid="3646729271176394091">"Nincs segélyhívás"</string>
<string name="RestrictedOnNormalTitle" msgid="3179574012752700984">"Hangszolgáltatás letiltva"</string>
<string name="RestrictedOnAllVoiceTitle" msgid="158800171499150681">"Hang- és segélyszolgáltatás letiltva"</string>
<string name="RestrictedStateContent" msgid="4278821484643362350">"Az Ön tartózkodási helyén ideiglenesen nem áll rendelkezésre a mobilhálózaton"</string>
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Szolgáltatás keresése"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-hívás"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Ha Wi-Fi-n szeretne telefonálni és üzenetet küldeni, kérje meg szolgáltatóját, hogy állítsa be ezt a szolgáltatást. Ezután a Beállítások menüben kapcsolhatja be újra a Wi-Fi-hívást."</item>
+ <item msgid="3910386316304772394">"Ha Wi-Fi-hálózaton szeretne telefonálni és üzenetet küldeni, kérje meg szolgáltatóját, hogy állítsa be ezt a szolgáltatást. Ezután kapcsolja be újra a Wi-Fi-hívást a Beállításokban. (Hibakód: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Regisztráljon a szolgáltatójánál"</item>
@@ -223,7 +223,7 @@
<string name="global_actions" product="default" msgid="2406416831541615258">"Telefonbeállítások"</string>
<string name="global_action_lock" msgid="2844945191792119712">"Képernyő lezárása"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Kikapcsolás"</string>
- <string name="global_action_emergency" msgid="7112311161137421166">"Vészhívás"</string>
+ <string name="global_action_emergency" msgid="7112311161137421166">"Segélyhívás"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Programhiba bejelentése"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Hibajelentés készítése"</string>
<string name="bugreport_message" msgid="398447048750350456">"Ezzel információt fog gyűjteni az eszköz jelenlegi állapotáról, amelyet a rendszer e-mailben fog elküldeni. Kérjük, legyen türelemmel, amíg a hibajelentés elkészül, és küldhető állapotba kerül."</string>
@@ -714,7 +714,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"A feloldáshoz vagy segélyhívás kezdeményezéséhez nyomja meg a Menü gombot."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"A feloldáshoz nyomja meg a Menü gombot."</string>
<string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Rajzolja le a mintát a feloldáshoz"</string>
- <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Vészhívás"</string>
+ <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Segélyhívás"</string>
<string name="lockscreen_return_to_call" msgid="5244259785500040021">"Hívás folytatása"</string>
<string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Helyes!"</string>
<string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Próbálja újra"</string>
@@ -1106,6 +1106,13 @@
<item quantity="other">Nyílt Wi-Fi hálózatok érhetők el</item>
<item quantity="one">Nyílt Wi-Fi hálózat érhető el</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Nyílt Wi-Fi-hálózathoz kapcsolódhat"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Kapcsolódás nyílt Wi‑Fi-hálózathoz…"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Sikeres kapcsolódás a Wi-Fi-hálózathoz"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nem sikerült kapcsolódni a Wi‑Fi-hálózathoz"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Koppintással megjelenítheti az összes hálózatot"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Kapcsolódás"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Összes hálózat"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Bejelentkezés Wi-Fi hálózatba"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Bejelentkezés a hálózatba"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 1717f5a4b1c3..0f67744f0109 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Wi-Fi-ի միջոցով զանգեր կատարելու և հաղորդագրություններ ուղարկելու համար նախ դիմեք ձեր օպերատորին՝ այս ծառայությունը կարգավորելու համար: Այնուհետև նորից միացրեք «Զանգեր Wi-Fi-ի միջոցով» ընտրանքը Կարգավորումներից: (Սխալի կոդ՝ <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Գրանցվեք օպերատորի մոտ"</item>
@@ -398,7 +398,7 @@
<string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռախոսում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"փոխել ձեր աուդիո կարգավորումները"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Թույլ է տալիս հավելվածին փոփոխել ձայնանյութի գլոբալ կարգավորումները, ինչպես օրինակ` ձայնը և թե որ խոսափողն է օգտագործված արտածման համար:"</string>
- <string name="permlab_recordAudio" msgid="3876049771427466323">"ձայնագրել ձայնանյութ"</string>
+ <string name="permlab_recordAudio" msgid="3876049771427466323">"ձայնագրել աուդիո ֆայլ"</string>
<string name="permdesc_recordAudio" msgid="4245930455135321433">"Այս հավելվածը ցանկացած պահի կարող է ձայնագրել խոսափողի օգնությամբ:"</string>
<string name="permlab_sim_communication" msgid="2935852302216852065">"ուղարկել հրամաններ SIM քարտին"</string>
<string name="permdesc_sim_communication" msgid="5725159654279639498">"Թույլ է տալիս հավելվածին հրամաններ ուղարկել SIM-ին: Սա շատ վտանգավոր է:"</string>
@@ -1106,6 +1106,13 @@
<item quantity="one">Հասանելի են չպաշտպանված Wi-Fi ցանցեր</item>
<item quantity="other">Հասանելի են չպաշտպանված Wi-Fi ցանցեր</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Միացեք բաց Wi‑Fi ցանցին"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Միացում բաց Wi‑Fi ցանցին"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Միացել է Wi‑Fi ցանցին"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Չհաջողվեց միանալ Wi‑Fi ցանցին"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Հպեք՝ բոլոր ցանցերը տեսնելու համար"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Միանալ"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Բոլոր ցանցերը"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Մուտք գործեք Wi-Fi ցանց"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Մուտք գործեք ցանց"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1420,7 +1427,7 @@
<string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Համակցված բարձրախոսներ"</string>
<string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
<string name="default_audio_route_category_name" msgid="3722811174003886946">"Համակարգ"</string>
- <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ի ձայնանյութ"</string>
+ <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ի աուդիո ֆայլ"</string>
<string name="wireless_display_route_description" msgid="9070346425023979651">"Անլար էկրան"</string>
<string name="media_route_button_content_description" msgid="591703006349356016">"Հեռարձակում"</string>
<string name="media_route_chooser_title" msgid="1751618554539087622">"Միանալ սարքին"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 84fd7df09575..99f9f098ad73 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Mencari layanan"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Panggilan Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Untuk melakukan panggilan telepon dan mengirim pesan melalui Wi-Fi, terlebih dahulu minta operator untuk menyiapkan layanan ini. Lalu, aktifkan lagi panggilan telepon Wi-Fi dari Setelan."</item>
+ <item msgid="3910386316304772394">"Untuk menelepon dan mengirim pesan melalui Wi-Fi, tanyalah ke operator Anda terlebih dahulu untuk menyiapkan layanan ini. Kemudian, aktifkan kembali panggilan Wi-Fi dari Setelan. (Kode error: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Harap daftarkan ke operator"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Jaringan Wi-Fi terbuka tersedia</item>
<item quantity="one">Jaringan Wi-Fi terbuka tersedia</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Hubungkan ke jaringan Wi-Fi terbuka"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Menghubungkan ke jaringan Wi-Fi terbuka"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Terhubung ke jaringan Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Tidak dapat menghubungkan ke jaringan Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap untuk melihat semua jaringan"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Hubungkan"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Semua Jaringan"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Masuk ke jaringan Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Masuk ke jaringan"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 7487be7dedc3..32d5c10e84d4 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Leitar að þjónustu"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi símtöl"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Til að hringja og senda skilaboð yfir Wi-Fi þarftu fyrst að biðja símafyrirtækið þitt um að setja þá þjónustu upp. Kveiktu síðan á Wi-Fi símtölum í stillingunum."</item>
+ <item msgid="3910386316304772394">"Til að hringja og senda skilaboð yfir Wi-Fi þarftu fyrst að biðja símafyrirtækið þitt um að setja þá þjónustu upp. Kveiktu síðan á Wi-Fi símtölum í stillingunum. (Villukóði: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Skráðu þig hjá símafyrirtækinu"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">Opin Wi-Fi net í boði</item>
<item quantity="other">Opin Wi-Fi net í boði</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Tengjast opnu Wi-Fi neti"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Tengist opnu Wi‑Fi neti"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Tengt við Wi‑Fi net"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Ekki hægt að tengjast Wi-Fi neti"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Ýttu til að sjá öll netkerfi"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Tengjast"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Öll netkerfi"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Skrá inn á Wi-Fi net"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Skrá inn á net"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 094e4a0de73c..ccaffaeeb1e8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Ricerca servizio"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Chiamate Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Per effettuare chiamate e inviare messaggi tramite Wi-Fi, è necessario prima chiedere all\'operatore telefonico di attivare il servizio. Successivamente, riattiva le chiamate Wi-Fi dalle Impostazioni."</item>
+ <item msgid="3910386316304772394">"Per effettuare chiamate e inviare messaggi tramite Wi-Fi, chiedi prima al tuo operatore di impostare questo servizio. Dopodiché, attiva di nuovo la funzione Chiamate Wi-Fi nelle impostazioni. (Codice di errore: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registrati con il tuo operatore"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Apri reti Wi-Fi disponibili</item>
<item quantity="one">Apri rete Wi-Fi disponibile</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Stabilisci la connessione per aprire la rete Wi‑Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Connessione per aprire la rete Wi‑Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Connessione alla rete Wi-Fi stabilita"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Impossibile connettersi alla rete Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tocca per vedere tutte le reti"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connetti"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Tutte le reti"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Accedi a rete Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Accedi alla rete"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1369,7 +1376,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Altre opzioni"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="3570990907910199483">"Archivio condiviso interno"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Memoria condivisa interna"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"Scheda SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Scheda SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Unità USB"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index bbcb26c1f086..d765403aa704 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -133,7 +133,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="3910386316304772394">"‏כדי להתקשר ולשלוח הודעות ברשת Wi-Fi, תחילה יש לבקש מהספק להגדיר את השירות. לאחר מכן, יש להפעיל שוב שיחות Wi-Fi ב\'הגדרות\'. (קוד שגיאה: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"הירשם אצל הספק"</item>
@@ -1150,6 +1150,13 @@
<item quantity="other">‏יש רשתות Wi-Fi פתוחות וזמינות</item>
<item quantity="one">‏יש רשת Wi-Fi פתוחה וזמינה</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"‏התחברות לרשת Wi‑Fi פתוחה"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"‏מתחבר לרשת Wi‑Fi פתוחה"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"‏מחובר לרשת Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"‏לא ניתן היה להתחבר לרשת Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"יש להקיש כדי לראות את כל הרשתות"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"התחבר"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"כל הרשתות"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"‏היכנס לרשת Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"היכנס לרשת"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 5cda8273d26d..e223eec83af3 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -131,7 +131,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サービスを申し込んだ上で、設定画面でWi-Fi発信を再度ONにしてください。"</item>
+ <item msgid="3910386316304772394">"Wi-Fi 経由で音声通話の発信やメッセージの送信を行うには、携帯通信会社に Wi-Fi サービスを申し込んだ上で、設定画面で Wi-Fi 発信を再度 ON にしてください(エラーコード: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"携帯通信会社に登録してください"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">複数のWi-Fiオープンネットワークが利用できます</item>
<item quantity="one">Wi-Fiオープンネットワークが利用できます</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Wi-Fi オープン ネットワークに接続"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Wi-Fi オープン ネットワークに接続しています"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi-Fi ネットワークに接続しました"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi ネットワークに接続できませんでした"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"すべてのネットワークを表示するにはタップします"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"接続"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"すべてのネットワーク"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fiネットワークにログイン"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ネットワークにログインしてください"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 2e1435e8466d..5b8a8bcd3ae5 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Wi-Fi-ს მეშვეობით ზარების განსახორციელებლად ან შეტყობინებების გასაგზავნად, პირველ რიგში, ამ სერვისის გააქტიურება თქვენს ოპერატორს უნდა თხოვოთ. შემდეგ კი ხელახლა ჩართეთ Wi-Fi დარეკვა პარამეტრებიდან.. (შეცდომის კოდი: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"დაარეგისტრირეთ თქვენი ოპერატორი"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">ხელმისაწვდომია ღია Wi-Fi ქსელები</item>
<item quantity="one">ხელმისაწვდომია ღია Wi-Fi ქსელი</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"დაუკავშირდით ღია Wi‑Fi ქსელს"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"მიმდინარეობს ღია Wi‑Fi ქსელთან დაკავშირება"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi ქსელთან დაკავშირება წარმატებით მოხერხდა"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi ქსელთან დაკავშირება ვერ მოხერხდა"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"შეეხეთ ყველა ქსელის სანახავად"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"დაკავშირება"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ყველა ქსელი"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi ქსელთან დაკავშირება"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ქსელში შესვლა"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 85eac4351af9..bedcc4372005 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Wi-Fi арқылы қоңырау шалу немесе хабарлар жіберу үшін, алдымен операторыңыздан құрылғыны реттеуді сұраңыз. Содан кейін \"Параметрлер\" бөлімінен Wi-Fi қоңырауларын қайта қосыңыз. (Қате коды: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Жабдықтаушыңыз арқылы тіркелу"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Ашық Wi-Fi желілері қол жетімді</item>
<item quantity="one">Ашық Wi-Fi желісі қол жетімді</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Ашық Wi‑Fi желісіне қосылу"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ашық Wi‑Fi желісіне қосылуда"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi желісіне қосылды"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi желісіне қосылмады"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Барлық желілерді көру үшін түртіңіз"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Қосылу"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Барлық желілер"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi желісіне кіру"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Желіге кіру"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 20868e6e450c..270e46727e61 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -131,7 +131,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="3910386316304772394">"ដើម្បីធ្វើការហៅ និងផ្ញើសារតាម Wi-Fi អ្នកត្រូវស្នើឲ្យក្រុមហ៊ុនបម្រើសេវាទូរសព្ទរបស់អ្នកដំឡើងសេវាកម្មនេះជាមុនសិន។ បន្ទាប់មកបើកការហៅតាម Wi-Fi ម្តងទៀតនៅក្នុងការកំណត់។ (លេខកូដបញ្ហា៖ <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"ចុះឈ្មោះជាមួយក្រុមហ៊ុនរបស់អ្នក"</item>
@@ -1108,6 +1108,13 @@
<item quantity="other">បើកបណ្តាញ Wi-Fi ដែលមាន</item>
<item quantity="one">បើកបណ្តាញ Wi-Fi ដែលមាន</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"ភ្ជាប់ទៅបណ្តាញ Wi‑Fi ចំហ"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"កំពុងភ្ជាប់ទៅបណ្តាញ Wi‑Fi ចំហ"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"បានភ្ជាប់ទៅបណ្តាញ Wi‑Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"មិនអាចភ្ជាប់ទៅបណ្តាញ Wi‑Fi បានទេ"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ចុចដើម្បីមើលបណ្តាញទាំងអស់"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"ភ្ជាប់"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"បណ្តាញទាំងអស់"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ចូល​បណ្ដាញ​វ៉ាយហ្វាយ"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ចូលទៅបណ្តាញ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 7dd5db7e3fdc..7783692e567f 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"ಸೇವೆ ಹುಡುಕಲಾಗುತ್ತಿದೆ"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"ವೈ-ಫೈ ಕರೆ ಮಾಡುವಿಕೆ"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"ವೈ-ಫೈ ಬಳಸಿಕೊಂಡು ಕರೆ ಮಾಡಲು ಮತ್ತು ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು, ಮೊದಲು ಈ ಸಾಧನವನ್ನು ಹೊಂದಿಸಲು ನಿಮ್ಮ ವಾಹಕವನ್ನು ಕೇಳಿ. ತದನಂತರ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಮತ್ತೆ ವೈ-ಫೈ ಆನ್‌ ಮಾಡಿ."</item>
+ <item msgid="3910386316304772394">"ವೈ-ಫೈ ಮೂಲಕ ಕರೆಗಳನ್ನು ಮಾಡಲು ಮತ್ತು ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು, ಈ ಸೇವೆಯನ್ನು ಹೊಂದಿಸಲು ಮೊದಲು ನಿಮ್ಮ ವಾಹಕವನ್ನು ಕೇಳಿ. ಆ ನಂತರ ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಂದ ವೈ-ಫೈ ಕರೆಮಾಡುವಿಕೆಯನ್ನು ಅನ್ನು ಆನ್ ಮಾಡಿ. (ದೋಷ ಕೋಡ್: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"ನಿಮ್ಮ ವಾಹಕದಲ್ಲಿ ನೋಂದಾಯಿಸಿಕೊಳ್ಳಿ"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿವೆ</item>
<item quantity="other">ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿವೆ</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಿ"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗುತ್ತಿದೆ"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ಎಲ್ಲಾ ನೆಟ್‌ವರ್ಕ್‌ಗಳನ್ನು ನೋಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"ಸಂಪರ್ಕಿಸಿ"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ಎಲ್ಲಾ ನೆಟ್‌ವರ್ಕ್‌ಗಳು"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ವೈ-ಫೈ ನೆಟ್‍ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index a2b9f6ef1c5d..739f128c77a8 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Wi-Fi를 사용하여 전화를 걸고 메시지를 보내려면 먼저 이동통신사에 문의하여 서비스를 설정해야 합니다. 그런 다음 설정에서 Wi-Fi 통화를 사용 설정하시기 바랍니다. (오류 코드: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"이동통신사에 등록"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">개방형 Wi-Fi 네트워크 사용 가능</item>
<item quantity="one">개방형 Wi-Fi 네트워크 사용 가능</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"공개 Wi‑Fi 네트워크에 연결"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"공개 Wi‑Fi 네트워크에 연결 중"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi 네트워크에 연결됨"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi 네트워크에 연결할 수 없음"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"모든 네트워크를 보려면 탭하세요."</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"연결"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"모든 네트워크"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi 네트워크에 로그인"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"네트워크에 로그인"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 89c1d54b8bfd..569bf2ce87ab 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Wi-Fi аркылуу чалууларды аткарып жана билдирүүлөрдү жөнөтүү үчүн адегенде байланыш операторуңуздан бул кызматты орнотушун сураныңыз. Андан соң, Жөндөөлөрдөн Wi-Fi чалууну кайра күйгүзүңүз. (Ката коду: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Операторуңузга катталыңыз"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Ачык Wi-Fi тармагы жеткиликтүү</item>
<item quantity="one">Ачык Wi-Fi тармагы жеткиликтүү</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Ачык Wi‑Fi тармагына туташуу"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ачык Wi‑Fi тармагына туташууда"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Ачык Wi‑Fi тармагына туташты"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi-Fi тармагына туташпай калды"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Бардык тармактарды көрүү үчүн басыңыз"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Туташуу"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Бардык тармактар"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi түйүнүнө кирүү"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Тармакка кирүү"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 8d2385fc5374..6c8603e8898f 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -131,7 +131,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="3910386316304772394">"ເພື່ອໂທ ແລະ ສົ່ງຂໍ້ຄວາມຜ່ານ Wi-Fi, ໃຫ້ແຈ້ງໃຫ້ຜູ້ໃຫ້ບໍລິການຂອງທ່ານຕັ້ງບໍລິການນີ້. ຈາກນັ້ນເປີດໃຊ້ການໂທ Wi-Fi ອີກຄັ້ງຈາກການຕັ້ງຄ່າ. (ລະຫັດຂໍ້ຜິດພາດ: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"ລົງ​ທະ​ບຽນ​ກັບ​ຜູ້​ໃຫ້​ບໍ​ລິ​ການ​ເຄືອ​ຂ່າຍ​ຂອງ​ທ່ານ"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">ເປີດເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
<item quantity="one">ເປີດເຄືອຂ່າຍ Wi-Fi ທີ່ມີໃຫ້</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ແບບເປີດ"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ກຳລັງເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ແລ້ວ"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ບໍ່ສາມາດເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍ Wi‑Fi ໄດ້"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ແຕະເພື່ອເບິ່ງເຄືອຂ່າຍທັງໝົດ"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"ເຊື່ອມ​ຕໍ່"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ເຄືອຂ່າຍທັງໝົດ"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ລົງຊື່ເຂົ້າເຄືອຂ່າຍ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 54f722d01e2f..2a82845accab 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -133,7 +133,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Ieškoma paslaugos"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"„Wi-Fi“ skambinimas"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Jei norite skambinti ir siųsti pranešimus „Wi-Fi“ ryšiu, pirmiausia paprašykite operatoriaus nustatyti šią paslaugą. Tada vėl įjunkite skambinimą „Wi-Fi“ ryšiu „Nustatymų“ skiltyje."</item>
+ <item msgid="3910386316304772394">"Jei norite skambinti ir siųsti pranešimus naudodami „Wi-Fi“, pirmiausia paprašykite operatoriaus nustatyti šią paslaugą. Tada vėl įjunkite „Wi-Fi“ skambinimą skiltyje „Nustatymai“. (Klaidos kodas: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Užregistruokite pas operatorių"</item>
@@ -1150,6 +1150,13 @@
<item quantity="many">Pasiekiami atvirieji „Wi-Fi“ tinklai</item>
<item quantity="other">Pasiekiami atvirieji „Wi-Fi“ tinklai</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Prisijunkite prie atviro „Wi‑Fi“ tinklo"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Prisijungiama prie atviro „Wi‑Fi“ tinklo"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Prisijungta prie „Wi-Fi“ tinklo"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nepavyko prisijungti prie „Wi‑Fi“ tinklo"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Palieskite, jei norite matyti visus tinklus"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Prisijungti"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Visi tinklai"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prisijungti prie „Wi-Fi“ tinklo"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prisijungti prie tinklo"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 5461c1a6d603..cfe036924a3a 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -132,7 +132,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Pakalpojuma meklēšana"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi zvani"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Lai veiktu zvanus un sūtītu īsziņas Wi-Fi tīklā, vispirms lūdziet mobilo sakaru operatoru iestatīt šo pakalpojumu. Pēc tam iestatījumos vēlreiz ieslēdziet Wi-Fi zvanus."</item>
+ <item msgid="3910386316304772394">"Lai veiktu zvanus un sūtītu īsziņas Wi-Fi tīklā, vispirms lūdziet mobilo sakaru operatoram iestatīt šo pakalpojumu. Pēc tam iestatījumos vēlreiz ieslēdziet Wi-Fi zvanus. (Kļūdas kods: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Reģistrēt to pie sava mobilo sakaru operatora"</item>
@@ -1128,6 +1128,13 @@
<item quantity="one">Ir pieejami atvērti Wi-Fi tīkli</item>
<item quantity="other">Ir pieejami atvērti Wi-Fi tīkli</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Savienojuma izveide ar atvērtu Wi-Fi tīklu"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Notiek savienojuma izveide ar atvērtu Wi-Fi tīklu"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Ir izveidots savienojums ar Wi-Fi tīklu"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nevarēja izveidot savienojumu ar Wi‑Fi tīklu"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Pieskarieties, lai skatītu visus tīklus"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Izveidot savienojumu"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Visi tīkli"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Pierakstieties Wi-Fi tīklā"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Pierakstīšanās tīklā"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-mcc302-mnc370-af/strings.xml b/core/res/res/values-mcc302-mnc370-af/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-af/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-am/strings.xml b/core/res/res/values-mcc302-mnc370-am/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-am/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ar/strings.xml b/core/res/res/values-mcc302-mnc370-ar/strings.xml
new file mode 100644
index 000000000000..f1c8176cb706
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ar/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"‏%s مع Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-az/strings.xml b/core/res/res/values-mcc302-mnc370-az/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-az/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-b+sr+Latn/strings.xml b/core/res/res/values-mcc302-mnc370-b+sr+Latn/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-b+sr+Latn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-be/strings.xml b/core/res/res/values-mcc302-mnc370-be/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-be/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-bg/strings.xml b/core/res/res/values-mcc302-mnc370-bg/strings.xml
new file mode 100644
index 000000000000..b3a9589b1eac
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-bg/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi от %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-bn/strings.xml b/core/res/res/values-mcc302-mnc370-bn/strings.xml
new file mode 100644
index 000000000000..efd9b4b4f8ca
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-bn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s ওয়াই-ফাই"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-bs/strings.xml b/core/res/res/values-mcc302-mnc370-bs/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-bs/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ca/strings.xml b/core/res/res/values-mcc302-mnc370-ca/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ca/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-cs/strings.xml b/core/res/res/values-mcc302-mnc370-cs/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-cs/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-da/strings.xml b/core/res/res/values-mcc302-mnc370-da/strings.xml
new file mode 100644
index 000000000000..709530cc56ae
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-da/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi fra %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-de/strings.xml b/core/res/res/values-mcc302-mnc370-de/strings.xml
new file mode 100644
index 000000000000..6aa76438581a
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-de/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"WLAN: %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-el/strings.xml b/core/res/res/values-mcc302-mnc370-el/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-el/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-en-rAU/strings.xml b/core/res/res/values-mcc302-mnc370-en-rAU/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-en-rAU/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-en-rGB/strings.xml b/core/res/res/values-mcc302-mnc370-en-rGB/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-en-rGB/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-en-rIN/strings.xml b/core/res/res/values-mcc302-mnc370-en-rIN/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-en-rIN/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-es-rUS/strings.xml b/core/res/res/values-mcc302-mnc370-es-rUS/strings.xml
new file mode 100644
index 000000000000..5ba6413304a6
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-es-rUS/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi de %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-es/strings.xml b/core/res/res/values-mcc302-mnc370-es/strings.xml
new file mode 100644
index 000000000000..5ba6413304a6
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-es/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi de %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-et/strings.xml b/core/res/res/values-mcc302-mnc370-et/strings.xml
new file mode 100644
index 000000000000..648544d81555
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-et/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s WiFi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-eu/strings.xml b/core/res/res/values-mcc302-mnc370-eu/strings.xml
new file mode 100644
index 000000000000..960e1e563b07
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-eu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi sarea"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-fa/strings.xml b/core/res/res/values-mcc302-mnc370-fa/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-fa/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-fi/strings.xml b/core/res/res/values-mcc302-mnc370-fi/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-fi/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-fr-rCA/strings.xml b/core/res/res/values-mcc302-mnc370-fr-rCA/strings.xml
new file mode 100644
index 000000000000..5ba6413304a6
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-fr-rCA/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi de %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-fr/strings.xml b/core/res/res/values-mcc302-mnc370-fr/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-fr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-gl/strings.xml b/core/res/res/values-mcc302-mnc370-gl/strings.xml
new file mode 100644
index 000000000000..b64447160530
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-gl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wifi de %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-gu/strings.xml b/core/res/res/values-mcc302-mnc370-gu/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-gu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-hi/strings.xml b/core/res/res/values-mcc302-mnc370-hi/strings.xml
new file mode 100644
index 000000000000..3521dd408d6e
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-hi/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s वाई-फ़ाई"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-hr/strings.xml b/core/res/res/values-mcc302-mnc370-hr/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-hr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-hu/strings.xml b/core/res/res/values-mcc302-mnc370-hu/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-hu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-hy/strings.xml b/core/res/res/values-mcc302-mnc370-hy/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-hy/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-in/strings.xml b/core/res/res/values-mcc302-mnc370-in/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-in/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-is/strings.xml b/core/res/res/values-mcc302-mnc370-is/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-is/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-it/strings.xml b/core/res/res/values-mcc302-mnc370-it/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-it/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-iw/strings.xml b/core/res/res/values-mcc302-mnc370-iw/strings.xml
new file mode 100644
index 000000000000..90b73ad4518b
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-iw/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"‎%s‎"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ja/strings.xml b/core/res/res/values-mcc302-mnc370-ja/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ja/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ka/strings.xml b/core/res/res/values-mcc302-mnc370-ka/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ka/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-kk/strings.xml b/core/res/res/values-mcc302-mnc370-kk/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-kk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-km/strings.xml b/core/res/res/values-mcc302-mnc370-km/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-km/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-kn/strings.xml b/core/res/res/values-mcc302-mnc370-kn/strings.xml
new file mode 100644
index 000000000000..636eb01d3eb0
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-kn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s ವೈ-ಫೈ"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ko/strings.xml b/core/res/res/values-mcc302-mnc370-ko/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ko/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ky/strings.xml b/core/res/res/values-mcc302-mnc370-ky/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ky/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-lo/strings.xml b/core/res/res/values-mcc302-mnc370-lo/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-lo/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-lt/strings.xml b/core/res/res/values-mcc302-mnc370-lt/strings.xml
new file mode 100644
index 000000000000..95746fb21691
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-lt/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"„%s“ „Wi-Fi“"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-lv/strings.xml b/core/res/res/values-mcc302-mnc370-lv/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-lv/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-mk/strings.xml b/core/res/res/values-mcc302-mnc370-mk/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-mk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ml/strings.xml b/core/res/res/values-mcc302-mnc370-ml/strings.xml
new file mode 100644
index 000000000000..810b72ccea3a
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ml/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s വൈഫൈ"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-mn/strings.xml b/core/res/res/values-mcc302-mnc370-mn/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-mn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-mr/strings.xml b/core/res/res/values-mcc302-mnc370-mr/strings.xml
new file mode 100644
index 000000000000..4b033335bb48
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-mr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s वाय-फाय"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ms/strings.xml b/core/res/res/values-mcc302-mnc370-ms/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ms/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-my/strings.xml b/core/res/res/values-mcc302-mnc370-my/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-my/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-nb/strings.xml b/core/res/res/values-mcc302-mnc370-nb/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-nb/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ne/strings.xml b/core/res/res/values-mcc302-mnc370-ne/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ne/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-nl/strings.xml b/core/res/res/values-mcc302-mnc370-nl/strings.xml
new file mode 100644
index 000000000000..036633506e93
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-nl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wifi via %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-pa/strings.xml b/core/res/res/values-mcc302-mnc370-pa/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-pa/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-pl/strings.xml b/core/res/res/values-mcc302-mnc370-pl/strings.xml
new file mode 100644
index 000000000000..f359c0300628
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-pl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi – %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-pt-rBR/strings.xml b/core/res/res/values-mcc302-mnc370-pt-rBR/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-pt-rBR/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-pt-rPT/strings.xml b/core/res/res/values-mcc302-mnc370-pt-rPT/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-pt-rPT/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-pt/strings.xml b/core/res/res/values-mcc302-mnc370-pt/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-pt/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ro/strings.xml b/core/res/res/values-mcc302-mnc370-ro/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ro/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ru/strings.xml b/core/res/res/values-mcc302-mnc370-ru/strings.xml
new file mode 100644
index 000000000000..5fdf802c9883
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ru/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Сеть Wi-Fi \"%s\""</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-si/strings.xml b/core/res/res/values-mcc302-mnc370-si/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-si/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-sk/strings.xml b/core/res/res/values-mcc302-mnc370-sk/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-sk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-sl/strings.xml b/core/res/res/values-mcc302-mnc370-sl/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-sl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-sq/strings.xml b/core/res/res/values-mcc302-mnc370-sq/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-sq/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-sr/strings.xml b/core/res/res/values-mcc302-mnc370-sr/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-sr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-sv/strings.xml b/core/res/res/values-mcc302-mnc370-sv/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-sv/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-sw/strings.xml b/core/res/res/values-mcc302-mnc370-sw/strings.xml
new file mode 100644
index 000000000000..8c1c88798030
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-sw/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi ya %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ta/strings.xml b/core/res/res/values-mcc302-mnc370-ta/strings.xml
new file mode 100644
index 000000000000..58075938c1da
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ta/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s வைஃபை"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-te/strings.xml b/core/res/res/values-mcc302-mnc370-te/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-te/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-th/strings.xml b/core/res/res/values-mcc302-mnc370-th/strings.xml
new file mode 100644
index 000000000000..fa5ff47fb62f
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-th/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi ของ %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-tl/strings.xml b/core/res/res/values-mcc302-mnc370-tl/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-tl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-tr/strings.xml b/core/res/res/values-mcc302-mnc370-tr/strings.xml
new file mode 100644
index 000000000000..2f9ff047c700
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-tr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s kablosuz"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-uk/strings.xml b/core/res/res/values-mcc302-mnc370-uk/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-uk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-ur/strings.xml b/core/res/res/values-mcc302-mnc370-ur/strings.xml
new file mode 100644
index 000000000000..81d28880fd84
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-ur/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"‎%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-uz/strings.xml b/core/res/res/values-mcc302-mnc370-uz/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-uz/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-vi/strings.xml b/core/res/res/values-mcc302-mnc370-vi/strings.xml
new file mode 100644
index 000000000000..74d4f17ce643
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-vi/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-zh-rCN/strings.xml b/core/res/res/values-mcc302-mnc370-zh-rCN/strings.xml
new file mode 100644
index 000000000000..a89f6a288197
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-zh-rCN/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s WLAN"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-zh-rHK/strings.xml b/core/res/res/values-mcc302-mnc370-zh-rHK/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-zh-rHK/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-zh-rTW/strings.xml b/core/res/res/values-mcc302-mnc370-zh-rTW/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-zh-rTW/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370-zu/strings.xml b/core/res/res/values-mcc302-mnc370-zu/strings.xml
new file mode 100644
index 000000000000..b93949e190c7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370-zu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="5022384999749536798">"%s"</item>
+ <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc370/strings.xml b/core/res/res/values-mcc302-mnc370/strings.xml
new file mode 100644
index 000000000000..f5b8496f9a0b
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc370/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Template for showing mobile network operator name while WFC is active -->
+ <string-array name="wfcSpnFormats">
+ <item>%s</item>
+ <item>%s Wi-Fi</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-af/strings.xml b/core/res/res/values-mcc302-mnc720-af/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-af/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-am/strings.xml b/core/res/res/values-mcc302-mnc720-am/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-am/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ar/strings.xml b/core/res/res/values-mcc302-mnc720-ar/strings.xml
new file mode 100644
index 000000000000..869678fdbf4a
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ar/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"‏%s مع Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-az/strings.xml b/core/res/res/values-mcc302-mnc720-az/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-az/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-b+sr+Latn/strings.xml b/core/res/res/values-mcc302-mnc720-b+sr+Latn/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-b+sr+Latn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-be/strings.xml b/core/res/res/values-mcc302-mnc720-be/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-be/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-bg/strings.xml b/core/res/res/values-mcc302-mnc720-bg/strings.xml
new file mode 100644
index 000000000000..890f19b4dd90
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-bg/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi от %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-bn/strings.xml b/core/res/res/values-mcc302-mnc720-bn/strings.xml
new file mode 100644
index 000000000000..543ec7aeed8f
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-bn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s ওয়াই-ফাই"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-bs/strings.xml b/core/res/res/values-mcc302-mnc720-bs/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-bs/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ca/strings.xml b/core/res/res/values-mcc302-mnc720-ca/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ca/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-cs/strings.xml b/core/res/res/values-mcc302-mnc720-cs/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-cs/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-da/strings.xml b/core/res/res/values-mcc302-mnc720-da/strings.xml
new file mode 100644
index 000000000000..483dee583459
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-da/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi fra %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-de/strings.xml b/core/res/res/values-mcc302-mnc720-de/strings.xml
new file mode 100644
index 000000000000..825fa0087cd8
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-de/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"WLAN: %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-el/strings.xml b/core/res/res/values-mcc302-mnc720-el/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-el/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-en-rAU/strings.xml b/core/res/res/values-mcc302-mnc720-en-rAU/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-en-rAU/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-en-rGB/strings.xml b/core/res/res/values-mcc302-mnc720-en-rGB/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-en-rGB/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-en-rIN/strings.xml b/core/res/res/values-mcc302-mnc720-en-rIN/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-en-rIN/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-es-rUS/strings.xml b/core/res/res/values-mcc302-mnc720-es-rUS/strings.xml
new file mode 100644
index 000000000000..c8c4c5eaeace
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-es-rUS/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi de %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-es/strings.xml b/core/res/res/values-mcc302-mnc720-es/strings.xml
new file mode 100644
index 000000000000..c8c4c5eaeace
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-es/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi de %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-et/strings.xml b/core/res/res/values-mcc302-mnc720-et/strings.xml
new file mode 100644
index 000000000000..3e5a7efaf7d5
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-et/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s WiFi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-eu/strings.xml b/core/res/res/values-mcc302-mnc720-eu/strings.xml
new file mode 100644
index 000000000000..802df65c5348
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-eu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi sarea"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-fa/strings.xml b/core/res/res/values-mcc302-mnc720-fa/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-fa/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-fi/strings.xml b/core/res/res/values-mcc302-mnc720-fi/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-fi/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-fr-rCA/strings.xml b/core/res/res/values-mcc302-mnc720-fr-rCA/strings.xml
new file mode 100644
index 000000000000..c8c4c5eaeace
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-fr-rCA/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi de %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-fr/strings.xml b/core/res/res/values-mcc302-mnc720-fr/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-fr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-gl/strings.xml b/core/res/res/values-mcc302-mnc720-gl/strings.xml
new file mode 100644
index 000000000000..d3a9055d8a09
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-gl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wifi de %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-gu/strings.xml b/core/res/res/values-mcc302-mnc720-gu/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-gu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-hi/strings.xml b/core/res/res/values-mcc302-mnc720-hi/strings.xml
new file mode 100644
index 000000000000..9a10eed9a140
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-hi/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s वाई-फ़ाई"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-hr/strings.xml b/core/res/res/values-mcc302-mnc720-hr/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-hr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-hu/strings.xml b/core/res/res/values-mcc302-mnc720-hu/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-hu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-hy/strings.xml b/core/res/res/values-mcc302-mnc720-hy/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-hy/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-in/strings.xml b/core/res/res/values-mcc302-mnc720-in/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-in/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-is/strings.xml b/core/res/res/values-mcc302-mnc720-is/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-is/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-it/strings.xml b/core/res/res/values-mcc302-mnc720-it/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-it/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-iw/strings.xml b/core/res/res/values-mcc302-mnc720-iw/strings.xml
new file mode 100644
index 000000000000..d0a799f8e379
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-iw/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"‎%s‎"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ja/strings.xml b/core/res/res/values-mcc302-mnc720-ja/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ja/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ka/strings.xml b/core/res/res/values-mcc302-mnc720-ka/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ka/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-kk/strings.xml b/core/res/res/values-mcc302-mnc720-kk/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-kk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-km/strings.xml b/core/res/res/values-mcc302-mnc720-km/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-km/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-kn/strings.xml b/core/res/res/values-mcc302-mnc720-kn/strings.xml
new file mode 100644
index 000000000000..6438ffb536ba
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-kn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s ವೈ-ಫೈ"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ko/strings.xml b/core/res/res/values-mcc302-mnc720-ko/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ko/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ky/strings.xml b/core/res/res/values-mcc302-mnc720-ky/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ky/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-lo/strings.xml b/core/res/res/values-mcc302-mnc720-lo/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-lo/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-lt/strings.xml b/core/res/res/values-mcc302-mnc720-lt/strings.xml
new file mode 100644
index 000000000000..2d3b87a58034
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-lt/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"„%s“ „Wi-Fi“"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-lv/strings.xml b/core/res/res/values-mcc302-mnc720-lv/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-lv/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-mk/strings.xml b/core/res/res/values-mcc302-mnc720-mk/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-mk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ml/strings.xml b/core/res/res/values-mcc302-mnc720-ml/strings.xml
new file mode 100644
index 000000000000..325b5db249e7
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ml/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s വൈഫൈ"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-mn/strings.xml b/core/res/res/values-mcc302-mnc720-mn/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-mn/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-mr/strings.xml b/core/res/res/values-mcc302-mnc720-mr/strings.xml
new file mode 100644
index 000000000000..9708843f5413
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-mr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s वाय-फाय"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ms/strings.xml b/core/res/res/values-mcc302-mnc720-ms/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ms/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-my/strings.xml b/core/res/res/values-mcc302-mnc720-my/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-my/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-nb/strings.xml b/core/res/res/values-mcc302-mnc720-nb/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-nb/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ne/strings.xml b/core/res/res/values-mcc302-mnc720-ne/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ne/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-nl/strings.xml b/core/res/res/values-mcc302-mnc720-nl/strings.xml
new file mode 100644
index 000000000000..4c5caddb9dcd
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-nl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wifi via %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-pa/strings.xml b/core/res/res/values-mcc302-mnc720-pa/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-pa/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-pl/strings.xml b/core/res/res/values-mcc302-mnc720-pl/strings.xml
new file mode 100644
index 000000000000..4e78857d94bc
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-pl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi – %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-pt-rBR/strings.xml b/core/res/res/values-mcc302-mnc720-pt-rBR/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-pt-rBR/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-pt-rPT/strings.xml b/core/res/res/values-mcc302-mnc720-pt-rPT/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-pt-rPT/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-pt/strings.xml b/core/res/res/values-mcc302-mnc720-pt/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-pt/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ro/strings.xml b/core/res/res/values-mcc302-mnc720-ro/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ro/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ru/strings.xml b/core/res/res/values-mcc302-mnc720-ru/strings.xml
new file mode 100644
index 000000000000..b88013beef37
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ru/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Сеть Wi-Fi \"%s\""</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-si/strings.xml b/core/res/res/values-mcc302-mnc720-si/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-si/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-sk/strings.xml b/core/res/res/values-mcc302-mnc720-sk/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-sk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-sl/strings.xml b/core/res/res/values-mcc302-mnc720-sl/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-sl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-sq/strings.xml b/core/res/res/values-mcc302-mnc720-sq/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-sq/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-sr/strings.xml b/core/res/res/values-mcc302-mnc720-sr/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-sr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-sv/strings.xml b/core/res/res/values-mcc302-mnc720-sv/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-sv/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-sw/strings.xml b/core/res/res/values-mcc302-mnc720-sw/strings.xml
new file mode 100644
index 000000000000..ee780df78ca5
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-sw/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi ya %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ta/strings.xml b/core/res/res/values-mcc302-mnc720-ta/strings.xml
new file mode 100644
index 000000000000..61c8b84800cc
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ta/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s வைஃபை"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-te/strings.xml b/core/res/res/values-mcc302-mnc720-te/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-te/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-th/strings.xml b/core/res/res/values-mcc302-mnc720-th/strings.xml
new file mode 100644
index 000000000000..d536f4510138
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-th/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi ของ %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-tl/strings.xml b/core/res/res/values-mcc302-mnc720-tl/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-tl/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-tr/strings.xml b/core/res/res/values-mcc302-mnc720-tr/strings.xml
new file mode 100644
index 000000000000..e41287af104b
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-tr/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s kablosuz"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-uk/strings.xml b/core/res/res/values-mcc302-mnc720-uk/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-uk/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-ur/strings.xml b/core/res/res/values-mcc302-mnc720-ur/strings.xml
new file mode 100644
index 000000000000..566f852435e2
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-ur/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"‎%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-uz/strings.xml b/core/res/res/values-mcc302-mnc720-uz/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-uz/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-vi/strings.xml b/core/res/res/values-mcc302-mnc720-vi/strings.xml
new file mode 100644
index 000000000000..20e4f47ad6e1
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-vi/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"Wi-Fi %s"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-zh-rCN/strings.xml b/core/res/res/values-mcc302-mnc720-zh-rCN/strings.xml
new file mode 100644
index 000000000000..c5526b24cb94
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-zh-rCN/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s WLAN"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-zh-rHK/strings.xml b/core/res/res/values-mcc302-mnc720-zh-rHK/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-zh-rHK/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-zh-rTW/strings.xml b/core/res/res/values-mcc302-mnc720-zh-rTW/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-zh-rTW/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720-zu/strings.xml b/core/res/res/values-mcc302-mnc720-zu/strings.xml
new file mode 100644
index 000000000000..9b2336d8006d
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720-zu/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array name="wfcSpnFormats">
+ <item msgid="2776657861851140021">"%s"</item>
+ <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc302-mnc720/strings.xml b/core/res/res/values-mcc302-mnc720/strings.xml
new file mode 100644
index 000000000000..f5b8496f9a0b
--- /dev/null
+++ b/core/res/res/values-mcc302-mnc720/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Template for showing mobile network operator name while WFC is active -->
+ <string-array name="wfcSpnFormats">
+ <item>%s</item>
+ <item>%s Wi-Fi</item>
+ </string-array>
+</resources>
diff --git a/core/res/res/values-mcc404/config.xml b/core/res/res/values-mcc404/config.xml
index 17539d81fa65..d6655f2361d4 100644
--- a/core/res/res/values-mcc404/config.xml
+++ b/core/res/res/values-mcc404/config.xml
@@ -25,4 +25,6 @@
</string-array>
<!-- Whether camera shutter sound is forced or not (country specific). -->
<bool name="config_camera_sound_forced">true</bool>
+ <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+ <bool name="config_showAreaUpdateInfoSettings">true</bool>
</resources>
diff --git a/core/res/res/values-mcc724/config.xml b/core/res/res/values-mcc724/config.xml
new file mode 100644
index 000000000000..98f70d5441d2
--- /dev/null
+++ b/core/res/res/values-mcc724/config.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+ <bool name="config_showAreaUpdateInfoSettings">true</bool>
+</resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index b35f770df132..599eabc748a5 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -131,7 +131,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="3910386316304772394">"За да воспоставувате повици и да испраќате пораки преку Wi-Fi, прво побарајте од операторот да ја постави услугава. Потоа, вклучете ја повторно „Повикување преку Wi-Fi“ во „Поставки“. (Код за грешка: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Регистрирајте се со операторот"</item>
@@ -1041,7 +1041,7 @@
<string name="anr_application_process" msgid="6417199034861140083">"<xliff:g id="APPLICATION">%1$s</xliff:g> не реагира"</string>
<string name="anr_process" msgid="6156880875555921105">"Процесот <xliff:g id="PROCESS">%1$s</xliff:g> не реагира"</string>
<string name="force_close" msgid="8346072094521265605">"Во ред"</string>
- <string name="report" msgid="4060218260984795706">"Извештај"</string>
+ <string name="report" msgid="4060218260984795706">"Пријави"</string>
<string name="wait" msgid="7147118217226317732">"Почекај"</string>
<string name="webpage_unresponsive" msgid="3272758351138122503">"Страницата не реагира.\n\nДали сакате да ја затворите?"</string>
<string name="launch_warning_title" msgid="1547997780506713581">"Пренасочена апликација"</string>
@@ -1106,6 +1106,13 @@
<item quantity="one">Отворени Wi-Fi мрежи се достапни</item>
<item quantity="other">Отворени Wi-Fi мрежи се достапни</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Поврзете се на отворена Wi‑Fi-мрежа"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Поврзување на отворена Wi‑Fi-мрежа"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Се поврзавте на Wi‑Fi-мрежа"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не можеше да се поврзе на Wi‑Fi-мрежа"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Допрете за да ги видите сите мрежи"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Поврзете се"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Сите мрежи"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Најавете се на мрежа на Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Најавете се на мрежа"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index f0871e8b9117..418392c5ea9d 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"സേവനത്തിനായി തിരയുന്നു"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"വൈഫൈ കോളിംഗ്"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"വൈഫൈ വഴി കോളുകൾ വിളിക്കാനും സന്ദേശങ്ങൾ അയയ്‌ക്കാനും ആദ്യം നിങ്ങളുടെ കാരിയറോട് ഈ സേവനം സജ്ജമാക്കാൻ ആവശ്യപ്പെടുക. ക്രമീകരണത്തിൽ നിന്ന് വീണ്ടും വൈഫൈ കോളിംഗ് ഓണാക്കുക."</item>
+ <item msgid="3910386316304772394">"വൈഫൈ വഴി കോളുകൾ ചെയ്യാനും സന്ദേശങ്ങൾ അയയ്‌ക്കാനും ആദ്യം നിങ്ങളുടെ കാരിയറോട് ഈ സേവനം സജ്ജമാക്കാൻ ആവശ്യപ്പെടുക. ക്രമീകരണത്തിൽ നിന്ന് വീണ്ടും വൈഫൈ കോളിംഗ് ഓണാക്കുക. (പിശക് കോഡ്: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"നിങ്ങളുടെ കാരിയറിൽ രജിസ്റ്റർ ചെയ്യുക"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">ലഭ്യമായ വൈഫൈ നെറ്റ്‌വർക്കുകൾ തുറക്കുക</item>
<item quantity="one">ലഭ്യമായ വൈഫൈ നെറ്റ്‌വർക്ക് തുറക്കുക</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"ലഭ്യമായ വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് കണക്റ്റുചെയ്യുക"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ലഭ്യമായ വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് കണക്റ്റുചെയ്യുന്നു"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് കണക്റ്റു‌ചെയ്‌‌തു"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"വൈ-ഫൈ നെറ്റ്‌വർക്കിലേക്ക് കണക്‌റ്റുചെയ്യാനായില്ല"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"എല്ലാ നെറ്റ്‌വർക്കുകളും കാണാൻ ടാപ്പുചെയ്യുക"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"കണക്റ്റുചെയ്യുക"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"എല്ലാ നെറ്റ്‌വർക്കുകളും"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 8b4f7f5b0cd6..4a8698a234ec 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Үйлчилгээг хайж байна…"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi Calling"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Wi-Fi-аар дуудлага хийх болон мессеж илгээхээр бол эхлээд оператороосоо энэ төхөөрөмжийг тохируулж өгөхийг хүсээрэй. Дараа нь Тохиргооноос Wi-Fi дуудлага хийх үйлдлийг асаагаарай."</item>
+ <item msgid="3910386316304772394">"Wi-Fi-аар дуудлага хийх, мессеж илгээх бол эхлээд оператор компаниасаа энэ үйлчилгээг тохируулж өгөхийг хүснэ үү. Дараа нь Тохиргооноос Wi-Fi дуудлага хийх үйлдлийг асаана уу. (Алдааны код: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Операторт бүртгүүлэх"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Нээлттэй Wi-Fi сүлжээ ашиглах боломжтой</item>
<item quantity="one">Нээлттэй Wi-Fi сүлжээ ашиглах боломжтой</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Нээлттэй Wi‑Fi сүлжээнд холбогдох"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Нээлттэй Wi‑Fi сүлжээнд холбогдож байна"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi сүлжээнд холбогдлоо"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi сүлжээнд холбогдож чадсангүй"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Бүх сүлжээг харахын тулд товшино уу"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Холбогдох"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Бүх сүлжээ"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi сүлжээнд нэвтэрнэ үү"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Сүлжээнд нэвтэрнэ үү"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 62d31aa98690..849f14d8cc7c 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"सेवा शोधत आहे"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"वाय-फाय कॉलिंग"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठविण्यासाठी, प्रथम आपल्या वाहकास ही सेवा सेट करण्यास सांगा. नंतर सेटिंग्जमधून पुन्हा वाय-फाय कॉलिंग चालू करा."</item>
+ <item msgid="3910386316304772394">"वाय-फायवरून कॉल करण्यासाठी आणि संदेश पाठवण्यासाठी आधी तुमच्या कॅरियरला ही सेवा सेट अप करण्यास सांगा. नंतर सेटिंग्जमधून वाय-फाय वापरून कॉल करणे पुन्हा चालू करा. (एरर कोड <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"आपल्या वाहकासह नोंदणी करा"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">खुले वाय-फाय नेटवर्क उपलब्ध</item>
<item quantity="other">खुले वाय-फाय नेटवर्क उपलब्ध</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"खुल्या वाय-फाय नेटवर्कशी कनेक्ट करा"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"खुल्या वाय-फाय नेटवर्कशी कनेक्ट करत आहे"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"वाय-फाय नेटवर्कशी कनेक्ट केले"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"वाय-फाय नेटवर्कशी कनेक्ट करू शकत नाही"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"सर्व नेटवर्क पाहण्यासाठी टॅप करा"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"कनेक्ट करा"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"सर्व नेटवर्क"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"वाय-फाय नेटवर्कमध्‍ये साइन इन करा"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"नेटवर्कवर साइन इन करा"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index adc03bcfeec7..d400f9624f9a 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Mencari Perkhidmatan"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Panggilan Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Untuk membuat panggilan dan menghantar mesej melalui Wi-Fi, mula-mula minta pembawa anda untuk menyediakan perkhidmatan ini. Kemudian hidupkan panggilan Wi-Fi semula daripada Tetapan."</item>
+ <item msgid="3910386316304772394">"Untuk membuat panggilan dan menghantar mesej melalui Wi-Fi, minta pembawa anda menyediakan perkhidmatan ini terlebih dahulu. Kemudian, hidupkan panggilan Wi-Fi sekali lagi daripada Tetapan. (Kod ralat: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Daftar dengan pembawa anda"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Rangkaian Wi-Fi terbuka tersedia</item>
<item quantity="one">Rangkaian Wi-Fi terbuka tersedia</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Sambung ke rangkaian Wi-Fi terbuka"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Menyambung ke rangkaian Wi‑Fi terbuka"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Disambungkan ke rangkaian Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Tidak dapat menyambung ke rangkaian Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Ketik untuk melihat semua rangkaian"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Sambung"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Semua Rangkaian"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Log masuk ke rangkaian Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Log masuk ke rangkaian"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 5577d1dd730f..a33bec8fe52a 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Wi-Fi အသုံးပြု၍ ဖုန်းခေါ်ရန်နှင့် မက်ဆေ့ဂျ်ပို့ရန်အတွက် သင့်ဝန်ဆောင်မှုပေးသူကို ဤဝန်ဆောင်မှုအား သတ်မှတ်ပေးရန် ဦးစွာတောင်းဆိုပါ။ ထို့နောက် ဆက်တင်ထဲသို့ သွား၍ Wi-Fi ဖြင့် ဖုန်းခေါ်ခြင်းကို ဖွင့်ရပါမည်။ (အမှားကုဒ်- <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"သင့် မိုဘိုင်းဝန်ဆောင်မှုဖြင့် မှတ်ပုံတင်ရန်"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Wi-Fi ကွန်ယက်များရရှိနိုင်သည်အား ဖွင့်ပါ</item>
<item quantity="one">Wi-Fi ကွန်ယက်ရရှိနိုင်သည်အား ဖွင့်ပါ</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"အများသုံး Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်ပါ"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"အများသုံး Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်နေသည်"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်ပြီးပါပြီ"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi ကွန်ရက်သို့ ချိတ်ဆက်၍ မရပါ"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ကွန်ရက်အားလုံးကို ကြည့်ရန် တို့ပါ"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"ချိတ်ဆက်ရန်"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ကွန်ရက်အားလုံး"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ဝိုင်ဖိုင်ကွန်ရက်သို့ လက်မှတ်ထိုးဝင်ပါ"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 3a19f3ae0d01..f38c260b9370 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Leter etter tjeneste"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-anrop"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"For å ringe og sende meldinger over Wi-Fi må du først be operatøren om å konfigurere denne tjenesten. Deretter slår du på Wi-Fi-anrop igjen fra Innstillinger."</item>
+ <item msgid="3910386316304772394">"For å ringe og sende meldinger over Wi-Fi må du først be operatøren om å konfigurere denne tjenesten. Deretter slår du på Wi-Fi-anrop igjen fra Innstillinger. (Feilkode: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registrer deg hos operatøren din"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Åpne Wi-Fi-nettverk er tilgjengelig</item>
<item quantity="one">Åpent Wi-Fi-nettverk er tilgjengelig</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Koble til et åpent Wi‑Fi-nettverk"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Kobler til åpent Wi-Fi-nettverk"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Koblet til Wi-Fi-nettverk"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Kunne ikke koble til Wi-Fi-nettverket"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Trykk for å se alle nettverkene"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Koble til"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle nettverk"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Logg på Wi-Fi-nettverket"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Logg på nettverk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 847914ffcb53..2098b51d612a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Wi-Fi मार्फत कलहरू गर्न र सन्देशहरू पठाउन सबभन्दा पहिला आफ्नो सेवा प्रदायकलाई यो सेवा सेट गर्न भन्नुहोस्। त्यसपछि सेटिङहरूबाट Wi-Fi कलिङलाई सक्रिय पार्नुहोस्। (त्रुटिसम्बन्धी कोड: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"तपाईँको वाहकसँग दर्ता गर्नुहोस्"</item>
@@ -1112,6 +1112,13 @@
<item quantity="other"> खुल्ला Wi-Fi सञ्जालहरू उपलब्ध छन्</item>
<item quantity="one">खुल्ला Wi-Fi सञ्जाल उपलब्ध छ</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"खुला Wi‑Fi नेटवर्कमा जडान गर्नुहोस्"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"खुला Wi‑Fi नेटवर्कमा जडान गर्दै"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi नेटवर्कमा जडान गरियो"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi नेटवर्कमा जडान गर्न सकिएन"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"सबै नेटवर्कहरू हेर्न ट्याप गर्नुहोस्"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"जडान गर्नुहोस्"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"सबै नेटवर्कहरू"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"सञ्जालमा साइन इन गर्नुहोस्"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index d11d66392a52..4d0beecd40ac 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Service zoeken"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Bellen via wifi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via \'Instellingen\'."</item>
+ <item msgid="3910386316304772394">"Als je wilt bellen en berichten wilt verzenden via wifi, moet je eerst je provider vragen deze service in te stellen. Schakel bellen via wifi vervolgens opnieuw in via Instellingen. (Foutcode: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registreren bij je provider"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Open wifi-netwerken beschikbaar</item>
<item quantity="one">Open wifi-netwerk beschikbaar</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Verbinding maken met een open wifi-netwerk"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Verbinding maken met een open wifi-netwerk…"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Verbonden met een wifi-netwerk"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Kan geen verbinding maken met het wifi-netwerk"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tik om alle netwerken te bekijken"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Verbinding maken"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alle netwerken"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Inloggen bij wifi-netwerk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Inloggen bij netwerk"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index a02e8cc88c01..a89872f0a6ef 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -130,9 +130,7 @@
<string name="roamingText12" msgid="1189071119992726320">"ਰੋਮਿੰਗ ਬੈਨਰ ਬੰਦ"</string>
<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>
- </string-array>
+ <!-- no translation found for wfcOperatorErrorAlertMessages:0 (3910386316304772394) -->
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਰਜਿਸਟਰ ਕਰੋ"</item>
</string-array>
@@ -1106,6 +1104,13 @@
<item quantity="one">ਉਪਲਬਧ Wi-Fi ਨੈੱਟਵਰਕ ਖੋਲ੍ਹੋ</item>
<item quantity="other">ਉਪਲਬਧ Wi-Fi ਨੈੱਟਵਰਕ ਖੋਲ੍ਹੋ</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"ਖੁੱਲ੍ਹੇ Wi‑Fi ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਹੋਵੋ"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ਖੁੱਲ੍ਹੇ Wi‑Fi ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"ਸਾਰੇ ਨੈੱਟਵਰਕਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"ਕਨੈਕਟ ਕਰੋ"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"ਸਾਰੇ ਨੈੱਟਵਰਕ"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi ਨੈੱਟਵਰਕ ਵਿੱਚ ਸਾਈਨ ਇਨ ਕਰੋ"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ਨੈੱਟਵਰਕ ਤੇ ਸਾਈਨ ਇਨ ਕਰੋ"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index e5dbab3eddac..f3d53872f1d7 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -133,7 +133,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Wyszukiwanie usługi"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Połączenia przez Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Aby dzwonić i wysyłać wiadomości przez Wi-Fi, poproś swojego operatora o skonfigurowanie tej usługi. Potem ponownie włącz połączenia przez Wi-Fi w Ustawieniach."</item>
+ <item msgid="3910386316304772394">"Aby dzwonić i wysyłać wiadomości przez Wi-Fi, poproś swojego operatora o skonfigurowanie tej usługi. Potem ponownie włącz połączenia przez Wi-Fi w Ustawieniach. (Kod błędu: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Zarejestruj u operatora"</item>
@@ -1150,6 +1150,13 @@
<item quantity="other">Dostępne są otwarte sieci Wi-Fi</item>
<item quantity="one">Dostępna jest otwarta sieć Wi-Fi</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Połącz się z otwartą siecią Wi-Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Łączę się z otwartą siecią Wi-Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Połączono z siecią Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nie udało się połączyć z siecią Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Kliknij, by zobaczyć wszystkie sieci"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Połącz"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Wszystkie sieci"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Zaloguj się w sieci Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Zaloguj się do sieci"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index c74178d890b7..6c224429b07b 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Pesquisando serviço"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Chamadas por Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Para fazer chamadas e enviar mensagens por Wi-Fi, primeiro peça à sua operadora para configurar esse serviço. Depois ative novamente as chamadas por Wi-Fi nas configurações."</item>
+ <item msgid="3910386316304772394">"Para fazer chamadas e enviar mensagens por Wi-Fi, primeiro peça à sua operadora para configurar esse serviço. Depois, ative novamente a chamada no Wi-Fi nas configurações. Código de erro: <xliff:g id="CODE">%1$s</xliff:g>"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Faça registro na sua operadora"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">Abrir redes Wi-Fi disponíveis</item>
<item quantity="other">Abrir redes Wi-Fi disponíveis</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Conectar-se a uma rede Wi‑Fi aberta"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Conectando-se a uma rede Wi‑Fi aberta"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Conectado a uma rede Wi‑Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Não foi possível conectar-se à rede Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toque para ver todas as redes"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectar"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas as redes"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Fazer login na rede Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Fazer login na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1623,7 +1630,7 @@
<string name="package_installed_device_owner" msgid="6875717669960212648">"Instalado pelo seu administrador"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"Atualizado pelo seu administrador"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"Excluído pelo seu administrador"</string>
- <string name="battery_saver_description" msgid="1960431123816253034">"A economia de bateria reduz o desempenho e os limites de vibração do dispositivo, os serviços de localização e a maioria dos dados em segundo plano para aumentar a duração da bateria. E-mails, mensagens e outros aplicativos que dependem de sincronização não serão atualizados, a não ser que você os abra.\n\nA economia de bateria é desligada automaticamente quando o dispositivo está sendo carregado."</string>
+ <string name="battery_saver_description" msgid="1960431123816253034">"A economia de bateria reduz o desempenho do dispositivo e limita a vibração, os serviços de localização e a maioria dos dados em segundo plano para aumentar a duração da bateria. E-mails, mensagens e outros apps que dependem de sincronização não serão atualizados, a não ser que você os abra.\n\nA economia de bateria é desligada automaticamente quando o dispositivo está sendo carregado."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Para ajudar a reduzir o uso de dados, a Economia de dados impede que alguns apps enviem ou recebam dados em segundo plano. Um app que você esteja usando no momento pode acessar dados, mas com menos frequência. Isso pode significar que as imagens não serão exibidas até que você toque nelas."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Ativar Economia de dados?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Ativar"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 1eb57a565d64..2d9a6d47583b 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"A procurar Serviço"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Chamadas Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. Em seguida, nas Definições, ative novamente as chamadas por Wi-Fi."</item>
+ <item msgid="3910386316304772394">"Para fazer chamadas e enviar mensagens por Wi-Fi, comece por pedir ao seu operador para configurar este serviço. De seguida, nas Definições, ative novamente as Chamadas Wi-Fi. (Código de erro: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registar-se junto do seu operador"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">Open Wi-Fi networks available</item>
<item quantity="other">Redes Wi-Fi abertas disponíveis</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Ligar à rede Wi-Fi aberta"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"A ligar à rede Wi-Fi aberta…"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Ligado à rede Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Não foi possível ligar à rede Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toque para ver todas as redes"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Ligar"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas as redes"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Iniciar sessão na rede Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Início de sessão na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c74178d890b7..6c224429b07b 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Pesquisando serviço"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Chamadas por Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Para fazer chamadas e enviar mensagens por Wi-Fi, primeiro peça à sua operadora para configurar esse serviço. Depois ative novamente as chamadas por Wi-Fi nas configurações."</item>
+ <item msgid="3910386316304772394">"Para fazer chamadas e enviar mensagens por Wi-Fi, primeiro peça à sua operadora para configurar esse serviço. Depois, ative novamente a chamada no Wi-Fi nas configurações. Código de erro: <xliff:g id="CODE">%1$s</xliff:g>"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Faça registro na sua operadora"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">Abrir redes Wi-Fi disponíveis</item>
<item quantity="other">Abrir redes Wi-Fi disponíveis</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Conectar-se a uma rede Wi‑Fi aberta"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Conectando-se a uma rede Wi‑Fi aberta"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Conectado a uma rede Wi‑Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Não foi possível conectar-se à rede Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Toque para ver todas as redes"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectar"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Todas as redes"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Fazer login na rede Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Fazer login na rede"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1623,7 +1630,7 @@
<string name="package_installed_device_owner" msgid="6875717669960212648">"Instalado pelo seu administrador"</string>
<string name="package_updated_device_owner" msgid="1847154566357862089">"Atualizado pelo seu administrador"</string>
<string name="package_deleted_device_owner" msgid="2307122077550236438">"Excluído pelo seu administrador"</string>
- <string name="battery_saver_description" msgid="1960431123816253034">"A economia de bateria reduz o desempenho e os limites de vibração do dispositivo, os serviços de localização e a maioria dos dados em segundo plano para aumentar a duração da bateria. E-mails, mensagens e outros aplicativos que dependem de sincronização não serão atualizados, a não ser que você os abra.\n\nA economia de bateria é desligada automaticamente quando o dispositivo está sendo carregado."</string>
+ <string name="battery_saver_description" msgid="1960431123816253034">"A economia de bateria reduz o desempenho do dispositivo e limita a vibração, os serviços de localização e a maioria dos dados em segundo plano para aumentar a duração da bateria. E-mails, mensagens e outros apps que dependem de sincronização não serão atualizados, a não ser que você os abra.\n\nA economia de bateria é desligada automaticamente quando o dispositivo está sendo carregado."</string>
<string name="data_saver_description" msgid="6015391409098303235">"Para ajudar a reduzir o uso de dados, a Economia de dados impede que alguns apps enviem ou recebam dados em segundo plano. Um app que você esteja usando no momento pode acessar dados, mas com menos frequência. Isso pode significar que as imagens não serão exibidas até que você toque nelas."</string>
<string name="data_saver_enable_title" msgid="4674073932722787417">"Ativar Economia de dados?"</string>
<string name="data_saver_enable_button" msgid="7147735965247211818">"Ativar"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 578710907237..320dfb5acc61 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -132,7 +132,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Se caută serviciul"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Apelare prin Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Pentru a apela și a trimite mesaje prin Wi-Fi, mai întâi solicitați configurarea acestui serviciu la operator. Apoi, activați din nou apelarea prin Wi-Fi din Setări."</item>
+ <item msgid="3910386316304772394">"Pentru a efectua apeluri și a trimite mesaje prin Wi-Fi, mai întâi solicitați configurarea acestui serviciu la operator. Apoi, activați din nou apelarea prin Wi-Fi din Setări. (Cod de eroare: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Înregistrați-vă la operatorul dvs."</item>
@@ -1128,6 +1128,13 @@
<item quantity="other">Rețele Wi-Fi deschise disponibile</item>
<item quantity="one">Rețea Wi-Fi deschisă disponibilă</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Conectați-vă la o rețea Wi‑Fi deschisă"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Se stabilește conexiunea la o rețea Wi‑Fi deschisă"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"S-a realizat conexiunea la rețeaua Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nu s-a putut stabili conexiunea la rețeaua Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Atingeți pentru a vedea toate rețelele"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Conectați-vă"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Toate rețelele"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Conectați-vă la rețeaua Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Conectați-vă la rețea"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 56349891e49d..f81c8735fef2 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -133,7 +133,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Поиск службы"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Звонки по Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Чтобы совершать звонки и отправлять сообщения по Wi-Fi, необходимо сначала обратиться к оператору связи и подключить эту услугу. После этого вы сможете снова выбрать этот параметр в настройках."</item>
+ <item msgid="3910386316304772394">"Чтобы совершать звонки и отправлять сообщения по Wi-Fi, необходимо подключить эту услугу через оператора связи. После этого вы сможете выбрать этот параметр в настройках. Код ошибки: <xliff:g id="CODE">%1$s</xliff:g>."</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Укажите оператора и зарегистрируйтесь"</item>
@@ -210,7 +210,7 @@
<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_title" msgid="4142355915340627490">"Сбросить к заводским настройкам"</string>
<string name="reboot_to_reset_message" msgid="2432077491101416345">"Перезагрузка…"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Выключение..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Планшетный ПК будет отключен."</string>
@@ -1150,6 +1150,13 @@
<item quantity="many">Есть открытые сети Wi-Fi</item>
<item quantity="other">Есть открытые сети Wi-Fi</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Подключитесь к открытой сети Wi‑Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Подключение к открытой сети Wi‑Fi…"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Подключено к сети Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не удалось подключиться к сети Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Нажмите, чтобы увидеть список сетей"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Подключиться"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Все сети"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Подключение к Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Регистрация в сети"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 0c38e4d140bc..3ed2c87d50eb 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Wi-Fi හරහා ඇමතුම් සිදු කිරීමට සහ පණිවිඩ යැවීමට, පළමුව මෙම සේවාව පිහිටුවන ලෙස ඔබේ වාහකයෙන් ඉල්ලන්න. අනතුරුව සැකසීම් වෙතින් Wi-Fi ඇමතුම නැවත ක්‍රියාත්මක කරන්න. (දෝෂ කේතය <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"ඔබගේ වාහකය සමඟ ලියාපදිංචි වන්න"</item>
@@ -1108,6 +1108,13 @@
<item quantity="one">විවෘත Wi-Fi ජාල තිබේ</item>
<item quantity="other">විවෘත Wi-Fi ජාල තිබේ</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"විවෘත Wi-Fi ජාලය වෙත සම්බන්ධ වෙන්න"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"විවෘත Wi-Fi ජාලය වෙත සම්බන්ධ වෙමින්"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi-Fi ජාලයක් වෙත සම්බන්ධ විය"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi-Fi ජාලයක් වෙත සම්බන්ධ විය නොහැකි විය"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"සියලු ජාල බැලීමට තට්ටු කරන්න"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"සම්බන්ධ කරන්න"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"සියලු ජාල"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi ජාලයට පුරනය වන්න"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ජාලයට පුරනය වන්න"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 5bea2a0cc3b2..e0767ce5ab3a 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -133,7 +133,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Vyhľadávanie služby"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Volanie cez Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Ak chcete volať a odosielať správy prostredníctvom siete Wi-Fi, kontaktujte najskôr svojho operátora v súvislosti s nastavením tejto služby. Potom opäť zapnite v Nastaveniach volanie cez Wi-Fi."</item>
+ <item msgid="3910386316304772394">"Ak chcete volať a odosielať správy prostredníctvom siete Wi-Fi, kontaktujte najskôr svojho operátora v súvislosti s nastavením tejto služby. Potom opäť zapnite v Nastaveniach volanie cez Wi-Fi. (Kód chyby: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registrujte sa so svojím operátorom"</item>
@@ -1150,6 +1150,13 @@
<item quantity="other">K dispozícii sú verejné siete Wi-Fi</item>
<item quantity="one">K dispozícii je verejná sieť Wi-Fi</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Pripojenie k otvorenej sieti Wi-Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Pripája sa k otvorenej sieti Wi-Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Pripojenie k sieti Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"K sieti Wi‑Fi sa nepodarilo pripojiť"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Klepnutím zobrazíte všetky siete"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Pripojiť"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Všetky siete"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prihlásiť sa do siete Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prihlásenie do siete"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 1944c3aa53ba..9f0d64634ff5 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -133,7 +133,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Iskanje storitve"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Klicanje prek Wi-Fi-ja"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Če želite klicati ali pošiljati sporočila prek omrežja Wi-Fi, se najprej obrnite na operaterja, da nastavi to storitev. Nato v nastavitvah znova vklopite klicanje prek omrežja Wi-Fi."</item>
+ <item msgid="3910386316304772394">"Če želite klicati ali pošiljati sporočila prek omrežja Wi-Fi, se najprej obrnite na operaterja, da nastavi to storitev. Nato v nastavitvah znova vklopite klicanje prek omrežja Wi-Fi. (Koda napake: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registracija pri operaterju"</item>
@@ -286,7 +286,7 @@
<string name="permgroupdesc_calendar" msgid="3889615280211184106">"dostop do koledarja"</string>
<string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
<string name="permgroupdesc_sms" msgid="4656988620100940350">"pošiljanje in ogled sporočil SMS"</string>
- <string name="permgrouplab_storage" msgid="1971118770546336966">"Prostor za shranjevanje"</string>
+ <string name="permgrouplab_storage" msgid="1971118770546336966">"Shramba"</string>
<string name="permgroupdesc_storage" msgid="637758554581589203">"dostop do fotografij, predstavnosti in datotek v napravi"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"snemanje zvoka"</string>
@@ -1150,6 +1150,13 @@
<item quantity="few">Na voljo so odprta omrežja Wi-Fi</item>
<item quantity="other">Na voljo so odprta omrežja Wi-Fi</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Vzpostavite povezavo z odprtim omrežjem Wi‑Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Vzpostavljanje povezave z odprtim omrežjem Wi‑Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Povezava z omrežjem Wi-Fi je vzpostavljena"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Povezave z omrežjem Wi-Fi ni bilo mogoče vzpostaviti"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Dotaknite se, če si želite ogledati vsa omrežja"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Vzpostavi povezavo"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Vsa omrežja"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Prijavite se v omrežje Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Prijava v omrežje"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 5f12917c3703..68a3642dbf7b 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Po kërkon për shërbim"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Telefonatë me Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Për të bërë telefonata dhe për të dërguar mesazhe me Wi-Fi, në fillim kërkoji operatorit celular ta konfigurojë këtë shërbim. Më pas aktivizo përsëri telefonatat me Wi-Fi, nga Cilësimet."</item>
+ <item msgid="3910386316304772394">"Për të bërë telefonata dhe për të dërguar mesazhe nëpërmjet Wi-Fi, në fillim kërkoji operatorit celular të konfigurojë këtë shërbim. Më pas aktivizo përsëri telefonatat me Wi-Fi nga \"Cilësimet\". (Kodi i gabimit: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Regjistrohu me operatorin tënd celular"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Rrjete të hapura Wi-Fi në përdorim</item>
<item quantity="one">Rrjet i hapur Wi-Fi në përdorim</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Lidhu me rrjetin e hapur Wi‑Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Po lidhet me rrjetin e hapur Wi‑Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Lidhur me rrjetin e hapur Wi‑Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Nuk mund të lidhet me rrjetin Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Trokit për të parë të gjitha rrjetet"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Lidhu"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Të gjitha rrjetet"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Identifikohu në rrjetin Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Identifikohu në rrjet"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 882a34386422..88fb1f2aba57 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -132,7 +132,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="3910386316304772394">"Да бисте упућивали позиве и слали поруке преко Wi-Fi-ја, прво затражите од мобилног оператера да вам омогући ову услугу. Затим у Подешавањима поново укључите Позивање преко Wi-Fi-ја. (кôд грешке: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Региструјте се код мобилног оператера"</item>
@@ -1128,6 +1128,13 @@
<item quantity="few">Отворене Wi-Fi мреже су доступне</item>
<item quantity="other">Отворене Wi-Fi мреже су доступне</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Повежите се са отвореном Wi‑Fi мрежом"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Повезујете се са отвореном Wi‑Fi мрежом"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Повезали сте се са Wi‑Fi мрежом"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Повезивање са Wi‑Fi мрежом није успело"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Додирните да бисте видели све мреже"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Повежи"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Све мреже"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Пријављивање на Wi-Fi мрежу"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Пријавите се на мрежу"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 4ab184eb8762..6075f72cfddb 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Söker efter tjänst"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi-samtal"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Om du vill ringa samtal och skicka meddelanden via Wi-Fi ber du först operatören att konfigurera tjänsten. Därefter kan du aktivera Wi-Fi-samtal på nytt från Inställningar."</item>
+ <item msgid="3910386316304772394">"Om du vill ringa samtal och skicka meddelanden via Wi-Fi ber du först operatören att konfigurera tjänsten. Därefter kan du aktivera Wi-Fi-samtal på nytt från Inställningar. (Felkod: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Registrera dig hos operatören"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Öppna Wi-Fi-nätverk är tillgängliga</item>
<item quantity="one">Öppet Wi-Fi-nätverk är tillgängligt</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Anslut till ett öppet Wi-Fi-nätverk"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ansluter till ett öppet Wi-Fi-nätverk"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Ansluten till Wi-Fi-nätverket"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Det gick inte att ansluta till Wi‑Fi-nätverket"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tryck för att visa alla nätverk"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Anslut"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Alla nätverk"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Logga in på ett Wi-Fi-nätverk"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Logga in på nätverket"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 3e64ce25ce99..673f335a1507 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Inatafuta Huduma"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Upigaji Simu kwa Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Ili upige simu na kutuma ujumbe kupitia Wi-Fi, mwambie mtoa huduma wako asanidi huduma hii kwanza. Kisha uwashe tena upigaji simu kwa Wi-Fi kutoka kwenye Mipangilio."</item>
+ <item msgid="3910386316304772394">"Ili upige simu na kutuma ujumbe kupitia Wi-Fi, mwambie mtoa huduma wako aweke mipangilio ya huduma hii kwanza. Kisha uwashe tena kipengele cha kupiga simu kupitia Wi-Fi kwenye Mipangilio. (Msimbo wa hitilafu: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Jisajili na mtoa huduma wako"</item>
@@ -1104,6 +1104,13 @@
<item quantity="other">Fungua mitandao ya Wi-Fi inayopatikana</item>
<item quantity="one">Fungua mtandao wa Wi-Fi unaopatikana</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Unganisha kwenye mtandao wa Wi‑Fi unaotumiwa na mtu yeyote"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Inaunganisha kwenye mtandao wa Wi‑Fi unaotumiwa na mtu yeyote"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Imeunganisha kwenye mtandao wa Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Imeshindwa kuunganisha kwenye mtandao wa Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Gonga ili uone mitandao yote"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Unganisha"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Mitandao Yote"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Ingia kwa mtandao wa Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Ingia katika mtandao"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 6fa67f79c5de..bb9e85f8b186 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"சேவையைத் தேடுகிறது"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"வைஃபை அழைப்பு"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"வைஃபை மூலம் அழைக்க மற்றும் செய்திகள் அனுப்ப, முதலில் மொபைல் நிறுவனத்திடம் இந்தச் சேவையை அமைக்குமாறு கேட்கவும். பிறகு அமைப்புகளில் மீண்டும் வைஃபை அழைப்பை இயக்கவும்."</item>
+ <item msgid="3910386316304772394">"வைஃபை மூலம் அழைக்கவும் செய்திகளை அனுப்பவும், முதலில் தொலைத்தொடர்பு நிறுவனத்திடம் இந்தச் சேவையை அமைக்குமாறு கேட்கவும். பிறகு அமைப்புகளில் மீண்டும் வைஃபை அழைப்பை இயக்கவும். (பிழைக் குறியீடு <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"உங்கள் மொபைல் நிறுவனத்தில் பதிவுசெய்யவும்"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">பொது வைஃபை நெட்வொர்க்குகள் உள்ளன</item>
<item quantity="one">பொது வைஃபை நெட்வொர்க் உள்ளது</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"திறந்த வைஃபை நெட்வொர்க்குடன் இணைக்கவும்"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"திறந்த வைஃபை நெட்வொர்க்குடன் இணைக்கிறது"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"வைஃபை நெட்வொர்க்குடன் இணைக்கப்பட்டது"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"வைஃபை நெட்வொர்க்குடன் இணைக்க முடியவில்லை"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"எல்லா நெட்வொர்க்குகளையும் பார்க்க, தட்டவும்"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"இணை"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"எல்லா நெட்வொர்க்குகளும்"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"வைஃபை நெட்வொர்க்கில் உள்நுழையவும்"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"நெட்வொர்க்கில் உள்நுழையவும்"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index d1e152806236..0d5e69f22b59 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -131,7 +131,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="3910386316304772394">"Wi-Fiతో కాల్‌లను చేయడానికి మరియు సందేశాలను పంపించడానికి, మొదట ఈ సేవను సెటప్ చేయాల్సిందిగా మీ క్యారియర్‌‌కి చెప్పండి. ఆ తర్వాత సెట్టింగ్‌ల నుండి Wi-Fi కాలింగ్‌ని మళ్లీ ఆన్ చేయండి. (లోపం కోడ్: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"మీ క్యారియర్‌తో నమోదు చేయండి"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">ఓపెన్ Wi-Fi నెట్‌వర్క్‌లు అందుబాటులో ఉన్నాయి</item>
<item quantity="one">ఓపెన్ Wi-Fi నెట్‌వర్క్ అందుబాటులో ఉంది</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"బహిరంగ Wi‑Fi నెట్‌వర్క్‌కు కనెక్ట్ చేయండి"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"బహిరంగ Wi‑Fi నెట్‌వర్క్‌కు కనెక్ట్ చేస్తోంది"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi నెట్‌వర్క్‌కు కనెక్ట్ చేయబడింది"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi‑Fi నెట్‌వర్క్‌కు కనెక్ట్ చేయడం సాధ్యపడలేదు"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"అన్ని నెట్‌వర్క్‌లు చూడటానికి నొక్కండి"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"కనెక్ట్ చేయి"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"అన్ని నెట్‌వర్క్‌లు"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 492099f5375e..463db4e535a3 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -131,7 +131,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="3910386316304772394">"หากต้องการโทรออกและส่งข้อความผ่าน Wi-Fi โปรดสอบถามผู้ให้บริการของคุณก่อนเพื่อตั้งค่าบริการนี้ แล้วเปิดการโทรผ่าน Wi-Fi อีกครั้งจากการตั้งค่า (รหัสข้อผิดพลาด: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"ลงทะเบียนกับผู้ให้บริการ"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">มีหลายเครือข่าย Wi-Fi สาธารณะที่ใช้งานได้</item>
<item quantity="one">มี 1 เครือข่าย Wi-Fi สาธารณะที่ใช้งานได้</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"เชื่อมต่อเครือข่าย Wi‑Fi แบบเปิด"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"กำลังเชื่อมต่อเครือข่าย Wi‑Fi แบบเปิด"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"เชื่อมต่อเครือข่าย Wi-Fi แล้ว"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ไม่สามารถเชื่อมต่อเครือข่าย Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"แตะเพื่อดูเครือข่ายทั้งหมด"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"เชื่อมต่อ"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"เครือข่ายทั้งหมด"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"ลงชื่อเข้าใช้เครือข่าย WiFi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"ลงชื่อเข้าใช้เครือข่าย"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index aad6f6015fb9..dc0bf9ea6db2 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Naghahanap ng Serbisyo"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Pagtawag sa pamamagitan ng Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Upang tumawag at magpadala ng mga mensahe sa pamamagitan ng Wi-Fi, hilingin muna sa iyong carrier na i-set up ang serbisyong ito. Pagkatapos ay muling i-on ang pagtawag sa Wi-Fi mula sa Mga Setting."</item>
+ <item msgid="3910386316304772394">"Upang makatawag at makapagpadala ng mga mensahe sa Wi-Fi, hilingin muna sa iyong carrier na i-set up ang serbisyong ito. Pagkatapos ay i-on muli ang pagtawag gamit ang Wi-Fi mula sa Mga Setting. (Error code: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Magparehistro sa iyong carrier"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">Available ang mga bukas na Wi-Fi network</item>
<item quantity="other">Available ang mga bukas na Wi-Fi network</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Kumonekta sa bukas na Wi‑Fi network"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Kumokonekta sa bukas na Wi‑Fi network"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Nakakonekta sa Wi‑Fi network"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Hindi makakonekta sa Wi‑Fi network"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"I-tap upang makita ang lahat ng network"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Kumonekta"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Lahat ng Network"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Mag-sign in sa Wi-Fi network"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Mag-sign in sa network"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e7c1f48246b1..c97746579360 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Hizmet Aranıyor"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Kablosuz Çağrı"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Kablosuz ağ üzerinden telefon etmek ve ileti göndermek için ilk önce operatörünüzden bu hizmeti ayarlamasını isteyin. Sonra tekrar Ayarlar\'dan Kablosuz çağrı özelliğini açın."</item>
+ <item msgid="3910386316304772394">"Kablosuz ağ üzerinden telefon etmek ve mesaj göndermek için öncelikle operatörünüzden bu hizmeti ayarlamasını isteyin. Sonra, Ayarlar\'dan Kablosuz çağrı özelliğini tekrar açın. (Hata kodu: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Operatörünüze kaydolun"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Kullanılabilir Kablosuz ağları aç</item>
<item quantity="one">Kullanılabilir Kablosuz ağı aç</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Açık kablosuz ağa bağlanın"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Açık kablosuz ağa bağlandı"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Kablosuz ağa bağlanıldı"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Kablosuz ağa bağlanamadı"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tüm ağları görmek için dokunun"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Bağlan"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Tüm Ağlar"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Kablosuz ağda oturum açın"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Ağda oturum açın"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index d545f3a26b6d..9b65f5768f08 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -133,7 +133,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="3910386316304772394">"Щоб телефонувати або надсилати повідомлення через Wi-Fi, спершу попросіть свого оператора налаштувати цю послугу. Після цього знову ввімкніть дзвінки через Wi-Fi у налаштуваннях. (Код помилки: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Зареєструйтеся в оператора"</item>
@@ -1150,6 +1150,13 @@
<item quantity="many">Відкриті мережі Wi-Fi доступні</item>
<item quantity="other">Відкриті мережі Wi-Fi доступні</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Під’єднайтеся до відкритої мережі Wi-Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Під’єднання до відкритої мережі Wi-Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Під’єднано до мережі Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Не вдалося під’єднатися до мережі Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Торкніться, щоб побачити всі мережі"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Під’єднатися"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Усі мережі"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Вхід у мережу Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Вхід у мережу"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index a453f334caea..e61a0624abf6 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -130,9 +130,7 @@
<string name="roamingText12" msgid="1189071119992726320">"رومنگ بینر آف"</string>
<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>
- </string-array>
+ <!-- no translation found for wfcOperatorErrorAlertMessages:0 (3910386316304772394) -->
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"اپنے کیریئر کے ساتھ رجسٹر کریں"</item>
</string-array>
@@ -1106,6 +1104,13 @@
<item quantity="other">‏عوامی Wi-Fi نیٹ ورکس دستیاب ہیں</item>
<item quantity="one">‏عوامی Wi-Fi نیٹ ورک دستیاب ہے</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"‏عوامی Wi‑Fi نیٹ ورک سے منسلک ہوں"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"‏عوامی Wi‑Fi نیٹ ورک سے منسلک ہو رہا ہے"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"‏عوامی Wi‑Fi نیٹ ورک سے منسلک ہو گيا"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"‏Wi‑Fi نیٹ ورک سے منسلک نہیں ہو سکا"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"تمام نیٹ ورکس دیکھنے کیلئے تھپتھپائيں"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"منسلک کریں"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"تمام نیٹ ورکس"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"‏Wi-Fi نیٹ ورک میں سائن ان کریں"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"نیٹ ورک میں سائن ان کریں"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index d44c5aeed050..36a74fe6df91 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Xizmatlar qidirilmoqda"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Wi-Fi qo‘ng‘iroq"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Wi-Fi orqali qo‘ng‘iroqlarni amalga oshirish va xabarlar bilan almashinish uchun uyali aloqa operatoringizdan ushbu xizmatni yoqib qo‘yishni so‘rashingiz lozim. Keyin sozlamalarda Wi-Fi qo‘ng‘irog‘i imkoniyatini yoqib olishingiz mumkin."</item>
+ <item msgid="3910386316304772394">"Wi-Fi orqali qo‘ng‘iroqlarni amalga oshirish va xabarlar bilan almashinish uchun uyali aloqa operatoringizdan ushbu xizmatni yoqib qo‘yishni so‘rashingiz lozim. Keyin sozlamalarda Wi-Fi qo‘ng‘irog‘i imkoniyatini yoqib olishingiz mumkin. (Xato kodi: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Mobil operatoringiz yordamida ro‘yxatdan o‘ting"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Ochiq Wi-Fi tarmoqlari aniqlandi</item>
<item quantity="one">Ochiq Wi-Fi tarmog‘i aniqlandi</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Ochiq Wi‑Fi tarmoqqa ulaning"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ochiq Wi‑Fi tarmoqqa ulanilmoqda"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Wi‑Fi tarmoqqa ulanildi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Wi-Fi tarmoqqa ulanib bo‘lmadi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Barcha tarmoqlarni ko‘rish uchun bosing"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Ulanish"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Barcha tarmoqlar"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Wi-Fi tarmoqqa kirish"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Tarmoqqa kirish"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1440,7 +1447,7 @@
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
<string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", xavfsiz"</string>
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Grafik kalit esimdan chiqdi"</string>
- <string name="kg_wrong_pattern" msgid="1850806070801358830">"Grafik kalit noto‘g‘ri"</string>
+ <string name="kg_wrong_pattern" msgid="1850806070801358830">"Grafik kalit xato"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"Parol noto‘g‘ri"</string>
<string name="kg_wrong_pin" msgid="1131306510833563801">"PIN-kod noto‘g‘ri"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 325ff2da128e..d15a48f978a3 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Đang tìm kiếm Dịch vụ"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Gọi qua Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Để gọi điện và gửi tin nhắn qua Wi-Fi, trước tiên hãy yêu cầu nhà cung cấp dịch vụ của bạn thiết lập dịch vụ này. Sau đó, bật lại gọi qua Wi-Fi từ Cài đặt."</item>
+ <item msgid="3910386316304772394">"Để gọi điện và gửi tin nhắn qua Wi-Fi, trước tiên hãy yêu cầu nhà cung cấp dịch vụ của bạn thiết lập dịch vụ này. Sau đó, bật lại gọi qua Wi-Fi từ Cài đặt. (Mã lỗi: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Đăng ký với nhà cung cấp dịch vụ của bạn"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">Mở các mạng Wi-Fi khả dụng</item>
<item quantity="one">Mở mạng Wi-Fi khả dụng</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Kết nối với mạng Wi-Fi đang mở"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Đang kết nối với mạng Wi‑Fi đang mở"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Đã kết nối với mạng Wi-Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Không thể kết nối với mạng Wi‑Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Nhấn để xem tất cả các mạng"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Kết nối"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Tất cả các mạng"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Đăng nhập vào mạng Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Đăng nhập vào mạng"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index a8d08ea4f487..6e10594326d0 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"正在搜索服务"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"WLAN 通话"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"要通过 WLAN 打电话和发信息,请先让您的运营商开通此服务,然后再到“设置”中重新开启 WLAN 通话功能。"</item>
+ <item msgid="3910386316304772394">"要通过 WLAN 打电话和发信息,请先让您的运营商开通此服务,然后再到“设置”中重新开启 WLAN 通话功能(错误代码:<xliff:g id="CODE">%1$s</xliff:g>)。"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"向您的运营商注册"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">有可用的开放 WLAN 网络</item>
<item quantity="one">有可用的开放 WLAN 网络</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"连接到开放的 WLAN 网络"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"正在连接到开放的 WLAN 网络"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"已连接到 WLAN 网络"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"无法连接到 WLAN 网络"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"点按即可查看所有网络"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"连接"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"所有网络"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"登录到WLAN网络"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"登录到网络"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index e03501ac8d44..c7b59f406d39 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -131,7 +131,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="3910386316304772394">"如要透過 Wi-Fi 撥打電話和傳送訊息,請先向流動網絡供應商要求設定此服務,然後再次在「設定」中開啟「Wi-Fi 通話」。(錯誤代碼:<xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"向您的流動網絡供應商註冊"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">有可用的公開 Wi-Fi 網絡</item>
<item quantity="one">有可用的公開 Wi-Fi 網絡</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"連線至開放的 Wi-Fi 網絡"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"正在連線至開放的 Wi-Fi 網絡"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"已連線至 Wi-Fi 網絡"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"無法連線至 Wi-Fi 網絡"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"輕按即可查看所有網絡"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"連線"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"所有網絡"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"登入 Wi-Fi 網絡"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"登入網絡"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 166e6efb6f0d..87117e4ae37b 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -131,7 +131,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="3910386316304772394">"如要透過 Wi-Fi 網路撥打電話及傳送訊息,請先要求電信業者為你設定這項服務,然後再次前往「設定」頁面啟用 Wi-Fi 通話功能。(錯誤代碼:<xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"向你的電信業者註冊"</item>
@@ -1106,6 +1106,13 @@
<item quantity="other">有多個可用的開放 Wi-Fi 網路</item>
<item quantity="one">有多個可用的開放 Wi-Fi 網路</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"連線至開放的 Wi‑Fi 網路"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"正在連線至開放的 Wi‑Fi 網路"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"已連線至 Wi-Fi 網路"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"無法連線至 Wi‑Fi 網路"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"輕觸即可查看所有網路"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"連線"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"所有網路"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"登入 Wi-Fi 網路"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"登入網路"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
@@ -1188,7 +1195,7 @@
<string name="usb_unsupported_audio_accessory_title" msgid="2256529893240208458">"不支援的音訊配件"</string>
<string name="usb_unsupported_audio_accessory_message" msgid="7811865061127547035">"輕觸即可瞭解詳情"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
- <string name="adb_active_notification_message" msgid="4948470599328424059">"輕觸即可停用 USB 偵錯。"</string>
+ <string name="adb_active_notification_message" msgid="4948470599328424059">"輕觸即可停用 USB 偵錯功能。"</string>
<string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"選取以停用 USB 偵錯。"</string>
<string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"正在接收錯誤報告…"</string>
<string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"要分享錯誤報告嗎?"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 04c9fa067d51..4d57f3c9afb1 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -131,7 +131,7 @@
<string name="roamingTextSearching" msgid="8360141885972279963">"Iseshela Isevisi"</string>
<string name="wfcRegErrorTitle" msgid="2301376280632110664">"Ukushaya kwe-Wi-Fi"</string>
<string-array name="wfcOperatorErrorAlertMessages">
- <item msgid="2254967670088539682">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-FI, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le divayisi. Bese uvula ukushaya kwe-Wi-FI futhi kusukela kuzilungiselelo."</item>
+ <item msgid="3910386316304772394">"Ukuze wenze amakholi uphinde uthumele imilayezo nge-Wi-Fi, qala ucele inkampani yakho yenethiwekhi ukuthi isethe le sevisi. Bese uvula ukushaya kwe-Wi-Fi futhi kusukela kuzilungiselelo (Ikhodi yephutha: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
</string-array>
<string-array name="wfcOperatorErrorNotificationMessages">
<item msgid="6177300162212449033">"Bhalisa ngenkampani yakho yenethiwekhi"</item>
@@ -1106,6 +1106,13 @@
<item quantity="one">Vula amanethiwekhi we-Wi-Fi atholakalayo</item>
<item quantity="other">Vula amanethiwekhi we-Wi-Fi atholakalayo</item>
</plurals>
+ <string name="wifi_available_title" msgid="3817100557900599505">"Xhuma kunethiwekhi evulekile ye-Wi‑Fi"</string>
+ <string name="wifi_available_title_connecting" msgid="1557292688310330032">"Ixhuma kunethiwekhi evulekile ye-Wi‑Fi"</string>
+ <string name="wifi_available_title_connected" msgid="7542672851522241548">"Kuxhumeke kunethiwekhi ye-Wi‑Fi"</string>
+ <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"Ayikwazanga ukuxhumeka kunethiwekhi ye-Wi-Fi"</string>
+ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Thepha ukuze ubone onke amanethiwekhi"</string>
+ <string name="wifi_available_action_connect" msgid="2635699628459488788">"Xhuma"</string>
+ <string name="wifi_available_action_all_networks" msgid="1100098935861622985">"Onke amanethiwekhi"</string>
<string name="wifi_available_sign_in" msgid="9157196203958866662">"Ngena ngemvume kunethiwekhi ye-Wi-Fi"</string>
<string name="network_available_sign_in" msgid="1848877297365446605">"Ngena ngemvume kunethiwekhi"</string>
<!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 76cee70fa0e8..d47bde744b88 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2968,6 +2968,8 @@
<!-- Name of a font family to use for headlines. If empty, falls back to platform default -->
<string name="config_headlineFontFamily" translatable="false"></string>
+ <!-- Name of a font family to use for headlines. Defaults to sans-serif-light -->
+ <string name="config_headlineFontFamilyLight" translatable="false">sans-serif-light</string>
<!-- An array of packages that need to be treated as type system in battery settings -->
<string-array translatable="false" name="config_batteryPackageTypeSystem">
@@ -2978,4 +2980,7 @@
<!-- An array of packages that need to be treated as type service in battery settings -->
<string-array translatable="false" name="config_batteryPackageTypeService"/>
+
+ <!-- Show area update info settings in CellBroadcastReceiver and information in SIM status in Settings app -->
+ <bool name="config_showAreaUpdateInfoSettings">false</bool>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 97b6940a1d39..ce701a735816 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -266,7 +266,7 @@
<string name="wfcRegErrorTitle">Wi-Fi Calling</string>
<!-- WFC Operator Error Messages showed as alerts -->
<string-array name="wfcOperatorErrorAlertMessages">
- <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings.</item>
+ <item>To make calls and send messages over Wi-Fi, first ask your carrier to set up this service. Then turn on Wi-Fi calling again from Settings. (Error code: <xliff:g id="code" example="REG09 - No 911 Address">%1$s</xliff:g>)</item>
</string-array>
<!-- WFC Operator Error Messages showed as notifications -->
<string-array name="wfcOperatorErrorNotificationMessages">
@@ -3003,6 +3003,21 @@
<item quantity="other">Open Wi-Fi networks available</item>
</plurals>
+ <!-- Notification title for a nearby open wireless network.-->
+ <string name="wifi_available_title">Connect to open Wi\u2011Fi network</string>
+ <!-- Notification title when the system is connecting to the specified open network. The network name is specified in the notification content. -->
+ <string name="wifi_available_title_connecting">Connecting to open Wi\u2011Fi network</string>
+ <!-- Notification title when the system has connected to the open network. The network name is specified in the notification content. -->
+ <string name="wifi_available_title_connected">Connected to Wi\u2011Fi network</string>
+ <!-- Notification title when the system failed to connect to the specified open network. -->
+ <string name="wifi_available_title_failed_to_connect">Could not connect to Wi\u2011Fi network</string>
+ <!-- Notification content when the system failed to connect to the specified open network. This informs the user that tapping on this notification will open the wifi picker. -->
+ <string name="wifi_available_content_failed_to_connect">Tap to see all networks</string>
+ <!-- Notification action name for connecting to the network specified in the notification body. -->
+ <string name="wifi_available_action_connect">Connect</string>
+ <!-- Notification action name for opening the wifi picker, showing the user all the nearby networks. -->
+ <string name="wifi_available_action_all_networks">All Networks</string>
+
<!-- A notification is shown when a wifi captive portal network is detected. This is the notification's title. -->
<string name="wifi_available_sign_in">Sign in to Wi-Fi network</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 241886c97ec1..1614efbd6b65 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1868,6 +1868,13 @@
<java-symbol type="layout" name="app_error_dialog" />
<java-symbol type="plurals" name="wifi_available" />
<java-symbol type="plurals" name="wifi_available_detailed" />
+ <java-symbol type="string" name="wifi_available_title" />
+ <java-symbol type="string" name="wifi_available_title_connecting" />
+ <java-symbol type="string" name="wifi_available_title_connected" />
+ <java-symbol type="string" name="wifi_available_title_failed_to_connect" />
+ <java-symbol type="string" name="wifi_available_content_failed_to_connect" />
+ <java-symbol type="string" name="wifi_available_action_connect" />
+ <java-symbol type="string" name="wifi_available_action_all_networks" />
<java-symbol type="string" name="accessibility_binding_label" />
<java-symbol type="string" name="adb_active_notification_message" />
<java-symbol type="string" name="adb_active_notification_title" />
@@ -3041,10 +3048,13 @@
<java-symbol type="bool" name="config_dozeAlwaysOnDisplayAvailable" />
<java-symbol type="integer" name="config_storageManagerDaystoRetainDefault" />
<java-symbol type="string" name="config_headlineFontFamily" />
+ <java-symbol type="string" name="config_headlineFontFamilyLight" />
<java-symbol type="drawable" name="stat_sys_vitals" />
+ <java-symbol type="color" name="text_color_primary" />
+
<java-symbol type="array" name="config_batteryPackageTypeSystem" />
<java-symbol type="array" name="config_batteryPackageTypeService" />
-
+ <java-symbol type="bool" name="config_showAreaUpdateInfoSettings" />
</resources>
diff --git a/graphics/java/android/graphics/ColorFilter.java b/graphics/java/android/graphics/ColorFilter.java
index 0ca3729dcc0e..b24b9885d1b0 100644
--- a/graphics/java/android/graphics/ColorFilter.java
+++ b/graphics/java/android/graphics/ColorFilter.java
@@ -14,19 +14,22 @@
* limitations under the License.
*/
-// This file was generated from the C++ include file: SkColorFilter.h
-// Any changes made to this file will be discarded by the build.
-// To change this file, either edit the include, or device/tools/gluemaker/main.cpp,
-// or one of the auxilary file specifications in device/tools/gluemaker.
-
package android.graphics;
+import libcore.util.NativeAllocationRegistry;
+
/**
* A color filter can be used with a {@link Paint} to modify the color of
* each pixel drawn with that paint. This is an abstract class that should
* never be used directly.
*/
public class ColorFilter {
+
+ private static class NoImagePreloadHolder {
+ public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+ ColorFilter.class.getClassLoader(), nativeGetFinalizer(), 50);
+ }
+
/**
* @deprecated Use subclass constructors directly instead.
*/
@@ -34,9 +37,11 @@ public class ColorFilter {
public ColorFilter() {}
/**
- * Holds the pointer to the native SkColorFilter instance.
+ * Current native SkColorFilter instance.
*/
private long mNativeInstance;
+ // Runnable to do immediate destruction
+ private Runnable mCleaner;
long createNativeInstance() {
return 0;
@@ -44,35 +49,28 @@ public class ColorFilter {
void discardNativeInstance() {
if (mNativeInstance != 0) {
- nSafeUnref(mNativeInstance);
+ mCleaner.run();
+ mCleaner = null;
mNativeInstance = 0;
}
}
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mNativeInstance != 0) {
- nSafeUnref(mNativeInstance);
- }
- mNativeInstance = -1;
- } finally {
- super.finalize();
- }
- }
-
/** @hide */
public long getNativeInstance() {
- if (mNativeInstance == -1) {
- throw new IllegalStateException("attempting to use a finalized ColorFilter");
- }
-
if (mNativeInstance == 0) {
mNativeInstance = createNativeInstance();
+
+ if (mNativeInstance != 0) {
+ // Note: we must check for null here, since it's possible for createNativeInstance()
+ // to return nullptr if the native SkColorFilter would be a no-op at draw time.
+ // See native implementations of subclass create methods for more info.
+ mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+ this, mNativeInstance);
+ }
}
return mNativeInstance;
}
- static native void nSafeUnref(long native_instance);
+ private static native long nativeGetFinalizer();
}
diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp
index 4ef0f4bd2712..b073070b58b6 100644
--- a/libs/hwui/OpenGLReadback.cpp
+++ b/libs/hwui/OpenGLReadback.cpp
@@ -133,8 +133,7 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
return CopyResult::DestinationInvalid;
}
- // TODO: Add support for RGBA_F16 destinations
- if (bitmap->colorType() == kRGBA_F16_SkColorType) {
+ if (bitmap->colorType() == kRGBA_F16_SkColorType && !caches.extensions().hasFloatTextures()) {
ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
return CopyResult::DestinationInvalid;
}
@@ -148,24 +147,34 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
GLuint texture;
GLenum format;
+ GLenum internalFormat;
GLenum type;
switch (bitmap->colorType()) {
case kAlpha_8_SkColorType:
format = GL_ALPHA;
+ internalFormat = GL_ALPHA;
type = GL_UNSIGNED_BYTE;
break;
case kRGB_565_SkColorType:
format = GL_RGB;
+ internalFormat = GL_RGB;
type = GL_UNSIGNED_SHORT_5_6_5;
break;
case kARGB_4444_SkColorType:
format = GL_RGBA;
+ internalFormat = GL_RGBA;
type = GL_UNSIGNED_SHORT_4_4_4_4;
break;
+ case kRGBA_F16_SkColorType:
+ format = GL_RGBA;
+ internalFormat = GL_RGBA16F;
+ type = GL_HALF_FLOAT;
+ break;
case kN32_SkColorType:
default:
format = GL_RGBA;
+ internalFormat = GL_RGBA;
type = GL_UNSIGNED_BYTE;
break;
}
@@ -184,7 +193,7 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, format, destWidth, destHeight,
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, destWidth, destHeight,
0, format, type, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture, 0);
@@ -220,6 +229,7 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
ortho.loadOrtho(destWidth, destHeight);
renderState.render(glop, ortho);
+ // TODO: We should convert to linear space when the target is RGBA16F
glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
type, bitmap->getPixels());
}
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index e36ceb8a3e13..f4039889aded 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -194,6 +194,12 @@ public final class AudioAttributes implements Parcelable {
* @see #SUPPRESSIBLE_USAGES
*/
public final static int SUPPRESSIBLE_CALL = 2;
+ /**
+ * @hide
+ * Denotes a usage that is never going to be muted, even in Total Silence.
+ * @see #SUPPRESSIBLE_USAGES
+ */
+ public final static int SUPPRESSIBLE_NEVER = 3;
/**
* @hide
@@ -211,6 +217,8 @@ public final class AudioAttributes implements Parcelable {
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_INSTANT,SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_COMMUNICATION_DELAYED,SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, SUPPRESSIBLE_NOTIFICATION);
+ SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY, SUPPRESSIBLE_NEVER);
+ SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION, SUPPRESSIBLE_NEVER);
}
/**
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 6ef3091dcc70..29fe275777b0 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -424,7 +424,8 @@ public class AudioSystem
DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY |
- DEVICE_OUT_USB_DEVICE);
+ DEVICE_OUT_USB_DEVICE |
+ DEVICE_OUT_USB_HEADSET);
public static final int DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO = (DEVICE_OUT_AUX_LINE |
DEVICE_OUT_HDMI_ARC |
DEVICE_OUT_SPDIF);
@@ -486,7 +487,8 @@ public class AudioSystem
DEVICE_IN_DEFAULT);
public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
- DEVICE_IN_USB_DEVICE);
+ DEVICE_IN_USB_DEVICE |
+ DEVICE_IN_USB_HEADSET);
// device states, must match AudioSystem::device_connection_state
public static final int DEVICE_STATE_UNAVAILABLE = 0;
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index dfd2bb35d6ea..44bd252a349e 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -43,6 +43,7 @@ import android.service.media.MediaBrowserService;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
+import android.view.ViewConfiguration;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -200,8 +201,7 @@ public final class MediaSession {
return;
}
if (mCallback != null) {
- // We're updating the callback, clear the session from the old
- // one.
+ // We're updating the callback, clear the session from the old one.
mCallback.mCallback.mSession = null;
}
if (handler == null) {
@@ -735,6 +735,8 @@ public final class MediaSession {
*/
public abstract static class Callback {
private MediaSession mSession;
+ private CallbackMessageHandler mHandler;
+ private boolean mMediaPlayPauseKeyPending;
public Callback() {
}
@@ -766,13 +768,41 @@ public final class MediaSession {
* @return True if the event was handled, false otherwise.
*/
public boolean onMediaButtonEvent(@NonNull Intent mediaButtonIntent) {
- if (mSession != null
+ if (mSession != null && mHandler != null
&& Intent.ACTION_MEDIA_BUTTON.equals(mediaButtonIntent.getAction())) {
KeyEvent ke = mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (ke != null && ke.getAction() == KeyEvent.ACTION_DOWN) {
PlaybackState state = mSession.mPlaybackState;
long validActions = state == null ? 0 : state.getActions();
switch (ke.getKeyCode()) {
+ case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ if (ke.getRepeatCount() > 0) {
+ // Consider long-press as a single tap.
+ handleMediaPlayPauseKeySingleTapIfPending();
+ } else if (mMediaPlayPauseKeyPending) {
+ // Consider double tap as the next.
+ mHandler.removeMessages(CallbackMessageHandler
+ .MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT);
+ mMediaPlayPauseKeyPending = false;
+ if ((validActions & PlaybackState.ACTION_SKIP_TO_NEXT) != 0) {
+ onSkipToNext();
+ }
+ } else {
+ mMediaPlayPauseKeyPending = true;
+ mHandler.sendEmptyMessageDelayed(CallbackMessageHandler
+ .MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT,
+ ViewConfiguration.getDoubleTapTimeout());
+ }
+ return true;
+ default:
+ // If another key is pressed within double tap timeout, consider the
+ // pending play/pause as a single tap to handle media keys in order.
+ handleMediaPlayPauseKeySingleTapIfPending();
+ break;
+ }
+
+ switch (ke.getKeyCode()) {
case KeyEvent.KEYCODE_MEDIA_PLAY:
if ((validActions & PlaybackState.ACTION_PLAY) != 0) {
onPlay();
@@ -815,28 +845,33 @@ public final class MediaSession {
return true;
}
break;
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- case KeyEvent.KEYCODE_HEADSETHOOK:
- boolean isPlaying = state == null ? false
- : state.getState() == PlaybackState.STATE_PLAYING;
- boolean canPlay = (validActions & (PlaybackState.ACTION_PLAY_PAUSE
- | PlaybackState.ACTION_PLAY)) != 0;
- boolean canPause = (validActions & (PlaybackState.ACTION_PLAY_PAUSE
- | PlaybackState.ACTION_PAUSE)) != 0;
- if (isPlaying && canPause) {
- onPause();
- return true;
- } else if (!isPlaying && canPlay) {
- onPlay();
- return true;
- }
- break;
}
}
}
return false;
}
+ private void handleMediaPlayPauseKeySingleTapIfPending() {
+ if (!mMediaPlayPauseKeyPending) {
+ return;
+ }
+ mMediaPlayPauseKeyPending = false;
+ mHandler.removeMessages(CallbackMessageHandler.MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT);
+ PlaybackState state = mSession.mPlaybackState;
+ long validActions = state == null ? 0 : state.getActions();
+ boolean isPlaying = state != null
+ && state.getState() == PlaybackState.STATE_PLAYING;
+ boolean canPlay = (validActions & (PlaybackState.ACTION_PLAY_PAUSE
+ | PlaybackState.ACTION_PLAY)) != 0;
+ boolean canPause = (validActions & (PlaybackState.ACTION_PLAY_PAUSE
+ | PlaybackState.ACTION_PAUSE)) != 0;
+ if (isPlaying && canPause) {
+ onPause();
+ } else if (!isPlaying && canPlay) {
+ onPlay();
+ }
+ }
+
/**
* Override to handle requests to prepare playback. During the preparation, a session should
* not hold audio focus in order to allow other sessions play seamlessly. The state of
@@ -1294,12 +1329,14 @@ public final class MediaSession {
private static final int MSG_CUSTOM_ACTION = 20;
private static final int MSG_ADJUST_VOLUME = 21;
private static final int MSG_SET_VOLUME = 22;
+ private static final int MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT = 23;
private MediaSession.Callback mCallback;
public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) {
super(looper, null, true);
mCallback = callback;
+ mCallback.mHandler = this;
}
public void post(int what, Object obj, Bundle bundle) {
@@ -1401,6 +1438,9 @@ public final class MediaSession {
vp.onSetVolumeTo((int) msg.obj);
}
break;
+ case MSG_PLAY_PAUSE_KEY_DOUBLE_TAP_TIMEOUT:
+ mCallback.handleMediaPlayPauseKeySingleTapIfPending();
+ break;
}
}
}
diff --git a/media/jni/soundpool/SoundPoolThread.cpp b/media/jni/soundpool/SoundPoolThread.cpp
index 3d988773ff04..ba3b482935dd 100644
--- a/media/jni/soundpool/SoundPoolThread.cpp
+++ b/media/jni/soundpool/SoundPoolThread.cpp
@@ -20,8 +20,6 @@
#include "SoundPoolThread.h"
-static const int kMaxWorkers = 3;
-
namespace android {
void SoundPoolThread::write(SoundPoolMsg msg) {
@@ -33,21 +31,14 @@ void SoundPoolThread::write(SoundPoolMsg msg) {
// if thread is quitting, don't add to queue
if (mRunning) {
mMsgQueue.push(msg);
- if (mNumWorkers < kMaxWorkers) {
- if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
- mNumWorkers++;
- ALOGV("created worker thread");
- }
- }
+ mCondition.signal();
}
}
const SoundPoolMsg SoundPoolThread::read() {
Mutex::Autolock lock(&mLock);
- if (mMsgQueue.size() == 0) {
- mNumWorkers--;
- mCondition.signal();
- return SoundPoolMsg(SoundPoolMsg::KILL, 0);
+ while (mMsgQueue.size() == 0) {
+ mCondition.wait(mLock);
}
SoundPoolMsg msg = mMsgQueue[0];
mMsgQueue.removeAt(0);
@@ -60,20 +51,20 @@ void SoundPoolThread::quit() {
if (mRunning) {
mRunning = false;
mMsgQueue.clear();
- mCondition.broadcast(); // wake up any blocked writers
- while (mNumWorkers > 0) {
- mCondition.wait(mLock);
- }
+ mMsgQueue.push(SoundPoolMsg(SoundPoolMsg::KILL, 0));
+ mCondition.signal();
+ mCondition.wait(mLock);
}
ALOGV("return from quit");
}
SoundPoolThread::SoundPoolThread(SoundPool* soundPool) :
- mSoundPool(soundPool),
- mNumWorkers(0),
- mRunning(true)
+ mSoundPool(soundPool)
{
mMsgQueue.setCapacity(maxMessages);
+ if (createThreadEtc(beginThread, this, "SoundPoolThread")) {
+ mRunning = true;
+ }
}
SoundPoolThread::~SoundPoolThread()
diff --git a/media/jni/soundpool/SoundPoolThread.h b/media/jni/soundpool/SoundPoolThread.h
index 5d7bf0c07803..7b3e1dda0a23 100644
--- a/media/jni/soundpool/SoundPoolThread.h
+++ b/media/jni/soundpool/SoundPoolThread.h
@@ -58,7 +58,6 @@ private:
Condition mCondition;
Vector<SoundPoolMsg> mMsgQueue;
SoundPool* mSoundPool;
- int32_t mNumWorkers;
bool mRunning;
};
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 22f53eabb99b..a487632b92f3 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -57,6 +57,7 @@ import java.lang.InterruptedException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Random;
+import java.util.concurrent.atomic.AtomicBoolean;
public class CaptivePortalLoginActivity extends Activity {
private static final String TAG = CaptivePortalLoginActivity.class.getSimpleName();
@@ -82,6 +83,8 @@ public class CaptivePortalLoginActivity extends Activity {
private ConnectivityManager mCm;
private boolean mLaunchBrowser = false;
private MyWebViewClient mWebViewClient;
+ // Ensures that done() happens once exactly, handling concurrent callers with atomic operations.
+ private final AtomicBoolean isDone = new AtomicBoolean(false);
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -178,13 +181,13 @@ public class CaptivePortalLoginActivity extends Activity {
}
private void done(Result result) {
+ if (isDone.getAndSet(true)) {
+ // isDone was already true: done() already called
+ return;
+ }
if (DBG) {
Log.d(TAG, String.format("Result %s for %s", result.name(), mUrl.toString()));
}
- if (mNetworkCallback != null) {
- mCm.unregisterNetworkCallback(mNetworkCallback);
- mNetworkCallback = null;
- }
logMetricsEvent(result.metricsEvent);
switch (result) {
case DISMISSED:
@@ -244,8 +247,8 @@ public class CaptivePortalLoginActivity extends Activity {
public void onDestroy() {
super.onDestroy();
if (mNetworkCallback != null) {
+ // mNetworkCallback is not null if mUrl is not null.
mCm.unregisterNetworkCallback(mNetworkCallback);
- mNetworkCallback = null;
}
if (mLaunchBrowser) {
// Give time for this network to become default. After 500ms just proceed.
@@ -374,6 +377,9 @@ public class CaptivePortalLoginActivity extends Activity {
return;
} else if (mPagesLoaded == 2) {
// Prevent going back to empty first page.
+ // Fix for missing focus, see b/62449959 for details. Remove it once we get a
+ // newer version of WebView (60.x.y).
+ view.requestFocus();
view.clearHistory();
}
testForCaptivePortal();
diff --git a/packages/SystemUI/res/drawable/ic_mode_edit.xml b/packages/SettingsLib/res/drawable/ic_mode_edit.xml
index 2ad31195ca57..2ad31195ca57 100644
--- a/packages/SystemUI/res/drawable/ic_mode_edit.xml
+++ b/packages/SettingsLib/res/drawable/ic_mode_edit.xml
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index b4c8cec2d698..438cbbbb16fe 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -376,6 +376,6 @@
<string name="active_input_method_subtypes" msgid="3596398805424733238">"Mètodes d\'introducció actius"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Utilitza els idiomes del sistema"</string>
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"No s\'ha pogut obrir la configuració de: <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g>"</string>
- <string name="ime_security_warning" msgid="4135828934735934248">"Pot ser que aquest mètode d\'entrada pugui recopilar tot el que escriviu, incloses dades personals, com ara contrasenyes i números de targetes de crèdit. Ve de l\'aplicació <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Voleu utilitzar aquest mètode d\'entrada?"</string>
+ <string name="ime_security_warning" msgid="4135828934735934248">"Pot ser que aquest mètode d\'introducció pugui recopilar tot el que escriviu, incloses dades personals, com ara contrasenyes i números de targetes de crèdit. Ve de l\'aplicació <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g>. Voleu utilitzar aquest mètode d\'introducció?"</string>
<string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"Nota: després de reiniciar, l\'aplicació no s\'iniciarà fins que no desbloquegis el telèfon"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 0484645cbcb4..7f2d85ac6384 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -110,7 +110,7 @@
<string name="unknown" msgid="1592123443519355854">"Sconosciuta"</string>
<string name="running_process_item_user_label" msgid="3129887865552025943">"Utente: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="313159469856372621">"Alcune opzioni predefinite impostate"</string>
- <string name="launch_defaults_none" msgid="4241129108140034876">"Nessuna app predefinita impostata"</string>
+ <string name="launch_defaults_none" msgid="4241129108140034876">"Nessuna impostazione predefinita"</string>
<string name="tts_settings" msgid="8186971894801348327">"Impostazioni di sintesi vocale"</string>
<string name="tts_settings_title" msgid="1237820681016639683">"Output sintesi vocale"</string>
<string name="tts_default_rate_title" msgid="6030550998379310088">"Velocità voce"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 09dae27da47f..eb20fdc5ad60 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -86,7 +86,7 @@
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"페어링"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"페어링"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"취소"</string>
- <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"페어링하면 연결 시 주소록 및 통화 기록에 액세스할 수 있습니다."</string>
+ <string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"페어링하면 연결 시 연락처 및 통화 기록에 액세스할 수 있습니다."</string>
<string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>와(과) 페어링하지 못했습니다."</string>
<string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"PIN 또는 패스키가 잘못되어 <xliff:g id="DEVICE_NAME">%1$s</xliff:g>와(과) 페어링하지 못했습니다."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>와(과) 통신할 수 없습니다."</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index f9d193058306..675a6d09ebea 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -90,7 +90,7 @@
<string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Não foi possível parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Não foi possível parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g> por causa de um PIN ou senha incorretos."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Não é possível se comunicar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
- <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Emparelhamento rejeitado por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Pareamento rejeitado por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi desligado."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi desconectado"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Uma barra de Wi-Fi."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index f9d193058306..675a6d09ebea 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -90,7 +90,7 @@
<string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Não foi possível parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Não foi possível parear com <xliff:g id="DEVICE_NAME">%1$s</xliff:g> por causa de um PIN ou senha incorretos."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Não é possível se comunicar com <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
- <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Emparelhamento rejeitado por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
+ <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Pareamento rejeitado por <xliff:g id="DEVICE_NAME">%1$s</xliff:g>."</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi desligado."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Wi-Fi desconectado"</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Uma barra de Wi-Fi."</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 61f280cab7f6..ff6c838536e0 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -59,7 +59,7 @@
<string name="bluetooth_profile_headset" msgid="7815495680863246034">"Звонки"</string>
<string name="bluetooth_profile_opp" msgid="9168139293654233697">"Профиль OPP"</string>
<string name="bluetooth_profile_hid" msgid="3680729023366986480">"Профиль HID"</string>
- <string name="bluetooth_profile_pan" msgid="3391606497945147673">"Интернет-доступ"</string>
+ <string name="bluetooth_profile_pan" msgid="3391606497945147673">"Доступ к Интернету"</string>
<string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Обмен контактами"</string>
<string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"Использовать для обмена контактами"</string>
<string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"Профиль PAN"</string>
@@ -83,12 +83,12 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Использовать для аудиоустройства телефона"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Используется для передачи файлов"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Использовать для ввода"</string>
- <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Подключить"</string>
- <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ПОДКЛЮЧИТЬ"</string>
+ <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Добавить"</string>
+ <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ДОБАВИТЬ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Отмена"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Сопряжение обеспечивает доступ к вашим контактам и журналу звонков при подключении."</string>
- <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Не удалось подключиться к устройству \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Не удалось подключиться к устройству \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\", так как введен неверный PIN-код или пароль."</string>
+ <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"Не удалось установить сопряжение с устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"Не удалось установить сопряжение с устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\", так как введен неверный PIN-код или пароль."</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"Не удается установить соединение с устройством \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\"."</string>
<string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> не разрешает сопряжение."</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Wi-Fi выключен"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 7e2e7d5a93f0..8ceb1d8c630b 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -50,7 +50,7 @@
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Bağlantı kesiliyor…"</string>
<string name="bluetooth_connecting" msgid="8555009514614320497">"Bağlanıyor…"</string>
<string name="bluetooth_connected" msgid="6038755206916626419">"Bağlandı"</string>
- <string name="bluetooth_pairing" msgid="1426882272690346242">"Eşleştiriliyor…"</string>
+ <string name="bluetooth_pairing" msgid="1426882272690346242">"Eşleniyor…"</string>
<string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"Bağlandı (telefon yok)"</string>
<string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"Bağlandı (medya yok)"</string>
<string name="bluetooth_connected_no_map" msgid="6504436917057479986">"Bağlı (mesaj erişimi yok)"</string>
@@ -83,14 +83,14 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Telefon sesi için kullan"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Dosya aktarımı için kullan"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Giriş için kullan"</string>
- <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Eşleştir"</string>
- <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"EŞLEŞTİR"</string>
+ <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Eşle"</string>
+ <string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"EŞLE"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"İptal"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="4982239145676394429">"Eşleme işlemi, bağlantı kurulduğunda kişilerinize ve çağrı geçmişine erişim izni verir."</string>
- <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ile eşleştirilemedi."</string>
- <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"PIN veya parola yanlış olduğundan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ile eşleştirilemedi"</string>
+ <string name="bluetooth_pairing_error_message" msgid="3748157733635947087">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ile eşlenemedi."</string>
+ <string name="bluetooth_pairing_pin_error_message" msgid="8337234855188925274">"PIN veya parola yanlış olduğundan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ile eşlenemedi"</string>
<string name="bluetooth_pairing_device_down_error_message" msgid="7870998403045801381">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ile iletişim kurulamıyor."</string>
- <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Eşleştirme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> tarafından reddedildi."</string>
+ <string name="bluetooth_pairing_rejected_error_message" msgid="1648157108520832454">"Eşleme <xliff:g id="DEVICE_NAME">%1$s</xliff:g> tarafından reddedildi."</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Kablosuz kapalı."</string>
<string name="accessibility_no_wifi" msgid="8834610636137374508">"Kablosuz bağlantı kesildi."</string>
<string name="accessibility_wifi_one_bar" msgid="4869376278894301820">"Kablosuz sinyal gücü tek çubuk."</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java b/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java
new file mode 100644
index 000000000000..9554e8128122
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/CustomDialogPreference.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.v14.preference.PreferenceDialogFragment;
+import android.support.v7.preference.DialogPreference;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class CustomDialogPreference extends DialogPreference {
+
+ private CustomPreferenceDialogFragment mFragment;
+
+ public CustomDialogPreference(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public CustomDialogPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public CustomDialogPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CustomDialogPreference(Context context) {
+ super(context);
+ }
+
+ public boolean isDialogOpen() {
+ return getDialog() != null && getDialog().isShowing();
+ }
+
+ public Dialog getDialog() {
+ return mFragment != null ? mFragment.getDialog() : null;
+ }
+
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
+ DialogInterface.OnClickListener listener) {
+ }
+
+ protected void onDialogClosed(boolean positiveResult) {
+ }
+
+ protected void onClick(DialogInterface dialog, int which) {
+ }
+
+ protected void onBindDialogView(View view) {
+ }
+
+ private void setFragment(CustomPreferenceDialogFragment fragment) {
+ mFragment = fragment;
+ }
+
+ public static class CustomPreferenceDialogFragment extends PreferenceDialogFragment {
+
+ public static CustomPreferenceDialogFragment newInstance(String key) {
+ final CustomPreferenceDialogFragment fragment = new CustomPreferenceDialogFragment();
+ final Bundle b = new Bundle(1);
+ b.putString(ARG_KEY, key);
+ fragment.setArguments(b);
+ return fragment;
+ }
+
+ private CustomDialogPreference getCustomizablePreference() {
+ return (CustomDialogPreference) getPreference();
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ super.onPrepareDialogBuilder(builder);
+ getCustomizablePreference().setFragment(this);
+ getCustomizablePreference().onPrepareDialogBuilder(builder, this);
+ }
+
+ @Override
+ public void onDialogClosed(boolean positiveResult) {
+ getCustomizablePreference().onDialogClosed(positiveResult);
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+ getCustomizablePreference().onBindDialogView(view);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ super.onClick(dialog, which);
+ getCustomizablePreference().onClick(dialog, which);
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java b/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java
new file mode 100644
index 000000000000..692d2110e498
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/CustomEditTextPreference.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.v14.preference.EditTextPreferenceDialogFragment;
+import android.support.v7.preference.EditTextPreference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.EditText;
+
+public class CustomEditTextPreference extends EditTextPreference {
+
+ private CustomPreferenceDialogFragment mFragment;
+
+ public CustomEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public CustomEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public CustomEditTextPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public CustomEditTextPreference(Context context) {
+ super(context);
+ }
+
+ public EditText getEditText() {
+ return mFragment != null ? (EditText) mFragment.getDialog().findViewById(android.R.id.edit)
+ : null;
+ }
+
+ public boolean isDialogOpen() {
+ return getDialog() != null && getDialog().isShowing();
+ }
+
+ public Dialog getDialog() {
+ return mFragment != null ? mFragment.getDialog() : null;
+ }
+
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
+ DialogInterface.OnClickListener listener) {
+ }
+
+ protected void onDialogClosed(boolean positiveResult) {
+ }
+
+ protected void onClick(DialogInterface dialog, int which) {
+ }
+
+ protected void onBindDialogView(View view) {
+ }
+
+ private void setFragment(CustomPreferenceDialogFragment fragment) {
+ mFragment = fragment;
+ }
+
+ public static class CustomPreferenceDialogFragment extends EditTextPreferenceDialogFragment {
+
+ public static CustomPreferenceDialogFragment newInstance(String key) {
+ final CustomPreferenceDialogFragment fragment = new CustomPreferenceDialogFragment();
+ final Bundle b = new Bundle(1);
+ b.putString(ARG_KEY, key);
+ fragment.setArguments(b);
+ return fragment;
+ }
+
+ private CustomEditTextPreference getCustomizablePreference() {
+ return (CustomEditTextPreference) getPreference();
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+ getCustomizablePreference().onBindDialogView(view);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ super.onPrepareDialogBuilder(builder);
+ getCustomizablePreference().setFragment(this);
+ getCustomizablePreference().onPrepareDialogBuilder(builder, this);
+ }
+
+ @Override
+ public void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+ getCustomizablePreference().onDialogClosed(positiveResult);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ super.onClick(dialog, which);
+ getCustomizablePreference().onClick(dialog, which);
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
index b06b0328f8fd..7357fe63d9b0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
@@ -107,4 +107,20 @@ public class AppUtils {
return false;
}
+ /** Returns the label for a given package. */
+ public static CharSequence getApplicationLabel(
+ PackageManager packageManager, String packageName) {
+ try {
+ final ApplicationInfo appInfo =
+ packageManager.getApplicationInfo(
+ packageName,
+ PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_ANY_USER);
+ return appInfo.loadLabel(packageManager);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Unable to find info for package: " + packageName);
+ }
+ return null;
+ }
+
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
index a8f6f025b6d5..8fc9fa6a4f26 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
@@ -54,6 +54,10 @@ public class StorageStatsSource {
mStorageStatsManager.queryStatsForPackage(volumeUuid, packageName, user));
}
+ public long getCacheQuotaBytes(String volumeUuid, int uid) {
+ return mStorageStatsManager.getCacheQuotaBytes(volumeUuid, uid);
+ }
+
/**
* Static class that provides methods for querying the amount of external storage available as
* well as breaking it up into several media types.
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
index 5a1e603e7fa2..f1d43bfe4096 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
@@ -51,6 +51,12 @@ public class Tile implements Parcelable {
public Icon icon;
/**
+ * Whether the icon can be tinted. This should be set to true for monochrome (single-color)
+ * icons that can be tinted to match the design.
+ */
+ public boolean isIconTintable;
+
+ /**
* Intent to launch when the preference is selected.
*/
public Intent intent;
@@ -126,6 +132,7 @@ public class Tile implements Parcelable {
dest.writeBundle(metaData);
dest.writeString(key);
dest.writeParcelable(remoteViews, flags);
+ dest.writeBoolean(isIconTintable);
}
public void readFromParcel(Parcel in) {
@@ -147,6 +154,7 @@ public class Tile implements Parcelable {
metaData = in.readBundle();
key = in.readString();
remoteViews = in.readParcelable(RemoteViews.class.getClassLoader());
+ isIconTintable = in.readBoolean();
}
Tile(Parcel in) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 04a3d1f81561..9620a9153f80 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -133,15 +133,25 @@ public class TileUtils {
/**
* Name of the meta-data item that should be set in the AndroidManifest.xml
- * to specify the title that should be displayed for the preference.
+ * to specify whether the icon is tintable. This should be a boolean value {@code true} or
+ * {@code false}, set using {@code android:value}
*/
- @Deprecated
- public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";
+ public static final String META_DATA_PREFERENCE_ICON_TINTABLE =
+ "com.android.settings.icon_tintable";
/**
* Name of the meta-data item that should be set in the AndroidManifest.xml
* to specify the title that should be displayed for the preference.
+ *
+ * <p>Note: It is preferred to provide this value using {@code android:resource} with a string
+ * resource for localization.
+ */
+ public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";
+
+ /**
+ * @deprecated Use {@link #META_DATA_PREFERENCE_TITLE} with {@code android:resource}
*/
+ @Deprecated
public static final String META_DATA_PREFERENCE_TITLE_RES_ID =
"com.android.settings.title.resid";
@@ -309,12 +319,13 @@ public class TileUtils {
intent.setPackage(settingPkg);
}
getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles,
- usePriority, true);
+ usePriority, true, true);
}
- public static void getTilesForIntent(Context context, UserHandle user, Intent intent,
+ public static void getTilesForIntent(
+ Context context, UserHandle user, Intent intent,
Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles,
- boolean usePriority, boolean checkCategory) {
+ boolean usePriority, boolean checkCategory, boolean forceTintExternalIcon) {
PackageManager pm = context.getPackageManager();
List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent,
PackageManager.GET_META_DATA, user.getIdentifier());
@@ -350,7 +361,7 @@ public class TileUtils {
tile.priority = usePriority ? resolved.priority : 0;
tile.metaData = activityInfo.metaData;
updateTileData(context, tile, activityInfo, activityInfo.applicationInfo,
- pm, providerMap);
+ pm, providerMap, forceTintExternalIcon);
if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title);
addedCache.put(key, tile);
@@ -366,25 +377,40 @@ public class TileUtils {
private static boolean updateTileData(Context context, Tile tile,
ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm,
- Map<String, IContentProvider> providerMap) {
+ Map<String, IContentProvider> providerMap, boolean forceTintExternalIcon) {
if (applicationInfo.isSystemApp()) {
+ boolean forceTintIcon = false;
int icon = 0;
Pair<String, Integer> iconFromUri = null;
CharSequence title = null;
String summary = null;
String keyHint = null;
+ boolean isIconTintable = false;
RemoteViews remoteViews = null;
// Get the activity's meta-data
try {
- Resources res = pm.getResourcesForApplication(
- applicationInfo.packageName);
+ Resources res = pm.getResourcesForApplication(applicationInfo.packageName);
Bundle metaData = activityInfo.metaData;
+ if (forceTintExternalIcon
+ && !context.getPackageName().equals(applicationInfo.packageName)) {
+ isIconTintable = true;
+ forceTintIcon = true;
+ }
+
if (res != null && metaData != null) {
if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
icon = metaData.getInt(META_DATA_PREFERENCE_ICON);
}
+ if (metaData.containsKey(META_DATA_PREFERENCE_ICON_TINTABLE)) {
+ if (forceTintIcon) {
+ Log.w(LOG_TAG, "Ignoring icon tintable for " + activityInfo);
+ } else {
+ isIconTintable =
+ metaData.getBoolean(META_DATA_PREFERENCE_ICON_TINTABLE);
+ }
+ }
int resId = 0;
if (metaData.containsKey(META_DATA_PREFERENCE_TITLE_RES_ID)) {
resId = metaData.getInt(META_DATA_PREFERENCE_TITLE_RES_ID);
@@ -392,8 +418,6 @@ public class TileUtils {
title = res.getString(resId);
}
}
- // Fallback to legacy title extraction if we couldn't get the title through
- // res id.
if ((resId == 0) && metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
if (metaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) {
title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
@@ -457,6 +481,7 @@ public class TileUtils {
activityInfo.name);
// Suggest a key for this tile
tile.key = keyHint;
+ tile.isIconTintable = isIconTintable;
tile.remoteViews = remoteViews;
return true;
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index 1bb141706736..924a82f0b1f4 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -28,6 +28,7 @@ import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Path.FillType;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
@@ -82,6 +83,7 @@ public class BatteryMeterDrawableBase extends Drawable {
private final float[] mPlusPoints;
private final Path mPlusPath = new Path();
+ private final Rect mPadding = new Rect();
private final RectF mFrame = new RectF();
private final RectF mButtonFrame = new RectF();
private final RectF mBoltFrame = new RectF();
@@ -219,12 +221,40 @@ public class BatteryMeterDrawableBase extends Drawable {
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
- mHeight = bottom - top;
- mWidth = right - left;
+ updateSize();
+ }
+
+ private void updateSize() {
+ final Rect bounds = getBounds();
+
+ mHeight = (bounds.bottom - mPadding.bottom) - (bounds.top + mPadding.top);
+ mWidth = (bounds.right - mPadding.right) - (bounds.left + mPadding.left);
mWarningTextPaint.setTextSize(mHeight * 0.75f);
mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
}
+ @Override
+ public boolean getPadding(Rect padding) {
+ if (mPadding.left == 0
+ && mPadding.top == 0
+ && mPadding.right == 0
+ && mPadding.bottom == 0) {
+ return super.getPadding(padding);
+ }
+
+ padding.set(mPadding);
+ return true;
+ }
+
+ public void setPadding(int left, int top, int right, int bottom) {
+ mPadding.left = left;
+ mPadding.top = top;
+ mPadding.right = right;
+ mPadding.bottom = bottom;
+
+ updateSize();
+ }
+
private int getColorForLevel(int percent) {
// If we are in power save mode, always use the normal color.
if (mPowerSaveEnabled) {
@@ -255,6 +285,10 @@ public class BatteryMeterDrawableBase extends Drawable {
invalidateSelf();
}
+ protected int batteryColorForLevel(int level) {
+ return mCharging ? mChargeColor : getColorForLevel(level);
+ }
+
@Override
public void draw(Canvas c) {
final int level = mLevel;
@@ -264,11 +298,10 @@ public class BatteryMeterDrawableBase extends Drawable {
float drawFrac = (float) level / 100f;
final int height = mHeight;
final int width = (int) (ASPECT_RATIO * mHeight);
- int px = (mWidth - width) / 2;
-
+ final int px = (mWidth - width) / 2;
final int buttonHeight = Math.round(height * mButtonHeightFraction);
- mFrame.set(0, 0, width, height);
+ mFrame.set(mPadding.left, mPadding.top, width + mPadding.left, height + mPadding.top);
mFrame.offset(px, 0);
// button-frame: area above the battery body
@@ -282,7 +315,7 @@ public class BatteryMeterDrawableBase extends Drawable {
mFrame.top += buttonHeight;
// set the battery charging color
- mBatteryPaint.setColor(mCharging ? mChargeColor : getColorForLevel(level));
+ mBatteryPaint.setColor(batteryColorForLevel(level));
if (level >= FULL) {
drawFrac = 1f;
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
index a28bece100eb..167ffe61e42b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
@@ -208,7 +208,7 @@ public class SuggestionParser {
intent.setPackage(category.pkg);
}
TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
- mAddCache, null, suggestions, true, false);
+ mAddCache, null, suggestions, true, false, false);
filterSuggestions(suggestions, countBefore, isSmartSuggestionEnabled);
if (!category.multiple && suggestions.size() > (countBefore + 1)) {
// If there are too many, remove them all and only re-add the one with the highest
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index edb322680c69..d45ed1922aa4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -703,6 +703,9 @@ public class AccessPoint implements Comparable<AccessPoint> {
case WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE:
summary.append(mContext.getString(R.string.wifi_disabled_password_failure));
break;
+ case WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD:
+ summary.append(mContext.getString(R.string.wifi_check_password_try_again));
+ break;
case WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE:
case WifiConfiguration.NetworkSelectionStatus.DISABLED_DNS_FAILURE:
summary.append(mContext.getString(R.string.wifi_disabled_network_failure));
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
index 83667ea00629..aa92fa40a91b 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -3,6 +3,7 @@ package com.android.settingslib.graph;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Rect;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -68,4 +69,36 @@ public class BatteryMeterDrawableBaseTest {
}
}
}
+
+ @Test
+ public void testPadding_returnsCorrectValues() {
+ // different pads on each side to differentiate
+ final int left = 1;
+ final int top = 2;
+ final int right = 3;
+ final int bottom = 4;
+
+ final Rect expected = new Rect(left, top, right, bottom);
+ final Rect padding = new Rect();
+
+ mBatteryDrawable.setPadding(left, top, right, bottom);
+
+ assertThat(mBatteryDrawable.getPadding(padding)).isEqualTo(true);
+ assertThat(padding).isEqualTo(expected);
+ }
+
+ @Test
+ public void testPadding_falseIfUnsetOrZero() {
+ final Rect padding = new Rect();
+ assertThat(mBatteryDrawable.getPadding(padding)).isEqualTo(false);
+ assertThat(isRectZero(padding)).isEqualTo(true);
+
+ mBatteryDrawable.setPadding(0, 0, 0, 0);
+ assertThat(mBatteryDrawable.getPadding(padding)).isEqualTo(false);
+ assertThat(isRectZero(padding)).isEqualTo(true);
+ }
+
+ private boolean isRectZero(Rect r) {
+ return r.left == 0 && r.top == 0 && r.right == 0 && r.bottom == 0;
+ }
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 72ac54421220..89328ee47f1c 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -417,6 +417,19 @@ public class AccessPointTest {
assertThat(ap.getSummary()).isEqualTo(expectedString);
}
+ @Test
+ public void testSummaryString_showsWrongPasswordLabel() {
+ WifiConfiguration configuration = createWifiConfiguration();
+ configuration.getNetworkSelectionStatus().setNetworkSelectionStatus(
+ WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED);
+ configuration.getNetworkSelectionStatus().setNetworkSelectionDisableReason(
+ WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD);
+ AccessPoint ap = new AccessPoint(mContext, configuration);
+
+ assertThat(ap.getSummary()).isEqualTo(mContext.getString(
+ R.string.wifi_check_password_try_again));
+ }
+
private ScoredNetwork buildScoredNetworkWithMockBadgeCurve() {
Bundle attr1 = new Bundle();
attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, mockBadgeCurve);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
index 22fd83c67667..31abecda9a39 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TestConfig.java
@@ -19,5 +19,5 @@ package com.android.settingslib;
public class TestConfig {
public static final int SDK_VERSION = 23;
public static final String MANIFEST_PATH =
- "frameworks/base/packages/SettingsLib/robotests/AndroidManifest.xml";
+ "frameworks/base/packages/SettingsLib/tests/robotests/AndroidManifest.xml";
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 7cfb32d7bdb0..036441839b5b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -16,6 +16,19 @@
package com.android.settingslib.drawer;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.RuntimeEnvironment.application;
+
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -50,8 +63,9 @@ import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
import org.robolectric.internal.ShadowExtractor;
import java.util.ArrayList;
@@ -59,20 +73,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-
@RunWith(RobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
@@ -100,8 +100,11 @@ public class TileUtilsTest {
MockitoAnnotations.initMocks(this);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getResourcesForApplication(anyString())).thenReturn(mResources);
- mContentResolver = spy(RuntimeEnvironment.application.getContentResolver());
+ when(mPackageManager.getApplicationInfo(eq("abc"), anyInt()))
+ .thenReturn(application.getApplicationInfo());
+ mContentResolver = spy(application.getContentResolver());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getPackageName()).thenReturn("com.android.settings");
}
@Test
@@ -118,7 +121,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).category).isEqualTo(testCategory);
@@ -139,7 +142,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).key).isEqualTo(keyHint);
@@ -159,7 +162,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.isEmpty()).isTrue();
}
@@ -182,7 +185,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
SuggestionParser parser = new SuggestionParser(
@@ -255,7 +258,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).title).isEqualTo("my title");
@@ -279,10 +282,60 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).title).isEqualTo("my localized title");
+
+ // Icon should be tintable because the tile is not from settings package, and
+ // "forceTintExternalIcon" is set
+ assertThat(outTiles.get(0).isIconTintable).isTrue();
+ }
+
+ @Test
+ public void getTilesForIntent_shouldNotTintIconIfInSettingsPackage() {
+ Intent intent = new Intent();
+ Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+ List<Tile> outTiles = new ArrayList<>();
+ List<ResolveInfo> info = new ArrayList<>();
+ ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+ URI_GET_SUMMARY, null, 123);
+ resolveInfo.activityInfo.packageName = "com.android.settings";
+ resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
+ info.add(resolveInfo);
+
+ when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+ .thenReturn(info);
+
+ TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+ null /* defaultCategory */, outTiles, false /* usePriority */,
+ false /* checkCategory */, true /* forceTintExternalIcon */);
+
+ assertThat(outTiles.size()).isEqualTo(1);
+ assertThat(outTiles.get(0).isIconTintable).isFalse();
+ }
+
+ @Test
+ public void getTilesForIntent_shouldMarkIconTintableIfMetadataSet() {
+ Intent intent = new Intent();
+ Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+ List<Tile> outTiles = new ArrayList<>();
+ List<ResolveInfo> info = new ArrayList<>();
+ ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+ URI_GET_SUMMARY, null, 123);
+ resolveInfo.activityInfo.metaData
+ .putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, true);
+ info.add(resolveInfo);
+
+ when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+ .thenReturn(info);
+
+ TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+ null /* defaultCategory */, outTiles, false /* usePriority */,
+ false /* checkCategory */, false /* forceTintExternalIcon */);
+
+ assertThat(outTiles.size()).isEqualTo(1);
+ assertThat(outTiles.get(0).isIconTintable).isTrue();
}
@Test
@@ -301,7 +354,7 @@ public class TileUtilsTest {
// Case 1: No provider associated with the uri specified.
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).icon.getResId()).isEqualTo(314159);
@@ -319,7 +372,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
assertThat(outTiles.get(0).icon.getResId()).isEqualTo(314159);
@@ -341,7 +394,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
}
@@ -362,7 +415,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
Tile tile = outTiles.get(0);
@@ -399,7 +452,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
Tile tile = outTiles.get(0);
@@ -437,7 +490,7 @@ public class TileUtilsTest {
TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */);
+ false /* checkCategory */, true /* forceTintExternalIcon */);
assertThat(outTiles.size()).isEqualTo(1);
Tile tile = outTiles.get(0);
@@ -484,7 +537,9 @@ public class TileUtilsTest {
if (summaryUri != null) {
info.activityInfo.metaData.putString("com.android.settings.summary_uri", summaryUri);
}
- if (title != null) {
+ if (titleResId != 0) {
+ info.activityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_TITLE, title);
+ } else if (title != null) {
info.activityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_TITLE, title);
}
if (titleResId != 0) {
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java
index 81bc83134b21..f59c4a56bf3b 100644
--- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java
+++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java
@@ -29,6 +29,7 @@ import android.util.Range;
import com.google.android.colorextraction.ColorExtractor.GradientColors;
+import java.util.Arrays;
import java.util.List;
/**
@@ -101,7 +102,7 @@ public class Tonal implements ExtractionType {
hsl[0] /= 360f;
// Find the palette that contains the closest color
- TonalPalette palette = findTonalPalette(hsl[0]);
+ TonalPalette palette = findTonalPalette(hsl[0], hsl[1]);
if (palette == null) {
Log.w(TAG, "Could not find a tonal palette!");
return false;
@@ -251,7 +252,13 @@ public class Tonal implements ExtractionType {
}
@Nullable
- private static TonalPalette findTonalPalette(float h) {
+ private static TonalPalette findTonalPalette(float h, float s) {
+ // Fallback to a grey palette if the color is too desaturated.
+ // This avoids hue shifts.
+ if (s < 0.05f) {
+ return GREY_PALETTE;
+ }
+
TonalPalette best = null;
float error = Float.POSITIVE_INFINITY;
@@ -305,6 +312,12 @@ public class Tonal implements ExtractionType {
final float maxHue;
TonalPalette(float[] h, float[] s, float[] l) {
+ if (h.length != s.length || s.length != l.length) {
+ throw new IllegalArgumentException("All arrays should have the same size. h: "
+ + Arrays.toString(h) + " s: " + Arrays.toString(s) + " l: "
+ + Arrays.toString(l));
+ }
+
this.h = h;
this.s = s;
this.l = l;
@@ -327,271 +340,280 @@ public class Tonal implements ExtractionType {
// a best fit. Each palette is defined as 22 HSL colors
private static final TonalPalette[] TONAL_PALETTES = {
new TonalPalette(
- new float[]{0.991f, 0.9833333333333333f, 0f, 0f, 0f, 0.01134380453752181f,
- 0.015625000000000003f, 0.024193548387096798f, 0.027397260273972573f,
- 0.017543859649122865f},
- new float[]{1f, 1f, 1f, 1f, 0.8434782608695652f, 1f, 1f, 1f, 1f, 1f},
- new float[]{0.2f, 0.27450980392156865f, 0.34901960784313724f,
- 0.4235294117647059f, 0.5490196078431373f, 0.6254901960784314f,
- 0.6862745098039216f, 0.7568627450980392f, 0.8568627450980393f,
- 0.9254901960784314f}
+ new float[] {1f, 1f, 0.991f, 0.991f, 0.9833333333333333f, 0f, 0f, 0f,
+ 0.01134380453752181f, 0.015625000000000003f, 0.024193548387096798f,
+ 0.027397260273972573f, 0.017543859649122865f},
+ new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 0.8434782608695652f, 1f, 1f, 1f, 1f,
+ 1f},
+ new float[] {0.04f, 0.09f, 0.14f, 0.2f, 0.27450980392156865f,
+ 0.34901960784313724f, 0.4235294117647059f, 0.5490196078431373f,
+ 0.6254901960784314f, 0.6862745098039216f, 0.7568627450980392f,
+ 0.8568627450980393f, 0.9254901960784314f}
),
new TonalPalette(
- new float[]{0.6385767790262171f, 0.6301169590643275f, 0.6223958333333334f,
- 0.6151079136690647f, 0.6065400843881856f, 0.5986964618249534f,
- 0.5910746812386157f, 0.5833333333333334f, 0.5748031496062993f,
- 0.5582010582010583f},
- new float[]{1f, 1f, 0.9014084507042253f, 0.8128654970760234f,
- 0.7979797979797981f, 0.7816593886462883f, 0.778723404255319f,
- 1f, 1f, 1f},
- new float[]{0.17450980392156862f, 0.2235294117647059f, 0.2784313725490196f,
- 0.3352941176470588f, 0.388235294117647f, 0.44901960784313727f,
- 0.5392156862745098f, 0.6509803921568628f, 0.7509803921568627f,
- 0.8764705882352941f}
+ new float[] {0.638f, 0.638f, 0.6385767790262171f, 0.6301169590643275f,
+ 0.6223958333333334f, 0.6151079136690647f, 0.6065400843881856f,
+ 0.5986964618249534f, 0.5910746812386157f, 0.5833333333333334f,
+ 0.5748031496062993f, 0.5582010582010583f},
+ new float[] {1f, 1f, 1f, 1f, 0.9014084507042253f, 0.8128654970760234f,
+ 0.7979797979797981f, 0.7816593886462883f, 0.778723404255319f, 1f, 1f,
+ 1f},
+ new float[] {0.05f, 0.12f, 0.17450980392156862f, 0.2235294117647059f,
+ 0.2784313725490196f, 0.3352941176470588f, 0.388235294117647f,
+ 0.44901960784313727f, 0.5392156862745098f, 0.6509803921568628f,
+ 0.7509803921568627f, 0.8764705882352941f}
),
new TonalPalette(
- new float[]{0.5669934640522876f, 0.5748031496062993f,
+ new float[] {0.563f, 0.569f, 0.5666f, 0.5669934640522876f, 0.5748031496062993f,
0.5595238095238095f, 0.5473118279569893f, 0.5393258426966292f,
0.5315955766192734f, 0.524031007751938f, 0.5154711673699016f,
0.508080808080808f, 0.5f},
- new float[]{1f, 1f, 1f, 1f, 1f, 1f, 0.8847736625514403f, 1f, 1f, 1f},
- new float[]{0.2f, 0.24901960784313726f, 0.27450980392156865f,
- 0.30392156862745096f, 0.34901960784313724f, 0.4137254901960784f,
- 0.47647058823529415f, 0.5352941176470588f, 0.6764705882352942f, 0.8f}
+ new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0.8847736625514403f, 1f, 1f,
+ 1f},
+ new float[] {0.07f, 0.12f, 0.16f, 0.2f, 0.24901960784313726f,
+ 0.27450980392156865f, 0.30392156862745096f, 0.34901960784313724f,
+ 0.4137254901960784f, 0.47647058823529415f, 0.5352941176470588f,
+ 0.6764705882352942f, 0.8f}
),
new TonalPalette(
- new float[]{0.5082304526748972f, 0.5069444444444444f, 0.5f, 0.5f,
- 0.5f, 0.48724954462659376f, 0.4800347222222222f,
- 0.4755134281200632f, 0.4724409448818897f, 0.4671052631578947f},
- new float[]{1f, 0.8888888888888887f, 0.9242424242424242f, 1f, 1f,
- 0.8133333333333332f, 0.7868852459016393f, 1f, 1f, 1f},
- new float[]{0.1588235294117647f, 0.21176470588235297f,
- 0.25882352941176473f, 0.3f, 0.34901960784313724f,
+ new float[] {0.508f, 0.511f, 0.508f, 0.508f, 0.5082304526748972f,
+ 0.5069444444444444f, 0.5f, 0.5f, 0.5f, 0.48724954462659376f,
+ 0.4800347222222222f, 0.4755134281200632f, 0.4724409448818897f,
+ 0.4671052631578947f},
+ new float[] {1f, 1f, 1f, 1f, 1f, 0.8888888888888887f, 0.9242424242424242f, 1f,
+ 1f, 0.8133333333333332f, 0.7868852459016393f, 1f, 1f, 1f},
+ new float[] {0.04f, 0.06f, 0.08f, 0.12f, 0.1588235294117647f,
+ 0.21176470588235297f, 0.25882352941176473f, 0.3f, 0.34901960784313724f,
0.44117647058823534f, 0.5215686274509804f, 0.5862745098039216f,
0.7509803921568627f, 0.8509803921568627f}
),
new TonalPalette(
- new float[]{0.3333333333333333f, 0.3333333333333333f,
+ new float[] {0.333f, 0.333f, 0.333f, 0.3333333333333333f, 0.3333333333333333f,
0.34006734006734f, 0.34006734006734f, 0.34006734006734f,
0.34259259259259256f, 0.3475783475783476f, 0.34767025089605735f,
0.3467741935483871f, 0.3703703703703704f},
- new float[]{0.6703296703296703f, 0.728813559322034f,
+ new float[] {0.70f, 0.72f, 0.69f, 0.6703296703296703f, 0.728813559322034f,
0.5657142857142856f, 0.5076923076923077f, 0.3944223107569721f,
0.6206896551724138f, 0.8931297709923666f, 1f, 1f, 1f},
- new float[]{0.1784313725490196f, 0.23137254901960785f,
+ new float[] {0.05f, 0.08f, 0.14f, 0.1784313725490196f, 0.23137254901960785f,
0.3431372549019608f, 0.38235294117647056f, 0.49215686274509807f,
0.6588235294117647f, 0.7431372549019608f, 0.8176470588235294f,
0.8784313725490196f, 0.9294117647058824f}
),
new TonalPalette(
- new float[]{0.162280701754386f, 0.15032679738562088f,
+ new float[] {0.161f, 0.163f, 0.163f, 0.162280701754386f, 0.15032679738562088f,
0.15879265091863518f, 0.16236559139784948f, 0.17443868739205526f,
- 0.17824074074074076f, 0.18674698795180725f,
- 0.18692449355432778f, 0.1946778711484594f, 0.18604651162790695f},
- new float[]{1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
- new float[]{0.14901960784313725f, 0.2f, 0.24901960784313726f,
- 0.30392156862745096f, 0.3784313725490196f, 0.4235294117647059f,
- 0.48823529411764705f, 0.6450980392156863f, 0.7666666666666666f,
- 0.8313725490196078f}
+ 0.17824074074074076f, 0.18674698795180725f, 0.18692449355432778f,
+ 0.1946778711484594f, 0.18604651162790695f},
+ new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
+ new float[] {0.05f, 0.08f, 0.11f, 0.14901960784313725f, 0.2f,
+ 0.24901960784313726f, 0.30392156862745096f, 0.3784313725490196f,
+ 0.4235294117647059f, 0.48823529411764705f, 0.6450980392156863f,
+ 0.7666666666666666f, 0.8313725490196078f}
),
new TonalPalette(
- new float[]{0.10619469026548674f, 0.11924686192468618f,
- 0.13046448087431692f, 0.14248366013071895f, 0.1506024096385542f,
- 0.16220238095238093f, 0.16666666666666666f,
+ new float[] {0.108f, 0.105f, 0.105f, 0.105f, 0.10619469026548674f,
+ 0.11924686192468618f, 0.13046448087431692f, 0.14248366013071895f,
+ 0.1506024096385542f, 0.16220238095238093f, 0.16666666666666666f,
0.16666666666666666f, 0.162280701754386f, 0.15686274509803924f},
- new float[]{1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
- new float[]{0.44313725490196076f, 0.46862745098039216f,
- 0.47843137254901963f, 0.5f, 0.5117647058823529f,
+ new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
+ new float[] {0.17f, 0.22f, 0.28f, 0.35f, 0.44313725490196076f,
+ 0.46862745098039216f, 0.47843137254901963f, 0.5f, 0.5117647058823529f,
0.5607843137254902f, 0.6509803921568628f, 0.7509803921568627f,
0.8509803921568627f, 0.9f}
),
new TonalPalette(
- new float[]{0.03561253561253561f, 0.05098039215686275f,
- 0.07516339869281045f, 0.09477124183006536f, 0.1150326797385621f,
- 0.134640522875817f, 0.14640522875816991f, 0.1582397003745319f,
- 0.15773809523809523f, 0.15359477124183002f},
- new float[]{1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
- new float[]{0.4588235294117647f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
- 0.5f, 0.6509803921568628f, 0.7803921568627451f, 0.9f}
+ new float[] {0.036f, 0.036f, 0.036f, 0.036f, 0.03561253561253561f,
+ 0.05098039215686275f, 0.07516339869281045f, 0.09477124183006536f,
+ 0.1150326797385621f, 0.134640522875817f, 0.14640522875816991f,
+ 0.1582397003745319f, 0.15773809523809523f, 0.15359477124183002f},
+ new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
+ new float[] {0.19f, 0.26f, 0.34f, 0.39f, 0.4588235294117647f, 0.5f, 0.5f, 0.5f,
+ 0.5f, 0.5f, 0.5f, 0.6509803921568628f, 0.7803921568627451f, 0.9f}
),
new TonalPalette(
- new float[]{0.9596491228070175f, 0.9593837535014005f,
+ new float[] {0.955f, 0.961f, 0.958f, 0.9596491228070175f, 0.9593837535014005f,
0.9514767932489452f, 0.943859649122807f, 0.9396825396825397f,
0.9395424836601307f, 0.9393939393939394f, 0.9362745098039216f,
0.9754098360655739f, 0.9824561403508771f},
- new float[]{0.84070796460177f, 0.8206896551724138f,
+ new float[] {0.87f, 0.85f, 0.85f, 0.84070796460177f, 0.8206896551724138f,
0.7979797979797981f, 0.7661290322580644f, 0.9051724137931036f,
1f, 1f, 1f, 1f, 1f},
- new float[]{0.22156862745098038f, 0.2843137254901961f,
+ new float[] {0.06f, 0.11f, 0.16f, 0.22156862745098038f, 0.2843137254901961f,
0.388235294117647f, 0.48627450980392156f, 0.5450980392156863f,
0.6f, 0.6764705882352942f, 0.8f, 0.8803921568627451f,
0.9254901960784314f}
),
new TonalPalette(
- new float[]{0.841025641025641f, 0.8333333333333334f,
+ new float[] {0.866f, 0.855f, 0.841025641025641f, 0.8333333333333334f,
0.8285256410256411f, 0.821522309711286f, 0.8083333333333333f,
0.8046594982078853f, 0.8005822416302766f, 0.7842377260981912f,
0.7771084337349398f, 0.7747747747747749f},
- new float[]{1f, 1f, 1f, 1f, 1f, 1f, 1f,
+ new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f,
0.737142857142857f, 0.6434108527131781f, 0.46835443037974644f},
- new float[]{0.12745098039215685f, 0.15490196078431373f,
+ new float[] {0.05f, 0.08f, 0.12745098039215685f, 0.15490196078431373f,
0.20392156862745098f, 0.24901960784313726f, 0.3137254901960784f,
- 0.36470588235294116f, 0.44901960784313727f,
- 0.6568627450980392f, 0.7470588235294118f, 0.8450980392156863f}
+ 0.36470588235294116f, 0.44901960784313727f, 0.6568627450980392f,
+ 0.7470588235294118f, 0.8450980392156863f}
),
new TonalPalette(
- new float[]{0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f},
- new float[]{0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f},
- new float[]{0.14901960784313725f, 0.2f, 0.2980392156862745f, 0.4f,
- 0.4980392156862745f, 0.6196078431372549f, 0.7176470588235294f,
- 0.8196078431372549f, 0.9176470588235294f, 0.9490196078431372f}
- ),
- new TonalPalette(
- new float[]{0.955952380952381f, 0.9681069958847737f,
- 0.9760479041916167f, 0.9873563218390804f, 0f, 0f,
+ new float[] {0.925f, 0.93f, 0.938f, 0.947f, 0.955952380952381f,
+ 0.9681069958847737f, 0.9760479041916167f, 0.9873563218390804f, 0f, 0f,
0.009057971014492771f, 0.026748971193415648f,
0.041666666666666616f, 0.05303030303030304f},
- new float[]{1f, 0.8350515463917526f, 0.6929460580912863f,
+ new float[] {1f, 1f, 1f, 1f, 1f, 0.8350515463917526f, 0.6929460580912863f,
0.6387665198237885f, 0.6914893617021276f, 0.7583892617449666f,
0.8070175438596495f, 0.9310344827586209f, 1f, 1f},
- new float[]{0.27450980392156865f, 0.3803921568627451f,
- 0.4725490196078432f, 0.5549019607843138f, 0.6313725490196078f,
- 0.707843137254902f, 0.7764705882352941f, 0.8294117647058823f,
- 0.9058823529411765f, 0.9568627450980391f}
+ new float[] {0.10f, 0.13f, 0.17f, 0.2f, 0.27450980392156865f,
+ 0.3803921568627451f, 0.4725490196078432f, 0.5549019607843138f,
+ 0.6313725490196078f, 0.707843137254902f, 0.7764705882352941f,
+ 0.8294117647058823f, 0.9058823529411765f, 0.9568627450980391f}
),
new TonalPalette(
- new float[]{0.7514619883040936f, 0.7679738562091503f,
+ new float[] {0.733f, 0.736f, 0.744f, 0.7514619883040936f, 0.7679738562091503f,
0.7802083333333333f, 0.7844311377245509f, 0.796875f,
0.8165618448637316f, 0.8487179487179487f, 0.8582375478927203f,
0.8562091503267975f, 0.8666666666666667f},
- new float[]{1f, 1f, 0.8163265306122449f, 0.6653386454183268f,
+ new float[] {1f, 1f, 1f, 1f, 1f, 0.8163265306122449f, 0.6653386454183268f,
0.7547169811320753f, 0.929824561403509f, 0.9558823529411766f,
0.9560439560439562f, 1f, 1f},
- new float[]{0.2235294117647059f, 0.3f, 0.38431372549019605f,
- 0.492156862745098f, 0.5843137254901961f, 0.6647058823529411f,
- 0.7333333333333334f, 0.8215686274509804f, 0.9f,
+ new float[] {0.07f, 0.12f, 0.17f, 0.2235294117647059f, 0.3f,
+ 0.38431372549019605f, 0.492156862745098f, 0.5843137254901961f,
+ 0.6647058823529411f, 0.7333333333333334f, 0.8215686274509804f, 0.9f,
0.9411764705882353f}
),
new TonalPalette(
- new float[]{0.6666666666666666f, 0.6666666666666666f,
+ new float[] {0.6666666666666666f, 0.6666666666666666f, 0.6666666666666666f,
0.6666666666666666f, 0.6666666666666666f, 0.6666666666666666f,
0.6666666666666666f, 0.6666666666666666f, 0.6666666666666666f,
0.6666666666666666f, 0.6666666666666666f},
- new float[]{0.24590163934426232f, 0.17880794701986752f,
+ new float[] {0.25f, 0.24590163934426232f, 0.17880794701986752f,
0.14606741573033713f, 0.13761467889908252f, 0.14893617021276592f,
- 0.16756756756756758f, 0.20312500000000017f,
- 0.26086956521739135f, 0.29999999999999966f, 0.5000000000000004f},
- new float[]{0.2392156862745098f, 0.296078431372549f,
+ 0.16756756756756758f, 0.20312500000000017f, 0.26086956521739135f,
+ 0.29999999999999966f, 0.5000000000000004f},
+ new float[] {0.18f, 0.2392156862745098f, 0.296078431372549f,
0.34901960784313724f, 0.4274509803921569f, 0.5392156862745098f,
0.6372549019607843f, 0.7490196078431373f, 0.8196078431372549f,
0.8823529411764706f, 0.9372549019607843f}
),
new TonalPalette(
- new float[]{0.9678571428571429f, 0.9944812362030905f, 0f, 0f,
+ new float[] {0.938f, 0.944f, 0.952f, 0.961f, 0.9678571428571429f,
+ 0.9944812362030905f, 0f, 0f,
0.0047348484848484815f, 0.00316455696202532f, 0f,
0.9980392156862745f, 0.9814814814814816f, 0.9722222222222221f},
- new float[]{1f, 0.7023255813953488f, 0.6638655462184874f,
+ new float[] {1f, 1f, 1f, 1f, 1f, 0.7023255813953488f, 0.6638655462184874f,
0.6521739130434782f, 0.7719298245614035f, 0.8315789473684211f,
0.6867469879518071f, 0.7264957264957265f, 0.8181818181818182f,
0.8181818181818189f},
- new float[]{0.27450980392156865f, 0.4215686274509804f,
+ new float[] {0.08f, 0.13f, 0.18f, 0.23f, 0.27450980392156865f,
+ 0.4215686274509804f,
0.4666666666666667f, 0.503921568627451f, 0.5529411764705883f,
0.6274509803921569f, 0.6745098039215687f, 0.7705882352941176f,
0.892156862745098f, 0.9568627450980391f}
),
new TonalPalette(
- new float[]{0.9052287581699346f, 0.9112021857923498f, 0.9270152505446624f,
- 0.9343137254901961f, 0.9391534391534391f, 0.9437984496124031f,
- 0.943661971830986f, 0.9438943894389439f, 0.9426229508196722f,
- 0.9444444444444444f},
- new float[]{1f, 0.8133333333333332f, 0.7927461139896375f, 0.7798165137614679f,
- 0.7777777777777779f, 0.8190476190476191f, 0.8255813953488372f,
- 0.8211382113821142f, 0.8133333333333336f, 0.8000000000000006f},
- new float[]{0.2f, 0.29411764705882354f, 0.3784313725490196f,
- 0.42745098039215684f, 0.4764705882352941f, 0.5882352941176471f,
- 0.6627450980392157f, 0.7588235294117647f, 0.8529411764705882f,
- 0.9411764705882353f}
+ new float[] {0.88f, 0.888f, 0.897f, 0.9052287581699346f, 0.9112021857923498f,
+ 0.9270152505446624f, 0.9343137254901961f, 0.9391534391534391f,
+ 0.9437984496124031f, 0.943661971830986f, 0.9438943894389439f,
+ 0.9426229508196722f, 0.9444444444444444f},
+ new float[] {1f, 1f, 1f, 1f, 0.8133333333333332f, 0.7927461139896375f,
+ 0.7798165137614679f, 0.7777777777777779f, 0.8190476190476191f,
+ 0.8255813953488372f, 0.8211382113821142f, 0.8133333333333336f,
+ 0.8000000000000006f},
+ new float[] {0.08f, 0.12f, 0.16f, 0.2f, 0.29411764705882354f,
+ 0.3784313725490196f, 0.42745098039215684f, 0.4764705882352941f,
+ 0.5882352941176471f, 0.6627450980392157f, 0.7588235294117647f,
+ 0.8529411764705882f, 0.9411764705882353f}
),
new TonalPalette(
- new float[]{0.6884057971014492f, 0.6974789915966387f, 0.7079889807162534f,
- 0.7154471544715447f, 0.7217741935483872f, 0.7274143302180687f,
- 0.7272727272727273f, 0.7258064516129031f, 0.7252252252252251f,
- 0.7333333333333333f},
- new float[]{0.8214285714285715f, 0.6878612716763006f, 0.6080402010050251f,
- 0.5774647887323943f, 0.5391304347826086f, 0.46724890829694316f,
- 0.4680851063829788f, 0.462686567164179f, 0.45679012345678977f,
- 0.4545454545454551f},
- new float[]{0.2196078431372549f, 0.33921568627450976f, 0.39019607843137255f,
- 0.4176470588235294f, 0.45098039215686275f,
+ new float[] {0.669f, 0.680f, 0.6884057971014492f, 0.6974789915966387f,
+ 0.7079889807162534f, 0.7154471544715447f, 0.7217741935483872f,
+ 0.7274143302180687f, 0.7272727272727273f, 0.7258064516129031f,
+ 0.7252252252252251f, 0.7333333333333333f},
+ new float[] {0.81f, 0.81f, 0.8214285714285715f, 0.6878612716763006f,
+ 0.6080402010050251f, 0.5774647887323943f, 0.5391304347826086f,
+ 0.46724890829694316f, 0.4680851063829788f, 0.462686567164179f,
+ 0.45679012345678977f, 0.4545454545454551f},
+ new float[] {0.12f, 0.16f, 0.2196078431372549f, 0.33921568627450976f,
+ 0.39019607843137255f, 0.4176470588235294f, 0.45098039215686275f,
0.5509803921568628f, 0.6313725490196078f, 0.7372549019607844f,
0.8411764705882353f, 0.9352941176470588f}
),
new TonalPalette(
- new float[]{0.6470588235294118f, 0.6516666666666667f, 0.6464174454828661f,
+ new float[] {0.6470588235294118f, 0.6516666666666667f, 0.6464174454828661f,
0.6441441441441442f, 0.6432748538011696f, 0.6416666666666667f,
0.6402439024390243f, 0.6412429378531074f, 0.6435185185185186f,
0.6428571428571429f},
- new float[]{0.8095238095238095f, 0.6578947368421053f, 0.5721925133689839f,
+ new float[] {0.8095238095238095f, 0.6578947368421053f, 0.5721925133689839f,
0.5362318840579711f, 0.5f, 0.4424778761061947f, 0.44086021505376327f,
- 0.44360902255639095f,
- 0.4499999999999997f, 0.4375000000000006f},
- new float[]{0.16470588235294117f, 0.2980392156862745f, 0.36666666666666664f,
+ 0.44360902255639095f, 0.4499999999999997f, 0.4375000000000006f},
+ new float[] {0.16470588235294117f, 0.2980392156862745f, 0.36666666666666664f,
0.40588235294117647f, 0.44705882352941173f,
0.5568627450980392f, 0.6352941176470588f, 0.7392156862745098f,
0.8431372549019608f, 0.9372549019607843f}
),
new TonalPalette(
- new float[]{0.46732026143790845f, 0.4718614718614719f, 0.4793650793650794f,
- 0.48071625344352614f, 0.4829683698296837f, 0.484375f,
- 0.4841269841269842f, 0.48444444444444457f, 0.48518518518518516f,
- 0.4907407407407408f},
- new float[]{1f, 1f, 1f, 1f, 1f, 0.6274509803921569f, 0.41832669322709176f,
- 0.41899441340782106f, 0.4128440366972478f,
- 0.4090909090909088f},
- new float[]{0.1f, 0.15098039215686274f, 0.20588235294117646f,
+ new float[] {0.469f, 0.46732026143790845f, 0.4718614718614719f,
+ 0.4793650793650794f, 0.48071625344352614f, 0.4829683698296837f,
+ 0.484375f, 0.4841269841269842f, 0.48444444444444457f,
+ 0.48518518518518516f, 0.4907407407407408f},
+ new float[] {1f, 1f, 1f, 1f, 1f, 1f, 0.6274509803921569f, 0.41832669322709176f,
+ 0.41899441340782106f, 0.4128440366972478f, 0.4090909090909088f},
+ new float[] {0.07f, 0.1f, 0.15098039215686274f, 0.20588235294117646f,
0.2372549019607843f, 0.26862745098039215f, 0.4f, 0.5078431372549019f,
0.6490196078431372f, 0.7862745098039216f, 0.9137254901960784f}
),
new TonalPalette(
- new float[]{0.5444444444444444f, 0.5555555555555556f, 0.5555555555555556f,
- 0.553763440860215f, 0.5526315789473684f, 0.5555555555555556f,
- 0.5555555555555555f, 0.5555555555555556f, 0.5512820512820514f,
- 0.5666666666666667f},
- new float[]{0.24590163934426232f, 0.19148936170212766f, 0.1791044776119403f,
- 0.18343195266272191f, 0.18446601941747576f,
+ new float[] {0.542f, 0.5444444444444444f, 0.5555555555555556f,
+ 0.5555555555555556f, 0.553763440860215f, 0.5526315789473684f,
+ 0.5555555555555556f, 0.5555555555555555f, 0.5555555555555556f,
+ 0.5512820512820514f, 0.5666666666666667f},
+ new float[] {0.25f, 0.24590163934426232f, 0.19148936170212766f,
+ 0.1791044776119403f, 0.18343195266272191f, 0.18446601941747576f,
0.1538461538461539f, 0.15625000000000003f, 0.15328467153284678f,
0.15662650602409653f, 0.151515151515151f},
- new float[]{0.1196078431372549f, 0.1843137254901961f, 0.2627450980392157f,
+ new float[] {0.05f, 0.1196078431372549f, 0.1843137254901961f,
+ 0.2627450980392157f,
0.33137254901960783f, 0.403921568627451f, 0.5411764705882354f,
0.6235294117647059f, 0.7313725490196079f, 0.8372549019607843f,
0.9352941176470588f}
),
new TonalPalette(
- new float[]{0.022222222222222223f, 0.02469135802469136f, 0.031249999999999997f,
+ new float[] {0.022222222222222223f, 0.02469135802469136f, 0.031249999999999997f,
0.03947368421052631f, 0.04166666666666668f,
0.043650793650793655f, 0.04411764705882352f, 0.04166666666666652f,
0.04444444444444459f, 0.05555555555555529f},
- new float[]{0.33333333333333337f, 0.2783505154639175f, 0.2580645161290323f,
+ new float[] {0.33333333333333337f, 0.2783505154639175f, 0.2580645161290323f,
0.25675675675675674f, 0.2528735632183908f, 0.17500000000000002f,
0.15315315315315312f, 0.15189873417721522f,
0.15789473684210534f, 0.15789473684210542f},
- new float[]{0.08823529411764705f, 0.19019607843137254f, 0.2431372549019608f,
+ new float[] {0.08823529411764705f, 0.19019607843137254f, 0.2431372549019608f,
0.2901960784313725f, 0.3411764705882353f, 0.47058823529411764f,
0.5647058823529412f, 0.6901960784313725f, 0.8137254901960784f,
0.9254901960784314f}
),
new TonalPalette(
- new float[]{0.050884955752212385f, 0.07254901960784313f, 0.0934640522875817f,
+ new float[] {0.027f, 0.03f, 0.038f, 0.044f, 0.050884955752212385f,
+ 0.07254901960784313f, 0.0934640522875817f,
0.10457516339869281f, 0.11699346405228758f,
0.1255813953488372f, 0.1268939393939394f, 0.12533333333333332f,
0.12500000000000003f, 0.12777777777777777f},
- new float[]{1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
- new float[]{0.44313725490196076f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5784313725490196f,
+ new float[] {1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f},
+ new float[] {0.25f, 0.3f, 0.35f, 0.4f, 0.44313725490196076f, 0.5f, 0.5f, 0.5f,
+ 0.5f, 0.5784313725490196f,
0.6549019607843137f, 0.7549019607843137f, 0.8509803921568627f,
0.9411764705882353f}
)
};
+ private static final TonalPalette GREY_PALETTE = new TonalPalette(
+ new float[]{0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f},
+ new float[]{0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f},
+ new float[]{0.08f, 0.11f, 0.14901960784313725f, 0.2f, 0.2980392156862745f, 0.4f,
+ 0.4980392156862745f, 0.6196078431372549f, 0.7176470588235294f,
+ 0.8196078431372549f, 0.9176470588235294f, 0.9490196078431372f}
+ );
+
@SuppressWarnings("WeakerAccess")
@VisibleForTesting
static final ColorRange[] BLACKLISTED_COLORS = new ColorRange[] {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationSwipeActionHelper.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationSwipeActionHelper.java
index 3cd5d89ea142..f6cf03562014 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationSwipeActionHelper.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationSwipeActionHelper.java
@@ -22,6 +22,7 @@ import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.view.MotionEvent;
import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
@ProvidesInterface(version = NotificationSwipeActionHelper.VERSION)
@DependsOn(target = SnoozeOption.class)
@@ -56,19 +57,17 @@ public interface NotificationSwipeActionHelper {
public boolean swipedFastEnough(float translation, float velocity);
@ProvidesInterface(version = SnoozeOption.VERSION)
- public static class SnoozeOption {
- public static final int VERSION = 1;
- public int snoozeForMinutes;
- public SnoozeCriterion criterion;
- public CharSequence description;
- public CharSequence confirmation;
-
- public SnoozeOption(SnoozeCriterion crit, int minsToSnoozeFor, CharSequence desc,
- CharSequence confirm) {
- criterion = crit;
- snoozeForMinutes = minsToSnoozeFor;
- description = desc;
- confirmation = confirm;
- }
+ public interface SnoozeOption {
+ public static final int VERSION = 2;
+
+ public SnoozeCriterion getSnoozeCriterion();
+
+ public CharSequence getDescription();
+
+ public CharSequence getConfirmation();
+
+ public int getMinutesToSnoozeFor();
+
+ public AccessibilityAction getAccessibilityAction();
}
}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 9a9716277662..501d0a57148a 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -53,7 +53,7 @@
android:gravity="center"
android:layout_centerHorizontal="true"
android:layout_marginRight="72dp"
- androidprv:scaledTextSize="28"
+ androidprv:scaledTextSize="@integer/scaled_password_text_size"
android:textColor="?attr/bgProtectTextColor"
android:contentDescription="@string/keyguard_accessibility_pin_area"
/>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index f0dec762abc6..c4732e42b5ad 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -66,7 +66,7 @@
android:gravity="center"
android:layout_centerHorizontal="true"
android:layout_marginRight="72dp"
- androidprv:scaledTextSize="28"
+ androidprv:scaledTextSize="@integer/scaled_password_text_size"
android:textColor="?attr/bgProtectTextColor"
android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
/>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 119b3ee11335..1c7defd6399a 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -67,7 +67,7 @@
android:gravity="center"
android:layout_centerHorizontal="true"
android:layout_marginRight="72dp"
- androidprv:scaledTextSize="28"
+ androidprv:scaledTextSize="@integer/scaled_password_text_size"
android:textColor="?attr/bgProtectTextColor"
android:contentDescription="@string/keyguard_accessibility_sim_puk_area"
/>
diff --git a/packages/SystemUI/res-keyguard/values/attrs.xml b/packages/SystemUI/res-keyguard/values/attrs.xml
index d3d60a1e18d2..802bd308d407 100644
--- a/packages/SystemUI/res-keyguard/values/attrs.xml
+++ b/packages/SystemUI/res-keyguard/values/attrs.xml
@@ -41,7 +41,4 @@
<declare-styleable name="CarrierText">
<attr name="allCaps" format="boolean" />
</declare-styleable>
-
- <attr name="pinDividerColor" format="color" />
- <attr name="pinDeleteColor" format="color" />
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 41c723e3daf7..a721dd0609dc 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -48,6 +48,8 @@
<!-- The size of the dots in the PIN unlock method. -->
<dimen name="password_dot_size">9dp</dimen>
+ <!-- The size of PIN text in the PIN unlock method. -->
+ <integer name="scaled_password_text_size">40</integer>
<!-- The padding between chars of the password view. -->
<dimen name="password_char_padding">8dp</dimen>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index d7ff349b52bf..0c96b0b221ab 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -32,8 +32,8 @@
<item name="android:singleLine">true</item>
<item name="android:gravity">center_horizontal|center_vertical</item>
<item name="android:background">@null</item>
- <item name="android:textSize">36sp</item>
- <item name="android:fontFamily">sans-serif-light</item>
+ <item name="android:textSize">32sp</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyLight</item>
<item name="android:textColor">?attr/bgProtectTextColor</item>
<item name="android:paddingBottom">-16dp</item>
</style>
@@ -53,7 +53,7 @@
</style>
<style name="widget_big_thin">
<item name="android:textSize">@dimen/widget_big_font_size</item>
- <item name="android:fontFamily">sans-serif-light</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyLight</item>
</style>
<style name="BouncerSecurityContainer">
diff --git a/packages/SystemUI/res/color/qs_background_dark.xml b/packages/SystemUI/res/color/qs_background_dark.xml
index 1aa732f43286..62e495974623 100644
--- a/packages/SystemUI/res/color/qs_background_dark.xml
+++ b/packages/SystemUI/res/color/qs_background_dark.xml
@@ -16,5 +16,5 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="0.93"
- android:color="?android:attr/colorPrimaryDark"/>
+ android:color="?android:attr/colorBackgroundFloating"/>
</selector>
diff --git a/packages/SystemUI/res/drawable/pip_icon.xml b/packages/SystemUI/res/drawable/pip_icon.xml
new file mode 100644
index 000000000000..bd92ccd2e6e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pip_icon.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2017 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="36dp"
+ android:height="36dp"
+ android:viewportWidth="25"
+ android:viewportHeight="25">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M19,7h-8v6h8L19,7zM21,3L3,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,1.98 2,1.98h18c1.1,0 2,-0.88 2,-1.98L23,5c0,-1.1 -0.9,-2 -2,-2zM21,19.01L3,19.01L3,4.98h18v14.03z"/>
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_background_primary.xml b/packages/SystemUI/res/drawable/qs_background_primary.xml
index 416583013e64..03bba53946da 100644
--- a/packages/SystemUI/res/drawable/qs_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_background_primary.xml
@@ -15,6 +15,6 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
- <solid android:color="?android:attr/colorBackgroundFloating"/>
+ <solid android:color="@color/qs_background_dark"/>
</shape>
</inset>
diff --git a/packages/SystemUI/res/layout/navigation_bar_window.xml b/packages/SystemUI/res/layout/navigation_bar_window.xml
index 051bf3ac3faf..6fa46d4ba3f8 100644
--- a/packages/SystemUI/res/layout/navigation_bar_window.xml
+++ b/packages/SystemUI/res/layout/navigation_bar_window.xml
@@ -16,11 +16,11 @@
** limitations under the License.
*/
-->
-<FrameLayout
+<com.android.systemui.statusbar.phone.NavigationBarFrame
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/navigation_bar_frame"
android:layout_height="match_parent"
android:layout_width="match_parent">
-</FrameLayout>
+</com.android.systemui.statusbar.phone.NavigationBarFrame>
diff --git a/packages/SystemUI/res/layout/notification_snooze.xml b/packages/SystemUI/res/layout/notification_snooze.xml
index b70f24b4d552..3209f27f7e00 100644
--- a/packages/SystemUI/res/layout/notification_snooze.xml
+++ b/packages/SystemUI/res/layout/notification_snooze.xml
@@ -20,12 +20,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
+ android:clickable="true"
android:background="@color/notification_guts_bg_color"
android:theme="@*android:style/Theme.DeviceDefault.Light">
<RelativeLayout
- android:layout_width="match_parent"
android:id="@+id/notification_snooze"
+ android:layout_width="match_parent"
android:layout_height="@dimen/snooze_snackbar_min_height">
<TextView
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 5143b4ea26b3..8b235fa0aad4 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -281,7 +281,7 @@
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotació bloquejada"</string>
<string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"Vertical"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"Horitzontal"</string>
- <string name="quick_settings_ime_label" msgid="7073463064369468429">"Mètode d\'entrada"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"Mètode d\'introducció"</string>
<string name="quick_settings_location_label" msgid="5011327048748762257">"Ubicació"</string>
<string name="quick_settings_location_off_label" msgid="7464544086507331459">"Ubicació desactivada"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispositiu multimèdia"</string>
@@ -730,7 +730,7 @@
<string name="pip_notification_message" msgid="4171698133469539591">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string>
<string name="pip_play" msgid="1417176722760265888">"Reprodueix"</string>
<string name="pip_pause" msgid="8881063404466476571">"Posa en pausa"</string>
- <string name="pip_skip_to_next" msgid="1948440006726306284">"Vés al següent"</string>
+ <string name="pip_skip_to_next" msgid="1948440006726306284">"Ves al següent"</string>
<string name="pip_skip_to_prev" msgid="1955311326688637914">"Torna a l\'anterior"</string>
<string name="thermal_shutdown_title" msgid="4458304833443861111">"Telèfon apagat per la calor"</string>
<string name="thermal_shutdown_message" msgid="9006456746902370523">"Ara el telèfon funciona de manera normal"</string>
@@ -759,7 +759,7 @@
<string name="instant_apps" msgid="6647570248119804907">"Aplicacions instantànies"</string>
<string name="instant_apps_message" msgid="8116608994995104836">"No cal instal·lar les aplicacions instantànies."</string>
<string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string>
- <string name="go_to_web" msgid="1106022723459948514">"Vés al web"</string>
+ <string name="go_to_web" msgid="1106022723459948514">"Ves al web"</string>
<string name="mobile_data" msgid="7094582042819250762">"Dades mòbils"</string>
<string name="wifi_is_off" msgid="1838559392210456893">"La Wi-Fi està desactivada"</string>
<string name="bt_is_off" msgid="2640685272289706392">"El Bluetooth està desactivat"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 1b9851079028..652e35bbe289 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -459,11 +459,11 @@
<string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string>
<string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Άνοιγμα αξιόπιστων διαπιστευτηρίων"</string>
<string name="monitoring_description_network_logging" msgid="7223505523384076027">"Ο διαχειριστής σας έχει ενεργοποιήσει την καταγραφή δικτύου, η οποία παρακολουθεί την επισκεψιμότητα στη συσκευή σας.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή σας."</string>
- <string name="monitoring_description_vpn" msgid="4445150119515393526">"Παραχωρήσατε σε μια εφαρμογή άδεια για τη ρύθμιση σύνδεσης VPN.\n\nΑυτή η εφαρμογή μπορεί να παρακολουθεί τη δραστηριότητα της συσκευής και του δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστότοπων."</string>
- <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Η διαχείριση του προφίλ εργασίας γίνεται από τον οργανισμό <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nΟ διαχειριστής έχει τη δυνατότητα παρακολούθησης της δραστηριότητας του δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστότοπων.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή.\n\nΕπίσης, είστε συνδεδεμένοι σε VPN, το οποίο μπορεί να παρακολουθεί τη δραστηριότητα του δικτύου σας."</string>
+ <string name="monitoring_description_vpn" msgid="4445150119515393526">"Παραχωρήσατε σε μια εφαρμογή άδεια για τη ρύθμιση σύνδεσης VPN.\n\nΑυτή η εφαρμογή μπορεί να παρακολουθεί τη δραστηριότητα της συσκευής και του δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Η διαχείριση του προφίλ εργασίας γίνεται από τον οργανισμό <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nΟ διαχειριστής έχει τη δυνατότητα παρακολούθησης της δραστηριότητας του δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή.\n\nΕπίσης, είστε συνδεδεμένοι σε VPN, το οποίο μπορεί να παρακολουθεί τη δραστηριότητα του δικτύου σας."</string>
<string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
<string name="monitoring_description_app" msgid="1828472472674709532">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
- <string name="monitoring_description_app_personal" msgid="484599052118316268">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του προσωπικού σας δικτύου, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστότοπων."</string>
+ <string name="monitoring_description_app_personal" msgid="484599052118316268">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του προσωπικού σας δικτύου, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
<string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του προσωπικού σας δικτύου, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
<string name="monitoring_description_app_work" msgid="4612997849787922906">"Ο οργανισμός <xliff:g id="ORGANIZATION">%1$s</xliff:g> διαχειρίζεται το προφίλ εργασίας σας. Το προφίλ είναι συνδεδεμένο στην εφαρμογή <xliff:g id="APPLICATION">%2$s</xliff:g>, η οποία μπορεί να παρακολουθήσει τη δραστηριότητα του δικτύου εργασίας σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή σας."</string>
<string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"Ο οργανισμός <xliff:g id="ORGANIZATION">%1$s</xliff:g> διαχειρίζεται το προφίλ εργασίας σας. Το προφίλ συνδέεται με την εφαρμογή <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του δικτύου της εργασίας σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων.\n\nΕπίσης, είστε συνδεδεμένοι στην εφαρμογή <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, που έχει τη δυνατότητα παρακολούθησης της δραστηριότητας του προσωπικού σας δικτύου."</string>
diff --git a/packages/SystemUI/res/values-mcc311-mnc480/config.xml b/packages/SystemUI/res/values-mcc311-mnc480/config.xml
new file mode 100644
index 000000000000..7dadae7f9107
--- /dev/null
+++ b/packages/SystemUI/res/values-mcc311-mnc480/config.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2017, 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+ <!-- Enable 5 bar signal strength icon -->
+ <bool name="config_inflateSignalStrength">true</bool>
+</resources>
+
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index d0af82cdd955..843f00b12567 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -489,7 +489,7 @@
<string name="quick_settings_reset_confirmation_message" msgid="2235970126803317374">"Keyingi safar sozlamalardan yoqilgan paydo bo‘ladi."</string>
<string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"Berkitish"</string>
<string name="managed_profile_foreground_toast" msgid="5421487114739245972">"Siz ishchi profildan foydalanmoqdasiz"</string>
- <string name="stream_voice_call" msgid="4410002696470423714">"Qo‘ng‘iroq qilish"</string>
+ <string name="stream_voice_call" msgid="4410002696470423714">"Chaqiruv"</string>
<string name="stream_system" msgid="7493299064422163147">"Tizim"</string>
<string name="stream_ring" msgid="8213049469184048338">"Jiringlatish"</string>
<string name="stream_music" msgid="9086982948697544342">"Multimedia"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 81ca23082367..74b0702ce5f6 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -398,4 +398,8 @@
it has been expanded to reveal its children. -->
<bool name="config_showGroupNotificationBgWhenExpanded">false</bool>
+ <!-- Whether to artificially interpret all signal strengths as
+ one bar higher than they actually are -->
+ <bool name="config_inflateSignalStrength">false</bool>
+
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 05678e274eef..93d2072e955c 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -820,11 +820,14 @@
<dimen name="edge_margin">16dp</dimen>
<dimen name="rounded_corner_radius">0dp</dimen>
- <dimen name="rounded_corner_content_padding">0dp</dimen>
+ <dimen name="rounded_corner_content_padding">8dp</dimen>
<!-- Intended corner radius when drawing the mobile signal -->
<dimen name="stat_sys_mobile_signal_corner_radius">0.75dp</dimen>
<!-- How far to inset the rounded edges -->
<dimen name="stat_sys_mobile_signal_circle_inset">0.9dp</dimen>
+ <!-- Width of the hollow triangle for empty signal state -->
+ <dimen name="mobile_signal_empty_strokewidth">2dp</dimen>
+
</resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 3c6ad23c9f07..b27deddb4dd0 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -78,5 +78,13 @@
<item type="id" name="action_move_tl_50" />
<item type="id" name="action_move_tl_30" />
<item type="id" name="action_move_rb_full" />
+
+ <!-- Accessibility actions for the notification menu -->
+ <item type="id" name="action_snooze_undo"/>
+ <item type="id" name="action_snooze_15_min"/>
+ <item type="id" name="action_snooze_30_min"/>
+ <item type="id" name="action_snooze_1_hour"/>
+ <item type="id" name="action_snooze_2_hours"/>
+ <item type="id" name="action_snooze_assistant_suggestion_1"/>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index f942be6a72d1..5274b6476aba 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -295,8 +295,6 @@
<item name="darkIconTheme">@style/DualToneDarkTheme</item>
<item name="bgProtectTextColor">?android:attr/textColorPrimaryInverse</item>
<item name="bgProtectSecondaryTextColor">?android:attr/textColorSecondaryInverse</item>
- <item name="pinDividerColor">@color/pin_divider_color</item>
- <item name="pinDeleteColor">@color/pin_delete_color</item>
<item name="*android:lockPatternStyle">@style/LockPatternStyle</item>
</style>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
index 38811ac85c8e..ce3068d765a8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
@@ -16,13 +16,19 @@
package com.android.keyguard;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.UserHandle;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionInfo;
import android.telephony.euicc.EuiccManager;
+import android.util.Log;
import java.lang.ref.WeakReference;
@@ -31,8 +37,26 @@ import java.lang.ref.WeakReference;
* the device with no cellular service.
*/
class KeyguardEsimArea extends Button implements View.OnClickListener {
+ private static final String ACTION_DISABLE_ESIM = "com.android.keyguard.disable_esim";
+ private static final String TAG = "KeyguardEsimArea";
+ private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
+
private EuiccManager mEuiccManager;
+ private BroadcastReceiver mReceiver =
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_DISABLE_ESIM.equals(intent.getAction())) {
+ int resultCode = getResultCode();
+ if (resultCode != EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK) {
+ // TODO (b/62680294): Surface more info. to the end users for this failure.
+ Log.e(TAG, "Error disabling esim, result code = " + resultCode);
+ }
+ }
+ }
+ };
+
public KeyguardEsimArea(Context context) {
this(context, null);
}
@@ -52,8 +76,10 @@ class KeyguardEsimArea extends Button implements View.OnClickListener {
}
@Override
- public void onClick(View v) {
- // STOPSHIP(b/37353596): use EuiccManager API to disable current carrier.
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_DISABLE_ESIM),
+ PERMISSION_SELF, null /* scheduler */);
}
public static boolean isEsimLocked(Context context, int subId) {
@@ -66,4 +92,23 @@ class KeyguardEsimArea extends Button implements View.OnClickListener {
return sub != null && sub.isEmbedded();
}
+ @Override
+ protected void onDetachedFromWindow() {
+ mContext.unregisterReceiver(mReceiver);
+ super.onDetachedFromWindow();
+ }
+
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(mContext, KeyguardEsimArea.class);
+ intent.setAction(ACTION_DISABLE_ESIM);
+ intent.setPackage(mContext.getPackageName());
+ PendingIntent callbackIntent = PendingIntent.getBroadcast(
+ mContext,
+ 0 /* requestCode */,
+ intent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+ mEuiccManager
+ .switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID, callbackIntent);
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index 7e811731c87d..12f75bb2d56c 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -29,10 +29,8 @@ import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.provider.Settings;
import android.text.InputType;
-import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@@ -135,7 +133,9 @@ public class PasswordTextView extends View {
}
mDrawPaint.setFlags(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
mDrawPaint.setTextAlign(Paint.Align.CENTER);
- mDrawPaint.setTypeface(Typeface.create("sans-serif-light", 0));
+ mDrawPaint.setTypeface(Typeface.create(
+ context.getString(com.android.internal.R.string.config_headlineFontFamilyLight),
+ 0));
mShowPassword = Settings.System.getInt(mContext.getContentResolver(),
Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
@@ -250,9 +250,9 @@ public class PasswordTextView extends View {
mText = mText.substring(0, length - 1);
CharState charState = mTextChars.get(length - 1);
charState.startRemoveAnimation(0, 0);
+ sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0);
}
userActivity();
- sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0);
}
public String getText() {
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 6476416a4e72..c4de63bdd303 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -235,6 +235,7 @@ public class BatteryMeterView extends LinearLayout implements
scaledLayoutParams.setMargins(0, 0, 0, marginBottom);
mBatteryIconView.setLayoutParams(scaledLayoutParams);
+ FontSizeUtils.updateFontSize(mBatteryPercentView, R.dimen.qs_time_expanded_size);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
index b35efb2e828d..61325400846a 100644
--- a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
+++ b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
@@ -55,11 +55,17 @@ public class RoundedCorners extends SystemUI implements Tunable {
public void start() {
mRoundedDefault = mContext.getResources().getDimensionPixelSize(
R.dimen.rounded_corner_radius);
- if (mRoundedDefault == 0) {
- // No rounded corners on this device.
- return;
+ if (mRoundedDefault != 0) {
+ setupRounding();
}
+ int padding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.rounded_corner_content_padding);
+ if (padding != 0) {
+ setupPadding(padding);
+ }
+ }
+ private void setupRounding() {
mOverlay = LayoutInflater.from(mContext)
.inflate(R.layout.rounded_corners, null);
mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
@@ -82,19 +88,23 @@ public class RoundedCorners extends SystemUI implements Tunable {
mDensity = metrics.density;
Dependency.get(TunerService.class).addTunable(this, SIZE);
+ }
+ private void setupPadding(int padding) {
// Add some padding to all the content near the edge of the screen.
- int padding = mContext.getResources().getDimensionPixelSize(
- R.dimen.rounded_corner_content_padding);
StatusBar sb = getComponent(StatusBar.class);
View statusBar = sb.getStatusBarWindow();
TunablePadding.addTunablePadding(statusBar.findViewById(R.id.keyguard_header), PADDING,
padding, FLAG_END);
- FragmentHostManager.get(sb.getNavigationBarWindow()).addTagListener(
+ View navigationBarWindow = sb.getNavigationBarWindow();
+ // Not all devices have on screen navigation bars.
+ if (navigationBarWindow != null) {
+ FragmentHostManager.get(navigationBarWindow).addTagListener(
NavigationBarFragment.TAG,
new TunablePaddingTagListener(padding, 0));
+ }
FragmentHostManager fragmentHostManager = FragmentHostManager.get(statusBar);
fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java b/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java
index 880951036661..4ff10e975b1a 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/ExtensionFragmentListener.java
@@ -34,12 +34,14 @@ public class ExtensionFragmentListener<T extends FragmentBase> implements Consum
private final FragmentHostManager mFragmentHostManager;
private final String mTag;
private final Extension<T> mExtension;
+ private final int mId;
private String mOldClass;
private ExtensionFragmentListener(View view, String tag, int id, Extension<T> extension) {
mTag = tag;
mFragmentHostManager = FragmentHostManager.get(view);
mExtension = extension;
+ mId = id;
mFragmentHostManager.getFragmentManager().beginTransaction()
.replace(id, (Fragment) mExtension.get(), mTag)
.commit();
@@ -49,7 +51,7 @@ public class ExtensionFragmentListener<T extends FragmentBase> implements Consum
public void accept(T extension) {
try {
Fragment.class.cast(extension);
- mFragmentHostManager.getExtensionManager().setCurrentExtension(mTag,
+ mFragmentHostManager.getExtensionManager().setCurrentExtension(mId, mTag,
mOldClass, extension.getClass().getName(), mExtension.getContext());
mOldClass = extension.getClass().getName();
} catch (ClassCastException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 871f113ac95e..f8f364da089b 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -266,16 +266,14 @@ public class FragmentHostManager {
class ExtensionFragmentManager {
private final ArrayMap<String, Context> mExtensionLookup = new ArrayMap<>();
- public void setCurrentExtension(@NonNull String tag, @Nullable String oldClass,
+ public void setCurrentExtension(int id, @NonNull String tag, @Nullable String oldClass,
@NonNull String currentClass, @Nullable Context context) {
- Fragment fragment = getFragmentManager().findFragmentByTag(tag);
if (oldClass != null) {
mExtensionLookup.remove(oldClass);
}
mExtensionLookup.put(currentClass, context);
getFragmentManager().beginTransaction()
- .replace(((View) fragment.getView().getParent()).getId(),
- instantiate(context, currentClass, null), tag)
+ .replace(id, instantiate(context, currentClass, null), tag)
.commit();
reloadFragments();
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index 32b5862e2b6b..af2b7677dcad 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -38,6 +38,7 @@ import android.util.Log;
import android.view.View;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.R;
/**
* Bouncer between work activities and the activity used to confirm credentials before unlocking
@@ -83,6 +84,7 @@ public class WorkLockActivity extends Activity {
// Blank out the activity. When it is on-screen it will look like a Recents thumbnail with
// redaction switched on.
final View blankView = new View(this);
+ blankView.setContentDescription(getString(R.string.accessibility_desc_work_lock));
blankView.setBackgroundColor(getPrimaryColor());
setContentView(blankView);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 0373d77940d7..ebf4b5d83029 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -93,6 +93,7 @@ public class PipManager implements BasePipManager {
ComponentName topPipActivity = PipUtils.getTopPinnedActivity(mContext,
mActivityManager);
mMenuController.hideMenu();
+ mTouchHandler.onActivityUnpinned(topPipActivity);
mNotificationController.onActivityUnpinned(topPipActivity);
SystemServicesProxy.getInstance(mContext).setPipVisibility(topPipActivity != null);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index ddaeb04f8443..3682ae655f7c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -25,6 +25,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.IActivityManager;
+import android.content.ComponentName;
import android.content.Context;
import android.graphics.Point;
import android.graphics.PointF;
@@ -116,7 +117,7 @@ public class PipTouchHandler {
};
// Behaviour states
- private int mMenuState;
+ private int mMenuState = MENU_STATE_NONE;
private boolean mIsMinimized;
private boolean mIsImeShowing;
private int mImeHeight;
@@ -212,14 +213,15 @@ public class PipTouchHandler {
}
public void onActivityPinned() {
- // Reset some states once we are pinned
- mMenuState = MENU_STATE_NONE;
+ cleanUp();
+ mShowPipMenuOnAnimationEnd = true;
+ }
- if (mIsMinimized) {
- setMinimizedStateInternal(false);
+ public void onActivityUnpinned(ComponentName topPipActivity) {
+ if (topPipActivity == null) {
+ // Clean up state after the last PiP activity is removed
+ cleanUp();
}
- cleanUpDismissTarget();
- mShowPipMenuOnAnimationEnd = true;
}
public void onPinnedStackAnimationEnded() {
@@ -729,6 +731,16 @@ public class PipTouchHandler {
mDismissViewController.destroyDismissTarget();
}
+ /**
+ * Resets some states related to the touch handling.
+ */
+ private void cleanUp() {
+ if (mIsMinimized) {
+ setMinimizedStateInternal(false);
+ }
+ cleanUpDismissTarget();
+ }
+
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
index f0745a0791ef..ac41b752020b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
@@ -174,7 +174,7 @@ public class PipNotification {
void onConfigurationChanged(Context context) {
Resources res = context.getResources();
mDefaultTitle = res.getString(R.string.pip_notification_unknown_title);
- mDefaultIconResId = R.drawable.pip_expand;
+ mDefaultIconResId = R.drawable.pip_icon;
if (mNotified) {
// update notification
notifyPipNotification();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 6b507645e4d0..8f1880039857 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -161,7 +161,8 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
QSTileLayout tileLayout = mQsPanel.getTileLayout();
mAllViews.add((View) tileLayout);
- int heightDiff = mQsPanel.getBottom() - mQs.getHeader().getBottom()
+ int height = mQs.getView() != null ? mQs.getView().getMeasuredHeight() : 0;
+ int heightDiff = height - mQs.getHeader().getBottom()
+ mQs.getHeader().getPaddingBottom();
firstPageBuilder.addFloat(tileLayout, "translationY", heightDiff, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 90275c50b54a..bb3672511c48 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -253,7 +253,8 @@ public class QSFragment extends Fragment implements QS {
}
mHeader.setExpansion(mKeyguardShowing ? 1 : expansion);
mFooter.setExpansion(mKeyguardShowing ? 1 : expansion);
- int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom();
+ int heightDiff = mQSPanel.getBottom() - mHeader.getBottom() + mHeader.getPaddingBottom()
+ + mFooter.getHeight();
mQSPanel.setTranslationY(translationScaleY * heightDiff);
mQSDetail.setFullyExpanded(expansion == 1);
@@ -262,7 +263,7 @@ public class QSFragment extends Fragment implements QS {
}
// Set bounds on the QS panel so it doesn't run over the header.
- mQsBounds.top = (int) (mQSPanel.getHeight() * (1 - expansion));
+ mQsBounds.top = (int) -mQSPanel.getTranslationY();
mQsBounds.right = mQSPanel.getWidth();
mQsBounds.bottom = mQSPanel.getHeight();
mQSPanel.setClipBounds(mQsBounds);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index 2d0fe6f63219..4d0e60d505f6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -32,6 +32,7 @@ import android.widget.Switch;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.*;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView {
@@ -44,6 +45,7 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView {
private String mAccessibilityClass;
private boolean mTileState;
private boolean mCollapsedView;
+ private boolean mClicked;
public QSTileBaseView(Context context, QSIconView icon) {
this(context, icon, false);
@@ -153,7 +155,11 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView {
setContentDescription(state.contentDescription);
mAccessibilityClass = state.expandedAccessibilityClassName;
if (state instanceof QSTile.BooleanState) {
- mTileState = ((QSTile.BooleanState) state).value;
+ boolean newState = ((BooleanState) state).value;
+ if (mTileState != newState) {
+ mClicked = false;
+ mTileState = newState;
+ }
}
}
@@ -173,15 +179,22 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView {
}
@Override
+ public boolean performClick() {
+ mClicked = true;
+ return super.performClick();
+ }
+
+ @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
if (!TextUtils.isEmpty(mAccessibilityClass)) {
event.setClassName(mAccessibilityClass);
if (Switch.class.getName().equals(mAccessibilityClass)) {
+ boolean b = mClicked ? !mTileState : mTileState;
String label = getResources()
- .getString(!mTileState ? R.string.switch_bar_on : R.string.switch_bar_off);
+ .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off);
event.setContentDescription(label);
- event.setChecked(!mTileState);
+ event.setChecked(b);
}
}
}
@@ -192,10 +205,11 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView {
if (!TextUtils.isEmpty(mAccessibilityClass)) {
info.setClassName(mAccessibilityClass);
if (Switch.class.getName().equals(mAccessibilityClass)) {
+ boolean b = mClicked ? !mTileState : mTileState;
String label = getResources()
- .getString(mTileState ? R.string.switch_bar_on : R.string.switch_bar_off);
+ .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off);
info.setText(label);
- info.setChecked(mTileState);
+ info.setChecked(b);
info.setCheckable(true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 918c00c2337f..089d07a567dd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -15,10 +15,13 @@
*/
package com.android.systemui.qs.tiles;
+import android.content.Context;
import android.content.Intent;
+import android.graphics.drawable.Drawable;
import android.service.quicksettings.Tile;
import android.widget.Switch;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settingslib.graph.BatteryMeterDrawableBase;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
@@ -79,7 +82,9 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements
protected void handleUpdateState(BooleanState state, Object arg) {
state.state = mCharging ? Tile.STATE_UNAVAILABLE
: mPowerSave ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
- state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver);
+ BatterySaverIcon bsi = new BatterySaverIcon();
+ bsi.mState = state.state;
+ state.icon = bsi;
state.label = mContext.getString(R.string.battery_detail_switch_title);
state.contentDescription = state.label;
state.value = mPowerSave;
@@ -99,4 +104,41 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements
mPowerSave = isPowerSave;
refreshState(null);
}
-} \ No newline at end of file
+
+ public static class BatterySaverIcon extends Icon {
+ private int mState;
+
+ @Override
+ public Drawable getDrawable(Context context) {
+ BatterySaverDrawable b = new BatterySaverDrawable(context, 0);
+ b.mState = mState;
+ final int pad = context.getResources()
+ .getDimensionPixelSize(R.dimen.qs_tile_divider_height);
+ b.setPadding(pad, pad, pad, pad);
+ return b;
+ }
+ }
+
+ private static class BatterySaverDrawable extends BatteryMeterDrawableBase {
+ private int mState;
+ private static final int MAX_BATTERY = 100;
+
+ BatterySaverDrawable(Context context, int frameColor) {
+ super(context, frameColor);
+ // Show as full so it's always uniform color
+ super.setBatteryLevel(MAX_BATTERY);
+ setPowerSave(true);
+ setCharging(false);
+ }
+
+ @Override
+ protected int batteryColorForLevel(int level) {
+ return QSTileImpl.getColorForState(mContext, mState);
+ }
+
+ @Override
+ public void setBatteryLevel(int val) {
+ // Don't change the actual level, otherwise this won't draw correctly
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index e6c3520c4d62..81ec6a7c72a9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -141,7 +141,11 @@ public class CellularTile extends QSTileImpl<SignalState> {
&& mDataController.isMobileDataEnabled();
state.icon = new SignalIcon(cb.mobileSignalIconId);
- state.state = Tile.STATE_ACTIVE;
+ if (cb.airplaneModeEnabled) {
+ state.state = Tile.STATE_INACTIVE;
+ } else {
+ state.state = Tile.STATE_ACTIVE;
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index cb9093ac4928..73915092e8b4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -32,17 +32,16 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.wifi.AccessPoint;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.R.string;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
-import com.android.systemui.qs.QSDetailItems;
-import com.android.systemui.qs.QSDetailItems.Item;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.SignalState;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.qs.QSDetailItems;
+import com.android.systemui.qs.QSDetailItems.Item;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.SignalTileView;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -188,7 +187,7 @@ public class WifiTile extends QSTileImpl<SignalState> {
minimalContentDescription.append(removeDoubleQuotes(cb.enabledDesc));
}
}
- state.contentDescription = minimalContentDescription;
+ state.contentDescription = minimalContentDescription.toString();
state.dualLabelContentDescription = r.getString(
R.string.accessibility_quick_settings_open_settings, getTileLabel());
state.expandedAccessibilityClassName = Switch.class.getName();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 86b1d3b7efce..4de121488ecc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -72,6 +72,7 @@ import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
import com.android.systemui.recents.events.ui.ShowIncompatibleAppOverlayEvent;
import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
+import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
@@ -420,8 +421,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
loader.loadTasks(this, loadPlan, loadOpts);
TaskStack stack = loadPlan.getTaskStack();
- mRecentsView.onReload(mIsVisible, stack.getTaskCount() == 0);
- mRecentsView.updateStack(stack, true /* setStackViewTasks */);
+ mRecentsView.onReload(stack, mIsVisible);
// Update the nav bar scrim, but defer the animation until the enter-window event
boolean animateNavBarScrim = !launchState.launchedViaDockGesture;
@@ -755,6 +755,10 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
ssp.removeTask(event.task.key.id);
}
+ public final void onBusEvent(TaskViewDismissedEvent event) {
+ mRecentsView.updateScrimOpacity();
+ }
+
public final void onBusEvent(AllTaskViewsDismissedEvent event) {
SystemServicesProxy ssp = Recents.getSystemServices();
if (ssp.hasDockedTask()) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 93033eae0db1..80c44a39bb0d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -71,6 +71,7 @@ public class RecentsTaskLoadPlan {
Context mContext;
+ int mPreloadedUserId;
List<ActivityManager.RecentTaskInfo> mRawTasks;
TaskStack mStack;
ArraySet<Integer> mCurrentQuietProfiles = new ArraySet<Integer>();
@@ -83,9 +84,6 @@ public class RecentsTaskLoadPlan {
private void updateCurrentQuietProfilesCache(int currentUserId) {
mCurrentQuietProfiles.clear();
- if (currentUserId == UserHandle.USER_CURRENT) {
- currentUserId = SystemServicesProxy.getInstance(mContext).getCurrentUser();
- }
UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
List<UserInfo> profiles = userManager.getProfiles(currentUserId);
if (profiles != null) {
@@ -105,9 +103,10 @@ public class RecentsTaskLoadPlan {
* Note: Do not lock, callers should synchronize on the loader before making this call.
*/
void preloadRawTasks(boolean includeFrontMostExcludedTask) {
- int currentUserId = UserHandle.USER_CURRENT;
- updateCurrentQuietProfilesCache(currentUserId);
SystemServicesProxy ssp = Recents.getSystemServices();
+ int currentUserId = ssp.getCurrentUser();
+ updateCurrentQuietProfilesCache(currentUserId);
+ mPreloadedUserId = currentUserId;
mRawTasks = ssp.getRecentTasks(ActivityManager.getMaxRecentTasksStatic(),
currentUserId, includeFrontMostExcludedTask, mCurrentQuietProfiles);
@@ -135,7 +134,6 @@ public class RecentsTaskLoadPlan {
preloadRawTasks(includeFrontMostExcludedTask);
}
- SystemServicesProxy ssp = SystemServicesProxy.getInstance(mContext);
SparseArray<Task.TaskKey> affiliatedTasks = new SparseArray<>();
SparseIntArray affiliatedTaskCounts = new SparseIntArray();
SparseBooleanArray lockedUsers = new SparseBooleanArray();
@@ -143,7 +141,7 @@ public class RecentsTaskLoadPlan {
R.string.accessibility_recents_item_will_be_dismissed);
String appInfoDescFormat = mContext.getString(
R.string.accessibility_recents_item_open_app_info);
- int currentUserId = ssp.getCurrentUser();
+ int currentUserId = mPreloadedUserId;
long legacyLastStackActiveTime = migrateLegacyLastStackActiveTime(currentUserId);
long lastStackActiveTime = Settings.Secure.getLongForUser(mContext.getContentResolver(),
Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, legacyLastStackActiveTime, currentUserId);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index d710244988cb..9ca756c5431f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -31,6 +31,7 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.ArraySet;
import android.util.AttributeSet;
+import android.util.MathUtils;
import android.view.AppTransitionAnimationSpec;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -79,6 +80,7 @@ import com.android.systemui.recents.views.RecentsTransitionHelper.AnimationSpecC
import com.android.systemui.recents.views.RecentsTransitionHelper.AppTransitionAnimationSpecsFuture;
import com.android.systemui.stackdivider.WindowManagerProxy;
import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.android.systemui.statusbar.phone.ScrimController;
import com.google.android.colorextraction.ColorExtractor;
import com.google.android.colorextraction.drawable.GradientDrawable;
@@ -96,11 +98,12 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
private static final String TAG = "RecentsView";
private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
- private static final float DEFAULT_SCRIM_ALPHA = 0.8f;
private static final int SHOW_STACK_ACTION_BUTTON_DURATION = 134;
private static final int HIDE_STACK_ACTION_BUTTON_DURATION = 100;
+ private static final int BUSY_RECENTS_TASK_COUNT = 3;
+
private TaskStackView mTaskStackView;
private TextView mStackActionButton;
private TextView mEmptyView;
@@ -112,7 +115,7 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
Rect mSystemInsets = new Rect();
private int mDividerSize;
- private final float mScrimAlpha;
+ private float mBusynessFactor;
private GradientDrawable mBackgroundScrim;
private final SysuiColorExtractor mColorExtractor;
private Animator mBackgroundScrimAnimator;
@@ -143,10 +146,8 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
mDividerSize = ssp.getDockedDividerSize(context);
mTouchHandler = new RecentsViewTouchHandler(this);
mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
- mScrimAlpha = DEFAULT_SCRIM_ALPHA;
mBackgroundScrim = new GradientDrawable(context);
mBackgroundScrim.setCallback(this);
- mBackgroundScrim.setAlpha((int) (mScrimAlpha * 255));
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
LayoutInflater inflater = LayoutInflater.from(context);
@@ -168,9 +169,10 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
/**
* Called from RecentsActivity when it is relaunched.
*/
- public void onReload(boolean isResumingFromVisible, boolean isTaskStackEmpty) {
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
+ public void onReload(TaskStack stack, boolean isResumingFromVisible) {
+ final RecentsConfiguration config = Recents.getConfiguration();
+ final RecentsActivityLaunchState launchState = config.getLaunchState();
+ final boolean isTaskStackEmpty = stack.getTaskCount() == 0;
if (mTaskStackView == null) {
isResumingFromVisible = false;
@@ -185,17 +187,19 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
// Update the stack
mTaskStackView.onReload(isResumingFromVisible);
+ updateStack(stack, true /* setStackViewTasks */);
+ updateBusyness();
if (isResumingFromVisible) {
// If we are already visible, then restore the background scrim
- animateBackgroundScrim(1f, DEFAULT_UPDATE_SCRIM_DURATION);
+ animateBackgroundScrim(getOpaqueScrimAlpha(), DEFAULT_UPDATE_SCRIM_DURATION);
} else {
// If we are already occluded by the app, then set the final background scrim alpha now.
// Otherwise, defer until the enter animation completes to animate the scrim alpha with
// the tasks for the home animation.
if (launchState.launchedViaDockGesture || launchState.launchedFromApp
|| isTaskStackEmpty) {
- mBackgroundScrim.setAlpha((int) (mScrimAlpha * 255));
+ mBackgroundScrim.setAlpha((int) (getOpaqueScrimAlpha() * 255));
} else {
mBackgroundScrim.setAlpha(0);
}
@@ -219,13 +223,40 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
}
/**
+ * Animates the scrim opacity based on how many tasks are visible.
+ * Called from {@link RecentsActivity} when tasks are dismissed.
+ */
+ public void updateScrimOpacity() {
+ if (updateBusyness()) {
+ animateBackgroundScrim(getOpaqueScrimAlpha(), DEFAULT_UPDATE_SCRIM_DURATION);
+ }
+ }
+
+ /**
+ * Updates the busyness factor.
+ *
+ * @return True if it changed.
+ */
+ private boolean updateBusyness() {
+ final int taskCount = mTaskStackView.getStack().getStackTaskCount();
+ final float busyness = Math.min(taskCount, BUSY_RECENTS_TASK_COUNT)
+ / (float) BUSY_RECENTS_TASK_COUNT;
+ if (mBusynessFactor == busyness) {
+ return false;
+ } else {
+ mBusynessFactor = busyness;
+ return true;
+ }
+ }
+
+ /**
* Returns the current TaskStack.
*/
public TaskStack getStack() {
return mTaskStackView.getStack();
}
- /*
+ /**
* Returns the window background scrim.
*/
public Drawable getBackgroundScrim() {
@@ -619,7 +650,7 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
if (!launchState.launchedViaDockGesture && !launchState.launchedFromApp
&& getStack().getTaskCount() > 0) {
- animateBackgroundScrim(1f,
+ animateBackgroundScrim(getOpaqueScrimAlpha(),
TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION);
}
}
@@ -779,13 +810,25 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
}
/**
+ * Scrim alpha based on how busy recents is:
+ * Scrim will be {@link ScrimController#GRADIENT_SCRIM_ALPHA} when the stack is empty,
+ * and {@link ScrimController#GRADIENT_SCRIM_ALPHA_BUSY} when it's full.
+ *
+ * @return Alpha from 0 to 1.
+ */
+ private float getOpaqueScrimAlpha() {
+ return MathUtils.map(0, 1, ScrimController.GRADIENT_SCRIM_ALPHA,
+ ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mBusynessFactor);
+ }
+
+ /**
* Animates the background scrim to the given {@param alpha}.
*/
private void animateBackgroundScrim(float alpha, int duration) {
Utilities.cancelAnimationWithoutCallbacks(mBackgroundScrimAnimator);
// Calculate the absolute alpha to animate from
- int fromAlpha = mBackgroundScrim.getAlpha();
- int toAlpha = (int) (alpha * mScrimAlpha * 255);
+ final int fromAlpha = mBackgroundScrim.getAlpha();
+ final int toAlpha = (int) (alpha * 255);
mBackgroundScrimAnimator = ObjectAnimator.ofInt(mBackgroundScrim, Utilities.DRAWABLE_ALPHA,
fromAlpha, toAlpha);
mBackgroundScrimAnimator.setDuration(duration);
@@ -835,7 +878,8 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
// Recents doesn't care about the wallpaper being visible or not, it always
// wants to scrim with wallpaper colors
mBackgroundScrim.setColors(
- mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM, true));
+ mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
+ ColorExtractor.TYPE_DARK, true));
}
}
@@ -843,7 +887,7 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC
mColorExtractor.addOnColorsChangedListener(this);
// Getting system scrim colors ignoring wallpaper visibility since it should never be grey.
ColorExtractor.GradientColors systemColors = mColorExtractor.getColors(
- WallpaperManager.FLAG_SYSTEM, true);
+ ColorExtractor.TYPE_DARK, WallpaperManager.FLAG_SYSTEM, true);
// We don't want to interpolate colors because we're defining the initial state.
// Gradient should be set/ready when you open "Recents".
mBackgroundScrim.setColors(systemColors, false);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index a7b845e2e62c..a2409d1f5583 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -50,6 +50,7 @@ import android.os.Process;
import android.os.UserHandle;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
+import android.util.Slog;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -100,6 +101,7 @@ class SaveImageInBackgroundData {
* An AsyncTask that saves an image to the media store in the background.
*/
class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
+ private static final String TAG = "SaveImageInBackgroundTask";
private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
@@ -303,6 +305,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
} catch (Exception e) {
// IOException/UnsupportedOperationException may be thrown if external storage is not
// mounted
+ Slog.e(TAG, "unable to save screenshot", e);
mParams.clearImage();
mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
}
@@ -379,8 +382,6 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
* An AsyncTask that deletes an image from the media store in the background.
*/
class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> {
- private static final String TAG = "DeleteImageInBackgroundTask";
-
private Context mContext;
DeleteImageInBackgroundTask(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index bae6a275800a..eec818b2c9b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -303,7 +303,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
@Override
public boolean performClick() {
- if (mWasActivatedOnDown || !mNeedsDimming) {
+ if (mWasActivatedOnDown || !mNeedsDimming || isTouchExplorationEnabled()) {
return super.performClick();
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index c0691c11a286..e5b1afe31370 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -568,8 +568,6 @@ public class NotificationData {
mTmpRanking.getImportance());
pw.print(indent);
pw.println(" notification=" + n.getNotification());
- pw.print(indent);
- pw.println(" tickerText=\"" + n.getNotification().tickerText + "\"");
}
private static boolean isSystemNotification(StatusBarNotification sbn) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 5a163d4d56c2..f8591247f1d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -417,7 +417,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
@Override
public void onHeightUpdate() {
- if (mParent == null || mMenuItems.size() == 0) {
+ if (mParent == null || mMenuItems.size() == 0 || mMenuContainer == null) {
return;
}
int parentHeight = mParent.getCollapsedHeight();
@@ -477,7 +477,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
private void setMenuLocation() {
boolean showOnLeft = mTranslation > 0;
- if ((mIconsPlaced && showOnLeft == mOnLeft) || mSnapping
+ if ((mIconsPlaced && showOnLeft == mOnLeft) || mSnapping || mMenuContainer == null
|| !mMenuContainer.isAttachedToWindow()) {
// Do nothing
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 67ea25870a45..97e2f6d3e6f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -465,7 +465,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
|| row.getTranslationZ() > mAmbientState.getBaseZHeight()))) {
iconState.hidden = true;
}
- int shelfColor = icon.getStaticDrawableColor();
+ int backgroundColor = getBackgroundColorWithoutTint();
+ int shelfColor = icon.getContrastedStaticDrawableColor(backgroundColor);
if (!noIcon && shelfColor != StatusBarIconView.NO_COLOR) {
int iconColor = row.getVisibleNotificationHeader().getOriginalIconColor();
shelfColor = NotificationUtils.interpolateColors(iconColor, shelfColor,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
index 0e5e4161c886..c45ca54024db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
@@ -21,11 +21,14 @@ import java.util.List;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
+import android.os.Bundle;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.text.SpannableString;
@@ -35,6 +38,9 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -45,6 +51,10 @@ import com.android.systemui.R;
public class NotificationSnooze extends LinearLayout
implements NotificationGuts.GutsContent, View.OnClickListener {
+ /**
+ * If this changes more number increases, more assistant action resId's should be defined for
+ * accessibility purposes, see {@link #setSnoozeOptions(List)}
+ */
private static final int MAX_ASSISTANT_SUGGESTIONS = 1;
private NotificationGuts mGutsContainer;
private NotificationSwipeActionHelper mSnoozeListener;
@@ -79,16 +89,60 @@ public class NotificationSnooze extends LinearLayout
mDivider = findViewById(R.id.divider);
mDivider.setAlpha(0f);
mSnoozeOptionContainer = (ViewGroup) findViewById(R.id.snooze_options);
+ mSnoozeOptionContainer.setVisibility(View.INVISIBLE);
mSnoozeOptionContainer.setAlpha(0f);
// Create the different options based on list
mSnoozeOptions = getDefaultSnoozeOptions();
createOptionViews();
- // Default to first option in list
setSelected(mDefaultOption);
}
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ if (mGutsContainer != null && mGutsContainer.isExposed()) {
+ if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+ event.getText().add(mSelectedOptionText.getText());
+ }
+ }
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.addAction(new AccessibilityAction(R.id.action_snooze_undo,
+ getResources().getString(R.string.snooze_undo)));
+ int count = mSnoozeOptions.size();
+ for (int i = 0; i < count; i++) {
+ AccessibilityAction action = mSnoozeOptions.get(i).getAccessibilityAction();
+ if (action != null) {
+ info.addAction(action);
+ }
+ }
+ }
+
+ @Override
+ public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+ if (super.performAccessibilityActionInternal(action, arguments)) {
+ return true;
+ }
+ if (action == R.id.action_snooze_undo) {
+ undoSnooze(mUndoButton);
+ return true;
+ }
+ for (int i = 0; i < mSnoozeOptions.size(); i++) {
+ SnoozeOption so = mSnoozeOptions.get(i);
+ if (so.getAccessibilityAction() != null
+ && so.getAccessibilityAction().getId() == action) {
+ setSelected(so);
+ return true;
+ }
+ }
+ return false;
+ }
+
public void setSnoozeOptions(final List<SnoozeCriterion> snoozeList) {
if (snoozeList == null) {
return;
@@ -98,7 +152,10 @@ public class NotificationSnooze extends LinearLayout
final int count = Math.min(MAX_ASSISTANT_SUGGESTIONS, snoozeList.size());
for (int i = 0; i < count; i++) {
SnoozeCriterion sc = snoozeList.get(i);
- mSnoozeOptions.add(new SnoozeOption(sc, 0, sc.getExplanation(), sc.getConfirmation()));
+ AccessibilityAction action = new AccessibilityAction(
+ R.id.action_snooze_assistant_suggestion_1, sc.getExplanation());
+ mSnoozeOptions.add(new NotificationSnoozeOption(sc, 0, sc.getExplanation(),
+ sc.getConfirmation(), action));
}
createOptionViews();
}
@@ -117,15 +174,16 @@ public class NotificationSnooze extends LinearLayout
private ArrayList<SnoozeOption> getDefaultSnoozeOptions() {
ArrayList<SnoozeOption> options = new ArrayList<>();
- options.add(createOption(15 /* minutes */));
- options.add(createOption(30 /* minutes */));
- mDefaultOption = createOption(60 /* minutes */);
+
+ options.add(createOption(15 /* minutes */, R.id.action_snooze_15_min));
+ options.add(createOption(30 /* minutes */, R.id.action_snooze_30_min));
+ mDefaultOption = createOption(60 /* minutes */, R.id.action_snooze_1_hour);
options.add(mDefaultOption);
- options.add(createOption(60 * 2 /* minutes */));
+ options.add(createOption(60 * 2 /* minutes */, R.id.action_snooze_2_hours));
return options;
}
- private SnoozeOption createOption(int minutes) {
+ private SnoozeOption createOption(int minutes, int accessibilityActionId) {
Resources res = getResources();
boolean showInHours = minutes >= 60;
int pluralResId = showInHours
@@ -137,7 +195,9 @@ public class NotificationSnooze extends LinearLayout
SpannableString string = new SpannableString(resultText);
string.setSpan(new StyleSpan(Typeface.BOLD),
resultText.length() - description.length(), resultText.length(), 0 /* flags */);
- return new SnoozeOption(null, minutes, description, string);
+ AccessibilityAction action = new AccessibilityAction(accessibilityActionId, description);
+ return new NotificationSnoozeOption(null, minutes, description, string,
+ action);
}
private void createOptionViews() {
@@ -149,7 +209,7 @@ public class NotificationSnooze extends LinearLayout
TextView tv = (TextView) inflater.inflate(R.layout.notification_snooze_option,
mSnoozeOptionContainer, false);
mSnoozeOptionContainer.addView(tv);
- tv.setText(option.description);
+ tv.setText(option.getDescription());
tv.setTag(option);
tv.setOnClickListener(this);
}
@@ -184,18 +244,36 @@ public class NotificationSnooze extends LinearLayout
mDivider.getAlpha(), show ? 1f : 0f);
ObjectAnimator optionAnim = ObjectAnimator.ofFloat(mSnoozeOptionContainer, View.ALPHA,
mSnoozeOptionContainer.getAlpha(), show ? 1f : 0f);
+ mSnoozeOptionContainer.setVisibility(View.VISIBLE);
mExpandAnimation = new AnimatorSet();
mExpandAnimation.playTogether(dividerAnim, optionAnim);
mExpandAnimation.setDuration(150);
mExpandAnimation.setInterpolator(show ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+ mExpandAnimation.addListener(new AnimatorListenerAdapter() {
+ boolean cancelled = false;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ cancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!show && !cancelled) {
+ mSnoozeOptionContainer.setVisibility(View.INVISIBLE);
+ mSnoozeOptionContainer.setAlpha(0f);
+ }
+ }
+ });
mExpandAnimation.start();
}
private void setSelected(SnoozeOption option) {
mSelectedOption = option;
- mSelectedOptionText.setText(option.confirmation);
+ mSelectedOptionText.setText(option.getConfirmation());
showSnoozeOptions(false);
hideSelectedOption();
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
@Override
@@ -212,20 +290,24 @@ public class NotificationSnooze extends LinearLayout
showSnoozeOptions(!mExpanded);
} else {
// Undo snooze was selected
- mSelectedOption = null;
- int[] parentLoc = new int[2];
- int[] targetLoc = new int[2];
- mGutsContainer.getLocationOnScreen(parentLoc);
- v.getLocationOnScreen(targetLoc);
- final int centerX = v.getWidth() / 2;
- final int centerY = v.getHeight() / 2;
- final int x = targetLoc[0] - parentLoc[0] + centerX;
- final int y = targetLoc[1] - parentLoc[1] + centerY;
- showSnoozeOptions(false);
- mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
+ undoSnooze(v);
}
}
+ private void undoSnooze(View v) {
+ mSelectedOption = null;
+ int[] parentLoc = new int[2];
+ int[] targetLoc = new int[2];
+ mGutsContainer.getLocationOnScreen(parentLoc);
+ v.getLocationOnScreen(targetLoc);
+ final int centerX = v.getWidth() / 2;
+ final int centerY = v.getHeight() / 2;
+ final int x = targetLoc[0] - parentLoc[0] + centerX;
+ final int y = targetLoc[1] - parentLoc[1] + centerY;
+ showSnoozeOptions(false);
+ mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
+ }
+
@Override
public int getActualHeight() {
return mExpanded ? getHeight() : mCollapsedHeight;
@@ -270,4 +352,48 @@ public class NotificationSnooze extends LinearLayout
public boolean isLeavebehind() {
return true;
}
+
+ public class NotificationSnoozeOption implements SnoozeOption {
+ private SnoozeCriterion mCriterion;
+ private int mMinutesToSnoozeFor;
+ private CharSequence mDescription;
+ private CharSequence mConfirmation;
+ private AccessibilityAction mAction;
+
+ public NotificationSnoozeOption(SnoozeCriterion sc, int minToSnoozeFor,
+ CharSequence description,
+ CharSequence confirmation, AccessibilityAction action) {
+ mCriterion = sc;
+ mMinutesToSnoozeFor = minToSnoozeFor;
+ mDescription = description;
+ mConfirmation = confirmation;
+ mAction = action;
+ }
+
+ @Override
+ public SnoozeCriterion getSnoozeCriterion() {
+ return mCriterion;
+ }
+
+ @Override
+ public CharSequence getDescription() {
+ return mDescription;
+ }
+
+ @Override
+ public CharSequence getConfirmation() {
+ return mConfirmation;
+ }
+
+ @Override
+ public int getMinutesToSnoozeFor() {
+ return mMinutesToSnoozeFor;
+ }
+
+ @Override
+ public AccessibilityAction getAccessibilityAction() {
+ return mAction;
+ }
+
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 3c7ddb502145..89694b33e035 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -35,6 +35,7 @@ import android.graphics.drawable.Icon;
import android.os.Parcelable;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
+import android.support.v4.graphics.ColorUtils;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.FloatProperty;
@@ -46,6 +47,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Interpolator;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationIconDozeHelper;
@@ -127,6 +129,8 @@ public class StatusBarIconView extends AnimatedImageView {
setColorInternal(newColor);
};
private final NotificationIconDozeHelper mDozer;
+ private int mContrastedDrawableColor;
+ private int mCachedContrastBackgroundColor = NO_COLOR;
public StatusBarIconView(Context context, String slot, StatusBarNotification sbn) {
this(context, slot, sbn, false);
@@ -528,6 +532,7 @@ public class StatusBarIconView extends AnimatedImageView {
public void setStaticDrawableColor(int color) {
mDrawableColor = color;
setColorInternal(color);
+ updateContrastedStaticColor();
mIconColor = color;
mDozer.setColor(color);
}
@@ -580,6 +585,43 @@ public class StatusBarIconView extends AnimatedImageView {
return mDrawableColor;
}
+ /**
+ * A drawable color that passes GAR on a specific background.
+ * This value is cached.
+ *
+ * @param backgroundColor Background to test against.
+ * @return GAR safe version of {@link StatusBarIconView#getStaticDrawableColor()}.
+ */
+ int getContrastedStaticDrawableColor(int backgroundColor) {
+ if (mCachedContrastBackgroundColor != backgroundColor) {
+ mCachedContrastBackgroundColor = backgroundColor;
+ updateContrastedStaticColor();
+ }
+ return mContrastedDrawableColor;
+ }
+
+ private void updateContrastedStaticColor() {
+ if (Color.alpha(mCachedContrastBackgroundColor) != 255) {
+ mContrastedDrawableColor = mDrawableColor;
+ return;
+ }
+ // We'll modify the color if it doesn't pass GAR
+ int contrastedColor = mDrawableColor;
+ if (!NotificationColorUtil.satisfiesTextContrast(mCachedContrastBackgroundColor,
+ contrastedColor)) {
+ float[] hsl = new float[3];
+ ColorUtils.colorToHSL(mDrawableColor, hsl);
+ // This is basically a light grey, pushing the color will only distort it.
+ // Best thing to do in here is to fallback to the default color.
+ if (hsl[1] < 0.2f) {
+ contrastedColor = Notification.COLOR_DEFAULT;
+ }
+ contrastedColor = NotificationColorUtil.resolveContrastColor(mContext,
+ contrastedColor, mCachedContrastBackgroundColor);
+ }
+ mContrastedDrawableColor = contrastedColor;
+ }
+
public void setVisibleState(int state) {
setVisibleState(state, true /* animate */, null /* endRunnable */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
index 7eaa290c9d23..bf926c625e4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
@@ -48,6 +48,7 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class NotificationInflater {
+ public static final String TAG = "NotificationInflater";
@VisibleForTesting
static final int FLAG_REINFLATE_ALL = ~0;
private static final int FLAG_REINFLATE_CONTENT_VIEW = 1<<0;
@@ -315,7 +316,8 @@ public class NotificationInflater {
return cancellationSignal;
}
- private static void applyRemoteView(final InflationProgress result,
+ @VisibleForTesting
+ static void applyRemoteView(final InflationProgress result,
final int reInflateFlags, int inflationId,
final ExpandableNotificationRow row,
final boolean redactAmbient, boolean isNewView,
@@ -325,6 +327,7 @@ public class NotificationInflater {
NotificationViewWrapper existingWrapper,
final HashMap<Integer, CancellationSignal> runningInflations,
ApplyCallback applyCallback) {
+ RemoteViews newContentView = applyCallback.getRemoteView();
RemoteViews.OnViewAppliedListener listener
= new RemoteViews.OnViewAppliedListener() {
@@ -343,12 +346,31 @@ public class NotificationInflater {
@Override
public void onError(Exception e) {
- runningInflations.remove(inflationId);
- handleInflationError(runningInflations, e, entry.notification, callback);
+ // Uh oh the async inflation failed. Due to some bugs (see b/38190555), this could
+ // actually also be a system issue, so let's try on the UI thread again to be safe.
+ try {
+ View newView = existingView;
+ if (isNewView) {
+ newView = newContentView.apply(
+ result.packageContext,
+ parentLayout,
+ remoteViewClickHandler);
+ } else {
+ newContentView.reapply(
+ result.packageContext,
+ existingView,
+ remoteViewClickHandler);
+ }
+ Log.wtf(TAG, "Async Inflation failed but normal inflation finished normally.",
+ e);
+ onViewApplied(newView);
+ } catch (Exception anotherException) {
+ runningInflations.remove(inflationId);
+ handleInflationError(runningInflations, e, entry.notification, callback);
+ }
}
};
CancellationSignal cancellationSignal;
- RemoteViews newContentView = applyCallback.getRemoteView();
if (isNewView) {
cancellationSignal = newContentView.applyAsync(
result.packageContext,
@@ -620,14 +642,16 @@ public class NotificationInflater {
}
}
- private static class InflationProgress {
+ @VisibleForTesting
+ static class InflationProgress {
private RemoteViews newContentView;
private RemoteViews newHeadsUpView;
private RemoteViews newExpandedView;
private RemoteViews newAmbientView;
private RemoteViews newPublicView;
- private Context packageContext;
+ @VisibleForTesting
+ Context packageContext;
private View inflatedContentView;
private View inflatedHeadsUpView;
@@ -636,7 +660,8 @@ public class NotificationInflater {
private View inflatedPublicView;
}
- private abstract static class ApplyCallback {
+ @VisibleForTesting
+ abstract static class ApplyCallback {
public abstract void setResultView(View v);
public abstract RemoteViews getRemoteView();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFrame.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFrame.java
new file mode 100644
index 000000000000..741f7839f455
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFrame.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static android.view.MotionEvent.ACTION_OUTSIDE;
+
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+import com.android.systemui.statusbar.policy.DeadZone;
+
+public class NavigationBarFrame extends FrameLayout {
+
+ private DeadZone mDeadZone = null;
+
+ public NavigationBarFrame(@NonNull Context context) {
+ super(context);
+ }
+
+ public NavigationBarFrame(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public NavigationBarFrame(@NonNull Context context, @Nullable AttributeSet attrs,
+ @AttrRes int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public void setDeadZone(@NonNull DeadZone deadZone) {
+ mDeadZone = deadZone;
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ if (event.getAction() == ACTION_OUTSIDE) {
+ if (mDeadZone != null) {
+ return mDeadZone.onTouchEvent(event);
+ }
+ }
+ return super.dispatchTouchEvent(event);
+ }
+} \ No newline at end of file
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 cb3222d6d287..a6cd472f2686 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -249,9 +249,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
if (mGestureHelper.onTouchEvent(event)) {
return true;
}
- if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
- mDeadZone.poke(event);
- }
return super.onTouchEvent(event);
}
@@ -612,9 +609,8 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
public void reorient() {
updateCurrentView();
- getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
-
mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
+ ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
mDeadZone.setDisplayRotation(mCurrentRotation);
// force the low profile & disabled states into compliance
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 95c2fc8df704..16d85bec4829 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -304,10 +304,10 @@ public abstract class PanelView extends FrameLayout {
trackMovement(event);
if (!mGestureWaitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning)
|| mPeekAnimator != null) {
- cancelHeightAnimator();
- cancelPeek();
mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning)
|| mPeekAnimator != null;
+ cancelHeightAnimator();
+ cancelPeek();
onTrackingStarted();
}
if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp()) {
@@ -612,6 +612,9 @@ public abstract class PanelView extends FrameLayout {
protected void cancelHeightAnimator() {
if (mHeightAnimator != null) {
+ if (mHeightAnimator.isRunning()) {
+ mPanelUpdateWhenAnimatorEnds = false;
+ }
mHeightAnimator.cancel();
}
endClosing();
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 bc278e0c3c2d..754c34486954 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -58,14 +58,14 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR_LOCKED
= new PathInterpolator(0.3f, 0f, 0.8f, 1f);
// Default alpha value for most scrims, if unsure use this constant
- public static final float GRADIENT_SCRIM_ALPHA = 0.60f;
+ public static final float GRADIENT_SCRIM_ALPHA = 0.45f;
// A scrim varies its opacity based on a busyness factor, for example
// how many notifications are currently visible.
- public static final float GRADIENT_SCRIM_ALPHA_BUSY = 0.90f;
+ public static final float GRADIENT_SCRIM_ALPHA_BUSY = 0.70f;
protected static final float SCRIM_BEHIND_ALPHA_KEYGUARD = GRADIENT_SCRIM_ALPHA;
protected static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
- private static final float SCRIM_IN_FRONT_ALPHA = GRADIENT_SCRIM_ALPHA;
- private static final float SCRIM_IN_FRONT_ALPHA_LOCKED = GRADIENT_SCRIM_ALPHA;
+ private static final float SCRIM_IN_FRONT_ALPHA = GRADIENT_SCRIM_ALPHA_BUSY;
+ private static final float SCRIM_IN_FRONT_ALPHA_LOCKED = GRADIENT_SCRIM_ALPHA_BUSY;
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;
@@ -81,9 +81,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
private final SysuiColorExtractor mColorExtractor;
private ColorExtractor.GradientColors mLockColors;
- private ColorExtractor.GradientColors mLockColorsDark;
private ColorExtractor.GradientColors mSystemColors;
- private ColorExtractor.GradientColors mSystemColorsDark;
private boolean mNeedsDrawableColorUpdate;
protected float mScrimBehindAlpha;
@@ -135,13 +133,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
mColorExtractor.addOnColorsChangedListener(this);
mLockColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
- ColorExtractor.TYPE_NORMAL, true /* ignoreVisibility */);
- mSystemColors = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
- ColorExtractor.TYPE_NORMAL, true /* ignoreVisibility */);
- // Darker gradient for the top scrim (mScrimInFront)
- mLockColorsDark = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
ColorExtractor.TYPE_DARK, true /* ignoreVisibility */);
- mSystemColorsDark = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
+ mSystemColors = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
ColorExtractor.TYPE_DARK, true /* ignoreVisibility */);
mNeedsDrawableColorUpdate = true;
@@ -311,13 +304,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
mNeedsDrawableColorUpdate = false;
if (mKeyguardShowing) {
// Always animate color changes if we're seeing the keyguard
- mScrimInFront.setColors(mLockColorsDark);
+ mScrimInFront.setColors(mLockColors);
mScrimBehind.setColors(mLockColors);
} else {
// Only animate scrim color if the scrim view is actually visible
boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0;
boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0;
- mScrimInFront.setColors(mSystemColorsDark, animateScrimInFront);
+ mScrimInFront.setColors(mSystemColors, animateScrimInFront);
mScrimBehind.setColors(mSystemColors, animateScrimBehind);
}
}
@@ -663,16 +656,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
public void onColorsChanged(ColorExtractor colorExtractor, int which) {
if ((which & WallpaperManager.FLAG_LOCK) != 0) {
mLockColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
- ColorExtractor.TYPE_NORMAL, true /* ignoreVisibility */);
- mLockColorsDark = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
ColorExtractor.TYPE_DARK, true /* ignoreVisibility */);
mNeedsDrawableColorUpdate = true;
scheduleUpdate();
}
if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
mSystemColors = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
- ColorExtractor.TYPE_NORMAL, mKeyguardShowing);
- mSystemColorsDark = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
ColorExtractor.TYPE_DARK, mKeyguardShowing);
mNeedsDrawableColorUpdate = true;
scheduleUpdate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
index 083da518eba4..deea521b7c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
@@ -21,13 +21,15 @@ import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
+import android.graphics.Matrix;
import android.graphics.Paint;
-import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Path.FillType;
import android.graphics.Path.Op;
+import android.graphics.PointF;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.LayoutDirection;
@@ -63,6 +65,7 @@ public class SignalDrawable extends Drawable {
private static final int STATE_EMPTY = 1;
private static final int STATE_CUT = 2;
private static final int STATE_CARRIER_CHANGE = 3;
+ private static final int STATE_AIRPLANE = 4;
private static final long DOT_DELAY = 1000;
@@ -97,6 +100,17 @@ public class SignalDrawable extends Drawable {
// How far the circle defining the corners is inset from the edges
private final float mAppliedCornerInset;
+ // The easiest way to understand this is as if we set Style.STROKE and draw the triangle,
+ // but that is only theoretically right. Instead, draw the triangle and clip out a smaller
+ // one inset by this amount.
+ private final float mEmptyStrokeWidth;
+ private static final float INV_TAN = 1f / (float) Math.tan(Math.PI / 8f);
+ private final float mEmptyDiagInset; // == mEmptyStrokeWidth * INV_TAN
+
+ // Where the top and left points of the triangle would be if not for rounding
+ private final PointF mVirtualTop = new PointF();
+ private final PointF mVirtualLeft = new PointF();
+
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mForegroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final int mDarkModeBackgroundColor;
@@ -106,6 +120,10 @@ public class SignalDrawable extends Drawable {
private final Path mFullPath = new Path();
private final Path mForegroundPath = new Path();
private final Path mXPath = new Path();
+ // Cut out when STATE_EMPTY
+ private final Path mCutPath = new Path();
+ // Draws the slash when in airplane mode
+ private final SlashArtist mSlash = new SlashArtist();
private final Handler mHandler;
private float mOldDarkIntensity = -1;
private float mNumLevels = 1;
@@ -126,6 +144,12 @@ public class SignalDrawable extends Drawable {
mLightModeFillColor =
Utils.getDefaultColor(context, R.color.light_mode_icon_color_dual_tone_fill);
mIntrinsicSize = context.getResources().getDimensionPixelSize(R.dimen.signal_icon_size);
+
+ // mCutPath parameters
+ mEmptyStrokeWidth = context.getResources()
+ .getDimensionPixelSize(R.dimen.mobile_signal_empty_strokewidth);
+ mEmptyDiagInset = mEmptyStrokeWidth * INV_TAN;
+
mHandler = new Handler();
setDarkIntensity(0);
@@ -224,9 +248,10 @@ public class SignalDrawable extends Drawable {
}
mFullPath.reset();
mFullPath.setFillType(FillType.WINDING);
+
final float width = getBounds().width();
final float height = getBounds().height();
- final float padding = (int) (PAD * width); // Stay on pixel boundary
+ final float padding = Math.round(PAD * width);
final float cornerRadius = RADIUS_RATIO * height;
// Offset from circle where the hypotenuse meets the circle
final float diagOffset = DIAG_OFFSET_MULTIPLIER * cornerRadius;
@@ -292,10 +317,37 @@ public class SignalDrawable extends Drawable {
mFullPath.rLineTo(0, cut);
}
- mPaint.setStyle(mState == STATE_EMPTY ? Style.STROKE : Style.FILL);
- mForegroundPaint.setStyle(mState == STATE_EMPTY ? Style.STROKE : Style.FILL);
-
- if (mState != STATE_CARRIER_CHANGE) {
+ if (mState == STATE_EMPTY) {
+ // Where the corners would be if this were a real triangle
+ mVirtualTop.set(
+ width - padding,
+ (padding + cornerRadius + mAppliedCornerInset) - (INV_TAN * cornerRadius));
+ mVirtualLeft.set(
+ (padding + cornerRadius + mAppliedCornerInset) - (INV_TAN * cornerRadius),
+ height - padding);
+
+ // Cut out a smaller triangle from the center of mFullPath
+ mCutPath.reset();
+ mCutPath.setFillType(FillType.WINDING);
+ mCutPath.moveTo(width - padding - mEmptyStrokeWidth,
+ height - padding - mEmptyStrokeWidth);
+ mCutPath.lineTo(width - padding - mEmptyStrokeWidth,
+ mVirtualTop.y + mEmptyDiagInset);
+ mCutPath.lineTo(mVirtualLeft.x + mEmptyDiagInset,
+ height - padding - mEmptyStrokeWidth);
+ mCutPath.lineTo(width - padding - mEmptyStrokeWidth,
+ height - padding - mEmptyStrokeWidth);
+
+ // In empty state, draw the full path as the foreground paint
+ mForegroundPath.set(mFullPath);
+ mFullPath.reset();
+ mForegroundPath.op(mCutPath, Path.Op.DIFFERENCE);
+ } else if (mState == STATE_AIRPLANE) {
+ // Airplane mode is slashed, full-signal
+ mForegroundPath.set(mFullPath);
+ mFullPath.reset();
+ mSlash.draw((int) height, (int) width, canvas, mForegroundPaint);
+ } else if (mState != STATE_CARRIER_CHANGE) {
mForegroundPath.reset();
int sigWidth = Math.round(calcFit(mLevel / (mNumLevels - 1)) * (width - 2 * padding));
mForegroundPath.addRect(padding, padding, padding + sigWidth, height - padding,
@@ -405,4 +457,65 @@ public class SignalDrawable extends Drawable {
public static int getEmptyState(int numLevels) {
return (STATE_EMPTY << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
}
+
+ public static int getAirplaneModeState(int numLevels) {
+ return (STATE_AIRPLANE << STATE_SHIFT) | (numLevels << NUM_LEVEL_SHIFT);
+ }
+
+ private final class SlashArtist {
+ // These values are derived in un-rotated (vertical) orientation
+ private static final float SLASH_WIDTH = 1.8384776f;
+ private static final float SLASH_HEIGHT = 22f;
+ private static final float CENTER_X = 10.65f;
+ private static final float CENTER_Y = 15.869239f;
+ private static final float SCALE = 24f;
+
+ // Bottom is derived during animation
+ private static final float LEFT = (CENTER_X - (SLASH_WIDTH / 2)) / SCALE;
+ private static final float TOP = (CENTER_Y - (SLASH_HEIGHT / 2)) / SCALE;
+ private static final float RIGHT = (CENTER_X + (SLASH_WIDTH / 2)) / SCALE;
+ private static final float BOTTOM = (CENTER_Y + (SLASH_HEIGHT / 2)) / SCALE;
+ // Draw the slash washington-monument style; rotate to no-u-turn style
+ private static final float ROTATION = -45f;
+
+ private final Path mPath = new Path();
+ private final RectF mSlashRect = new RectF();
+
+ void draw(int height, int width, @NonNull Canvas canvas, Paint paint) {
+ Matrix m = new Matrix();
+ updateRect(
+ scale(LEFT, width),
+ scale(TOP, height),
+ scale(RIGHT, width),
+ scale(BOTTOM, height));
+
+ mPath.reset();
+ // Draw the slash vertically
+ mPath.addRect(mSlashRect, Direction.CW);
+ m.setRotate(ROTATION, width / 2, height / 2);
+ mPath.transform(m);
+ canvas.drawPath(mPath, paint);
+
+ // Rotate back to vertical, and draw the cut-out rect next to this one
+ m.setRotate(-ROTATION, width / 2, height / 2);
+ mPath.transform(m);
+ m.setTranslate(mSlashRect.width(), 0);
+ mPath.transform(m);
+ mPath.addRect(mSlashRect, Direction.CW);
+ m.setRotate(ROTATION, width / 2, height / 2);
+ mPath.transform(m);
+ canvas.clipOutPath(mPath);
+ }
+
+ void updateRect(float left, float top, float right, float bottom) {
+ mSlashRect.left = left;
+ mSlashRect.top = top;
+ mSlashRect.right = right;
+ mSlashRect.bottom = bottom;
+ }
+
+ private float scale(float frac, int width) {
+ return frac * width;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 193077f23ffc..14d0b7ea86b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -48,6 +48,7 @@ import android.app.PendingIntent;
import android.app.RemoteInput;
import android.app.StatusBarManager;
import android.app.TaskStackBuilder;
+import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
@@ -103,7 +104,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
-import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.service.vr.IVrManager;
@@ -139,6 +139,7 @@ import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
+import com.android.internal.graphics.ColorUtils;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
@@ -213,7 +214,6 @@ import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.RowInflaterTask;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -309,6 +309,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public static final boolean DEBUG_GESTURES = false;
public static final boolean DEBUG_MEDIA = false;
public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
+ public static final boolean DEBUG_CAMERA_LIFT = true; // false once b/62623620 is fixed
public static final boolean DEBUG_WINDOW_STATE = false;
@@ -1300,10 +1301,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public void onOverlayChanged() {
- final boolean usingDarkTheme = isUsingDarkTheme();
- if (DEBUG) {
- Log.d(TAG, "Updating theme because overlay changed. Is theme dark? " + usingDarkTheme);
- }
reevaluateStyles();
// Clock and bottom icons
@@ -2843,6 +2840,17 @@ public class StatusBar extends SystemUI implements DemoMode,
updateTheme();
}
+ public boolean isUsingDarkText() {
+ OverlayInfo themeInfo = null;
+ try {
+ themeInfo = mOverlayManager.getOverlayInfo("com.android.systemui.theme.lightwallpaper",
+ mCurrentUserId);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ return themeInfo != null && themeInfo.isEnabled();
+ }
+
public boolean isUsingDarkTheme() {
OverlayInfo themeInfo = null;
try {
@@ -3448,7 +3456,9 @@ public class StatusBar extends SystemUI implements DemoMode,
pw.println(Settings.Global.zenModeToString(mZenMode));
pw.print(" mUseHeadsUp=");
pw.println(mUseHeadsUp);
- dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions());
+ if (mStatusBarView != null) {
+ dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions());
+ }
pw.print(" mMediaSessionManager=");
pw.println(mMediaSessionManager);
@@ -3514,7 +3524,9 @@ public class StatusBar extends SystemUI implements DemoMode,
pw.println(" mGroupManager: null");
}
- mLightBarController.dump(fd, pw, args);
+ if (mLightBarController != null) {
+ mLightBarController.dump(fd, pw, args);
+ }
if (KeyguardUpdateMonitor.getInstance(mContext) != null) {
KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
@@ -4521,30 +4533,49 @@ public class StatusBar extends SystemUI implements DemoMode,
* Switches theme from light to dark and vice-versa.
*/
private void updateTheme() {
- boolean useDarkTheme;
- // Ignore visibility since we calculate the theme based on the real colors,
- // not the current state.
+
+ int which;
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
- useDarkTheme = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK, true /* vis */)
- .supportsDarkText();
+ which = WallpaperManager.FLAG_LOCK;
} else {
- useDarkTheme = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM, true /* vis */)
- .supportsDarkText();
+ which = WallpaperManager.FLAG_SYSTEM;
}
- // Enable/Disable dark overlay
- if (isUsingDarkTheme() != useDarkTheme) {
- if (DEBUG) {
- Log.d(TAG, "Switching theme to: " + (useDarkTheme ? "Dark" : "Light"));
+ // Gradient defines if text color should be light or dark.
+ final boolean useDarkText = mColorExtractor.getColors(which, true /* ignoreVisibility */)
+ .supportsDarkText();
+ // And wallpaper defines if QS should be light or dark.
+ boolean useDarkTheme = false;
+ final WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
+ if (wallpaperManager != null) {
+ WallpaperColors wallpaperColors = wallpaperManager
+ .getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
+ if (wallpaperColors != null) {
+ final int mainColor = wallpaperColors.getPrimaryColor().toArgb();
+ final float[] hsl = new float[3];
+ ColorUtils.colorToHSL(mainColor, hsl);
+ useDarkTheme = hsl[2] < 0.2f;
}
+ }
+
+ // Enable/disable dark UI.
+ if (isUsingDarkTheme() != useDarkTheme) {
try {
mOverlayManager.setEnabled("com.android.systemui.theme.dark",
useDarkTheme, mCurrentUserId);
} catch (RemoteException e) {
Log.w(TAG, "Can't change theme", e);
- return;
}
- mStatusBarWindowManager.setKeyguardDark(useDarkTheme);
+ }
+ // Enable/disable dark text overlay.
+ if (isUsingDarkText() != useDarkText) {
+ try {
+ mOverlayManager.setEnabled("com.android.systemui.theme.lightwallpaper",
+ useDarkText, mCurrentUserId);
+ mStatusBarWindowManager.setKeyguardDark(useDarkText);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Can't change theme", e);
+ }
}
}
@@ -5163,11 +5194,14 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onCameraLaunchGestureDetected(int source) {
mLastCameraLaunchSource = source;
if (mStartedGoingToSleep) {
+ if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Finish going to sleep before launching camera");
mLaunchCameraOnFinishedGoingToSleep = true;
return;
}
if (!mNotificationPanel.canCameraGestureBeLaunched(
mStatusBarKeyguardViewManager.isShowing() && mExpandedVisible)) {
+ if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Can't launch camera right now, mExpandedVisible: " +
+ mExpandedVisible);
return;
}
if (!mDeviceInteractive) {
@@ -5187,12 +5221,14 @@ public class StatusBar extends SystemUI implements DemoMode,
mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
}
if (mScreenTurningOn || mStatusBarKeyguardViewManager.isScreenTurnedOn()) {
+ if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Launching camera");
mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source);
} else {
// We need to defer the camera launch until the screen comes on, since otherwise
// we will dismiss us too early since we are waiting on an activity to be drawn and
// incorrectly get notified because of the screen on event (which resumes and pauses
// some activities)
+ if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Deferring until screen turns on");
mLaunchCameraOnScreenTurningOn = true;
}
}
@@ -6039,11 +6075,12 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
- if (snoozeOption.criterion != null) {
- mNotificationListener.snoozeNotification(sbn.getKey(), snoozeOption.criterion.getId());
+ if (snoozeOption.getSnoozeCriterion() != null) {
+ mNotificationListener.snoozeNotification(sbn.getKey(),
+ snoozeOption.getSnoozeCriterion().getId());
} else {
mNotificationListener.snoozeNotification(sbn.getKey(),
- snoozeOption.snoozeForMinutes * 60 * 1000);
+ snoozeOption.getMinutesToSnoozeFor() * 60 * 1000);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index 4c879c68f2ff..13ee23fb7af9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -127,6 +127,7 @@ public class DeadZone extends View {
final int action = event.getAction();
if (action == MotionEvent.ACTION_OUTSIDE) {
poke(event);
+ return true;
} else if (action == MotionEvent.ACTION_DOWN) {
if (DEBUG) {
Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY());
@@ -158,7 +159,7 @@ public class DeadZone extends View {
return false;
}
- public void poke(MotionEvent event) {
+ private void poke(MotionEvent event) {
mLastPokeTime = event.getEventTime();
if (DEBUG)
Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime));
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 d77796144282..2d3e0b6829ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -226,6 +226,9 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
case MotionEvent.ACTION_UP:
final boolean doIt = isPressed() && !mLongClicked;
setPressed(false);
+ // Always send a release ourselves because it doesn't seem to be sent elsewhere
+ // and it feels weird to sometimes get a release haptic and other times not.
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);
if (mCode != 0) {
if (doIt) {
sendEvent(KeyEvent.ACTION_UP, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 3f5f5a0ed5ae..874f0d9d5b5f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -31,8 +31,10 @@ import android.os.Message;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
import com.android.systemui.R;
+import com.android.systemui.util.Utils;
import java.util.ArrayList;
import java.util.List;
@@ -141,7 +143,8 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
/**
* Returns true if there currently exist active high power location requests.
*/
- private boolean areActiveHighPowerLocationRequests() {
+ @VisibleForTesting
+ protected boolean areActiveHighPowerLocationRequests() {
List<AppOpsManager.PackageOps> packages
= mAppOpsManager.getPackagesForOps(mHighPowerRequestAppOpArray);
// AppOpsManager can return null when there is no requested data.
@@ -205,16 +208,14 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
}
private void locationActiveChanged() {
- for (LocationChangeCallback cb : mSettingsChangeCallbacks) {
- cb.onLocationActiveChanged(mAreActiveLocationRequests);
- }
+ Utils.safeForeach(mSettingsChangeCallbacks,
+ cb -> cb.onLocationActiveChanged(mAreActiveLocationRequests));
}
private void locationSettingsChanged() {
boolean isEnabled = isLocationEnabled();
- for (LocationChangeCallback cb : mSettingsChangeCallbacks) {
- cb.onLocationSettingsChanged(isEnabled);
- }
+ Utils.safeForeach(mSettingsChangeCallbacks,
+ cb -> cb.onLocationSettingsChanged(isEnabled));
}
}
}
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 67b5596e34c9..b6c76551c48b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -235,6 +235,9 @@ public class MobileSignalController extends SignalController<
}
private int getNumLevels() {
+ if (mConfig.inflateSignalStrengths) {
+ return SignalStrength.NUM_SIGNAL_STRENGTH_BINS + 1;
+ }
return SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
}
@@ -243,7 +246,11 @@ public class MobileSignalController extends SignalController<
if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) {
return SignalDrawable.getCarrierChangeState(getNumLevels());
} else if (mCurrentState.connected) {
- return SignalDrawable.getState(mCurrentState.level, getNumLevels(),
+ int level = mCurrentState.level;
+ if (mConfig.inflateSignalStrengths) {
+ level++;
+ }
+ return SignalDrawable.getState(level, getNumLevels(),
mCurrentState.inetCondition == 0);
} else if (mCurrentState.enabled) {
return SignalDrawable.getEmptyState(getNumLevels());
@@ -254,6 +261,10 @@ public class MobileSignalController extends SignalController<
@Override
public int getQsCurrentIconId() {
+ if (mCurrentState.airplaneMode) {
+ return SignalDrawable.getAirplaneModeState(getNumLevels());
+ }
+
return getCurrentIconId();
}
@@ -330,6 +341,10 @@ public class MobileSignalController extends SignalController<
}
private boolean isRoaming() {
+ // During a carrier change, roaming indications need to be supressed.
+ if (isCarrierNetworkChangeActive()) {
+ return false;
+ }
if (isCdma()) {
final int iconMode = mServiceState.getCdmaEriIconMode();
return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
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 39f7d1295d1b..c217bda935c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -958,6 +958,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
boolean show4gForLte = false;
boolean hideLtePlus = false;
boolean hspaDataDistinguishable;
+ boolean inflateSignalStrengths = false;
static Config readConfig(Context context) {
Config config = new Config();
@@ -970,6 +971,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
config.hspaDataDistinguishable =
res.getBoolean(R.bool.config_hspa_data_distinguishable);
config.hideLtePlus = res.getBoolean(R.bool.config_hideLtePlus);
+ config.inflateSignalStrengths = res.getBoolean(R.bool.config_inflateSignalStrength);
return config;
}
}
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 612a54a8d70d..b12fd1c9ba89 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -37,6 +37,7 @@
<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
<uses-permission android:name="android.permission.CONTROL_VPN" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
index 630da2e7eabc..2a2acabc8cee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
@@ -57,4 +57,10 @@ public class NotificationMenuRowTest extends LeakCheckedTest {
row.createMenu(null, null);
assertTrue(row.getMenuView() != null);
}
+
+ @Test
+ public void testResetUncreatedMenu() {
+ NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+ row.resetMenu();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
index 68f9cb05ecaf..7b2071ca14fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
@@ -16,8 +16,10 @@
package com.android.systemui.statusbar;
+import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -33,12 +35,14 @@ import android.content.ContextWrapper;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.graphics.Color;
import android.graphics.drawable.Icon;
import android.os.UserHandle;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -100,4 +104,22 @@ public class StatusBarIconViewTest extends SysuiTestCase {
assertFalse(mIconView.set(mStatusBarIcon));
}
+
+ @Test
+ public void testGetContrastedStaticDrawableColor() {
+ mIconView.setStaticDrawableColor(Color.DKGRAY);
+ int color = mIconView.getContrastedStaticDrawableColor(Color.WHITE);
+ assertEquals("Color should not change when we have enough contrast",
+ Color.DKGRAY, color);
+
+ mIconView.setStaticDrawableColor(Color.WHITE);
+ color = mIconView.getContrastedStaticDrawableColor(Color.WHITE);
+ assertTrue("Similar colors should be shifted to satisfy contrast",
+ NotificationColorUtil.satisfiesTextContrast(Color.WHITE, color));
+
+ mIconView.setStaticDrawableColor(Color.GREEN);
+ color = mIconView.getContrastedStaticDrawableColor(0xcc000000);
+ assertEquals("Transparent backgrounds should fallback to drawable color",
+ color, mIconView.getStaticDrawableColor());
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
index c7af0d9c8979..1b42d1b5dffc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
@@ -24,12 +24,17 @@ import static org.mockito.Mockito.verify;
import android.app.Notification;
import android.content.Context;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.Looper;
import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.view.ViewGroup;
import android.widget.RemoteViews;
import com.android.systemui.R;
@@ -45,7 +50,9 @@ import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -142,6 +149,41 @@ public class NotificationInflaterTest extends SysuiTestCase {
Assert.assertNull(mRow.getEntry().getRunningTask());
}
+ @Test
+ public void testInflationIsRetriedIfAsyncFails() throws Exception {
+ NotificationInflater.InflationProgress result =
+ new NotificationInflater.InflationProgress();
+ result.packageContext = mContext;
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ NotificationInflater.applyRemoteView(result,
+ NotificationInflater.FLAG_REINFLATE_EXPANDED_VIEW, 0, mRow,
+ false /* redactAmbient */, true /* isNewView */, new RemoteViews.OnClickHandler(),
+ new NotificationInflater.InflationCallback() {
+ @Override
+ public void handleInflationException(StatusBarNotification notification,
+ Exception e) {
+ countDownLatch.countDown();
+ throw new RuntimeException("No Exception expected");
+ }
+
+ @Override
+ public void onAsyncInflationFinished(NotificationData.Entry entry) {
+ countDownLatch.countDown();
+ }
+ }, mRow.getEntry(), mRow.getPrivateLayout(), null, null, new HashMap<>(),
+ new NotificationInflater.ApplyCallback() {
+ @Override
+ public void setResultView(View v) {
+ }
+
+ @Override
+ public RemoteViews getRemoteView() {
+ return new AsyncFailRemoteView(mContext.getPackageName(),
+ R.layout.custom_view_dark);
+ }
+ });
+ countDownLatch.await();
+ }
@Test
public void testSupersedesExistingTask() throws Exception {
@@ -200,4 +242,30 @@ public class NotificationInflaterTest extends SysuiTestCase {
mException = exception;
}
}
+
+ private class AsyncFailRemoteView extends RemoteViews {
+ Handler mHandler = new Handler(Looper.getMainLooper());
+
+ public AsyncFailRemoteView(String packageName, int layoutId) {
+ super(packageName, layoutId);
+ }
+
+ @Override
+ public View apply(Context context, ViewGroup parent) {
+ return super.apply(context, parent);
+ }
+
+ @Override
+ public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
+ OnViewAppliedListener listener, OnClickHandler handler) {
+ mHandler.post(() -> listener.onError(new RuntimeException("Failed to inflate async")));
+ return new CancellationSignal();
+ }
+
+ @Override
+ public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
+ OnViewAppliedListener listener) {
+ return applyAsync(context, parent, executor, listener, null);
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index a120cecb55e8..4cc83f632426 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -14,7 +14,6 @@
package com.android.systemui.statusbar.phone;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -33,17 +32,13 @@ import com.android.systemui.recents.Recents;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
-import com.android.systemui.utils.leaks.BaseLeakChecker;
import android.testing.TestableLooper.RunWithLooper;
-import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
@@ -54,6 +49,10 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest {
super(NavigationBarFragment.class);
}
+ protected void createRootView() {
+ mView = new NavigationBarFrame(mContext);
+ }
+
@Before
public void setup() {
mDependency.injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 0e3ea7a07e7d..17ca92458bcf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -38,6 +38,8 @@ import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import android.app.Notification;
+import android.app.trust.TrustManager;
+import android.hardware.fingerprint.FingerprintManager;
import android.metrics.LogMaker;
import android.os.Handler;
import android.os.HandlerThread;
@@ -55,6 +57,7 @@ import android.testing.TestableLooper;
import android.testing.TestableLooper.MessageHandler;
import android.testing.TestableLooper.RunWithLooper;
import android.util.DisplayMetrics;
+import android.view.ViewGroup.LayoutParams;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -75,6 +78,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
import java.util.ArrayList;
@SmallTest
@@ -99,6 +104,8 @@ public class StatusBarTest extends SysuiTestCase {
@Before
public void setup() throws Exception {
+ mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
+ mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager.class);
mUnlockMethodCache = mock(UnlockMethodCache.class);
mKeyguardIndicationController = mock(KeyguardIndicationController.class);
@@ -108,6 +115,7 @@ public class StatusBarTest extends SysuiTestCase {
mNotificationData = mock(NotificationData.class);
mSystemServicesProxy = mock(SystemServicesProxy.class);
mNotificationPanelView = mock(NotificationPanelView.class);
+ when(mNotificationPanelView.getLayoutParams()).thenReturn(new LayoutParams(0, 0));
mNotificationList = mock(ArrayList.class);
IPowerManager powerManagerService = mock(IPowerManager.class);
HandlerThread handlerThread = new HandlerThread("TestThread");
@@ -122,6 +130,7 @@ public class StatusBarTest extends SysuiTestCase {
mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
mNotificationData, mPowerManager, mSystemServicesProxy, mNotificationPanelView,
mBarService);
+ mStatusBar.mContext = mContext;
doAnswer(invocation -> {
OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
onDismissAction.onDismiss();
@@ -385,6 +394,11 @@ public class StatusBarTest extends SysuiTestCase {
TestableLooper.get(this).processAllMessages();
}
+ @Test
+ public void testDump_DoesNotCrash() {
+ mStatusBar.dump(null, new PrintWriter(new ByteArrayOutputStream()), null);
+ }
+
static class TestableStatusBar extends StatusBar {
public TestableStatusBar(StatusBarKeyguardViewManager man,
UnlockMethodCache unlock, KeyguardIndicationController key,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
new file mode 100644
index 000000000000..a10bebfd4f2d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Intent;
+import android.location.LocationManager;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class LocationControllerImplTest extends SysuiTestCase {
+
+ private LocationControllerImpl mLocationController;
+
+ @Before
+ public void setup() {
+ mLocationController = spy(new LocationControllerImpl(mContext,
+ TestableLooper.get(this).getLooper()));
+ }
+
+ @Test
+ public void testRemoveSelfActive_DoesNotCrash() {
+ LocationController.LocationChangeCallback callback = new LocationChangeCallback() {
+ @Override
+ public void onLocationActiveChanged(boolean active) {
+ mLocationController.removeCallback(this);
+ }
+ };
+ mLocationController.addCallback(callback);
+ mLocationController.addCallback(mock(LocationChangeCallback.class));
+
+ when(mLocationController.areActiveHighPowerLocationRequests()).thenReturn(false);
+ mLocationController.onReceive(mContext, new Intent(
+ LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION));
+ when(mLocationController.areActiveHighPowerLocationRequests()).thenReturn(true);
+ mLocationController.onReceive(mContext, new Intent(
+ LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION));
+
+ TestableLooper.get(this).processAllMessages();
+ }
+
+ @Test
+ public void testRemoveSelfSettings_DoesNotCrash() {
+ LocationController.LocationChangeCallback callback = new LocationChangeCallback() {
+ @Override
+ public void onLocationSettingsChanged(boolean isEnabled) {
+ mLocationController.removeCallback(this);
+ }
+ };
+ mLocationController.addCallback(callback);
+ mLocationController.addCallback(mock(LocationChangeCallback.class));
+
+ TestableLooper.get(this).processAllMessages();
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index be3802bd68ed..cba9f77df2ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -494,6 +494,79 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
DEFAULT_ICON /* typeIcon */);
}
+ @Test
+ public void testCarrierNetworkChange_roamingBeforeNetworkChange() {
+ int strength = SignalStrength.SIGNAL_STRENGTH_GREAT;
+
+ setupDefaultSignal();
+ setLevel(strength);
+ setGsmRoaming(true);
+
+ // Verify baseline
+ verifyLastMobileDataIndicators(true /* visible */,
+ strength /* strengthIcon */,
+ DEFAULT_ICON /* typeIcon */,
+ true /* roaming */);
+
+ // API call is made
+ setCarrierNetworkChange(true /* enabled */);
+
+ // Carrier network change is true, show special indicator, no roaming.
+ verifyLastMobileDataIndicators(true /* visible */,
+ SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS),
+ 0 /* typeIcon */,
+ false /* roaming */);
+
+ // Revert back
+ setCarrierNetworkChange(false /* enabled */);
+
+ // Verify back in previous state
+ verifyLastMobileDataIndicators(true /* visible */,
+ strength /* strengthIcon */,
+ DEFAULT_ICON /* typeIcon */,
+ true /* roaming */);
+ }
+
+ @Test
+ public void testCarrierNetworkChange_roamingAfterNetworkChange() {
+ int strength = SignalStrength.SIGNAL_STRENGTH_GREAT;
+
+ setupDefaultSignal();
+ setLevel(strength);
+
+ // Verify baseline
+ verifyLastMobileDataIndicators(true /* visible */,
+ strength /* strengthIcon */,
+ DEFAULT_ICON /* typeIcon */,
+ false /* roaming */);
+
+ // API call is made
+ setCarrierNetworkChange(true /* enabled */);
+
+ // Carrier network change is true, show special indicator, no roaming.
+ verifyLastMobileDataIndicators(true /* visible */,
+ SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS),
+ 0 /* typeIcon */,
+ false /* roaming */);
+
+ setGsmRoaming(true);
+
+ // Roaming should not show.
+ verifyLastMobileDataIndicators(true /* visible */,
+ SignalDrawable.getCarrierChangeState(SignalStrength.NUM_SIGNAL_STRENGTH_BINS),
+ 0 /* typeIcon */,
+ false /* roaming */);
+
+ // Revert back
+ setCarrierNetworkChange(false /* enabled */);
+
+ // Verify back in previous state
+ verifyLastMobileDataIndicators(true /* visible */,
+ strength /* strengthIcon */,
+ DEFAULT_ICON /* typeIcon */,
+ true /* roaming */);
+ }
+
private void verifyEmergencyOnly(boolean isEmergencyOnly) {
ArgumentCaptor<Boolean> emergencyOnly = ArgumentCaptor.forClass(Boolean.class);
Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setEmergencyCallsOnly(
diff --git a/packages/SysuiDarkThemeOverlay/Android.mk b/packages/overlays/SysuiDarkThemeOverlay/Android.mk
index 4b83058ab481..4b83058ab481 100644
--- a/packages/SysuiDarkThemeOverlay/Android.mk
+++ b/packages/overlays/SysuiDarkThemeOverlay/Android.mk
diff --git a/packages/SysuiDarkThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
index ba1c91cbdebe..ba1c91cbdebe 100644
--- a/packages/SysuiDarkThemeOverlay/AndroidManifest.xml
+++ b/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
diff --git a/packages/SysuiDarkThemeOverlay/res/values/strings.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/strings.xml
index 71f48d6279f1..71f48d6279f1 100644
--- a/packages/SysuiDarkThemeOverlay/res/values/strings.xml
+++ b/packages/overlays/SysuiDarkThemeOverlay/res/values/strings.xml
diff --git a/packages/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
index 28ecfa0b37fa..7e2b955a8871 100644
--- a/packages/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
+++ b/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <!-- Dark theme for a window that should look like the Settings app. -->
<style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault">
- <!-- Color palette -->
<item name="android:colorPrimary">@*android:color/primary_device_default_settings</item>
<item name="android:colorPrimaryDark">@*android:color/primary_dark_device_default_settings</item>
- <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
- <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
+ <!-- textColorPrimaryInverse is used on the lock screen and this means that we can't just
+ invert text colors otherwise we won't have contrast on the keyguard -->
+ <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_dark</item>
+ <!-- same for textColorSecondaryInverse -->
+ <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_dark</item>
<item name="android:colorSecondary">@*android:color/secondary_device_default_settings</item>
<item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
<item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/Android.mk b/packages/overlays/SysuiLightWallpaperThemeOverlay/Android.mk
new file mode 100644
index 000000000000..4782a166146b
--- /dev/null
+++ b/packages/overlays/SysuiLightWallpaperThemeOverlay/Android.mk
@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := SysuiLightWallpaperTheme
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := SysuiLightWallpaperThemeOverlay
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
new file mode 100644
index 000000000000..1745b4cda03d
--- /dev/null
+++ b/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.systemui.theme.lightwallpaper"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android" android:priority="2"/>
+
+ <application android:label="@string/sysui_overlay_light" android:hasCode="false"/>
+</manifest>
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/strings.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/strings.xml
new file mode 100644
index 000000000000..acc3d16610ec
--- /dev/null
+++ b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <string name="sysui_overlay_light">Light</string>
+
+</resources>
+
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml
new file mode 100644
index 000000000000..877ebf8c4e9d
--- /dev/null
+++ b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault.Light">
+ <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
+ <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
+ </style>
+</resources> \ No newline at end of file
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index fa2b1ee83419..2edcd71721ca 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -4095,6 +4095,70 @@ message MetricsEvent {
// OS: O DR
CAPTIVE_PORTAL_LOGIN_ACTIVITY_SSL_ERROR = 1013;
+ // OPEN: Settings > Network > Tether > Wi-Fi hotspot
+ WIFI_TETHER_SETTINGS = 1014;
+
+ // OPEN: Settings->Connected Devices->Bluetooth->(click on details link for a paired device)
+ // -> Edit name button.
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ DIALOG_BLUETOOTH_PAIRED_DEVICE_RENAME = 1015;
+
+ // ACTION: Settings > Notification Settings > Open application notification
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ ACTION_OPEN_APP_NOTIFICATION_SETTING = 1016;
+
+ // ACTION: Settings > App Info > Open app settings
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ ACTION_OPEN_APP_SETTING = 1017;
+
+ // OPEN: Settings > Connected devices > Bluetooth > Pair new device
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ BLUETOOTH_PAIRING = 1018;
+
+ // ACTION: Collect PSD Signals
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ ACTION_PSD_LOADER = 1019;
+
+ // ACTION: Background check action on an app
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ ACTION_APP_BACKGROUND_CHECK = 1020;
+
+ // ACTION: Location check action on an app
+ // CATEGORY: SETTINGS
+ // OS: O DR
+ ACTION_APP_LOCATION_CHECK = 1021;
+
+ // Device headset status
+ // CATEGORY: OTHER
+ // SUBTYPE: 1 is DON, 2 is DOFF
+ // OS: O DR
+ ACTION_HEADSET_STATUS = 1022;
+
+ // Device Headset Plug status
+ // CATEGORY: OTHER
+ // SUBTYPE: 1 is AC power, 2 is USB power, 3 is Unplug
+ // OS: O DR
+ ACTION_HEADSET_PLUG = 1023;
+
+ // Device Headset battery level on Plug
+ // CATEGORY: OTHER
+ // FIELD - The battery percentage when the user decided to plug in
+ // Type: integer
+ // OS: O DR
+ FIELD_PLUG_BATTERY_PERCENTAGE = 1024;
+
+ // Device Headset Pose status
+ // CATEGORY: OTHER
+ // SUBTYPE: 1 is 6DOF, 2 is 3DOF
+ // OS: O DR
+ ACTION_HEADSET_POSE_STATUS = 1025;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index e85f96be3160..cb91f9308b03 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -270,6 +270,12 @@ public final class AutofillManagerService extends SystemService {
}
@Override
+ public void onSwitchUser(int userHandle) {
+ if (sDebug) Slog.d(TAG, "Hiding UI when user switched");
+ mUi.hideAll(null);
+ }
+
+ @Override
public void onCleanupUser(int userId) {
synchronized (mLock) {
removeCachedServiceLocked(userId);
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 38b796b316de..751c0547afd6 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -360,8 +360,7 @@ final class AutofillManagerServiceImpl {
}
void disableOwnedAutofillServicesLocked(int uid) {
- if (mInfo == null || mInfo.getServiceInfo().applicationInfo.uid
- != UserHandle.getAppId(uid)) {
+ if (mInfo == null || mInfo.getServiceInfo().applicationInfo.uid != uid) {
return;
}
final long identity = Binder.clearCallingIdentity();
@@ -489,46 +488,78 @@ final class AutofillManagerServiceImpl {
* Initializes the last fill selection after an autofill service returned a new
* {@link FillResponse}.
*/
- void setLastResponse(int serviceUid, @NonNull FillResponse response) {
+ void setLastResponse(int serviceUid, int sessionId, @NonNull FillResponse response) {
synchronized (mLock) {
- mEventHistory = new FillEventHistory(serviceUid, response.getClientState());
+ mEventHistory = new FillEventHistory(serviceUid, sessionId, response.getClientState());
}
}
/**
+ * Resets the last fill selection.
+ */
+ void resetLastResponse() {
+ synchronized (mLock) {
+ mEventHistory = null;
+ }
+ }
+
+ private boolean isValidEventLocked(String method, int sessionId) {
+ if (mEventHistory == null) {
+ Slog.w(TAG, method + ": not logging event because history is null");
+ return false;
+ }
+ if (sessionId != mEventHistory.getSessionId()) {
+ if (sDebug) {
+ Slog.d(TAG, method + ": not logging event for session " + sessionId
+ + " because tracked session is " + mEventHistory.getSessionId());
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
* Updates the last fill selection when an authentication was selected.
*/
- void setAuthenticationSelected() {
+ void setAuthenticationSelected(int sessionId) {
synchronized (mLock) {
- mEventHistory.addEvent(new Event(Event.TYPE_AUTHENTICATION_SELECTED, null));
+ if (isValidEventLocked("setAuthenticationSelected()", sessionId)) {
+ mEventHistory.addEvent(new Event(Event.TYPE_AUTHENTICATION_SELECTED, null));
+ }
}
}
/**
* Updates the last fill selection when an dataset authentication was selected.
*/
- void setDatasetAuthenticationSelected(@Nullable String selectedDataset) {
+ void setDatasetAuthenticationSelected(@Nullable String selectedDataset, int sessionId) {
synchronized (mLock) {
- mEventHistory.addEvent(
- new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset));
+ if (isValidEventLocked("setDatasetAuthenticationSelected()", sessionId)) {
+ mEventHistory.addEvent(
+ new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset));
+ }
}
}
/**
* Updates the last fill selection when an save Ui is shown.
*/
- void setSaveShown() {
+ void setSaveShown(int sessionId) {
synchronized (mLock) {
- mEventHistory.addEvent(new Event(Event.TYPE_SAVE_SHOWN, null));
+ if (isValidEventLocked("setSaveShown()", sessionId)) {
+ mEventHistory.addEvent(new Event(Event.TYPE_SAVE_SHOWN, null));
+ }
}
}
/**
* Updates the last fill response when a dataset was selected.
*/
- void setDatasetSelected(@Nullable String selectedDataset) {
+ void setDatasetSelected(@Nullable String selectedDataset, int sessionId) {
synchronized (mLock) {
- mEventHistory.addEvent(new Event(Event.TYPE_DATASET_SELECTED, selectedDataset));
+ if (isValidEventLocked("setDatasetSelected()", sessionId)) {
+ mEventHistory.addEvent(new Event(Event.TYPE_DATASET_SELECTED, selectedDataset));
+ }
}
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 9aebf6d2bacb..aebe92e1687d 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -427,6 +427,7 @@ final class RemoteFillService implements DeathRecipient {
mCompleted = true;
}
+ Slog.w(LOG_TAG, getClass().getSimpleName() + " timed out");
final RemoteFillService remoteService = mWeakService.get();
if (remoteService != null) {
fail(remoteService);
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 3ae05115217a..72ad752caf19 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -407,13 +407,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if ((requestFlags & FLAG_MANUAL_REQUEST) != 0) {
getUiForShowing().showError(R.string.autofill_error_cannot_autofill, this);
}
+ mService.resetLastResponse();
// Nothing to be done, but need to notify client.
notifyUnavailableToClient();
removeSelf();
return;
}
- mService.setLastResponse(serviceUid, response);
+ mService.setLastResponse(serviceUid, id, response);
if ((response.getDatasets() == null || response.getDatasets().isEmpty())
&& response.getAuthentication() == null) {
@@ -444,6 +445,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
+ id + " destroyed");
return;
}
+ mService.resetLastResponse();
}
LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
.setType(MetricsEvent.TYPE_FAILURE)
@@ -542,7 +544,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
getFillContextByRequestIdLocked(requestId).getStructure(), extras);
}
- mService.setAuthenticationSelected();
+ mService.setAuthenticationSelected(id);
final int authenticationId = AutofillManager.makeAuthenticationId(requestId, datasetIndex);
mHandlerCaller.getHandler().post(() -> startAuthentication(authenticationId,
@@ -831,7 +833,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
if (atLeastOneChanged) {
if (sDebug) Slog.d(TAG, "at least one field changed - showing save UI");
- mService.setSaveShown();
+ mService.setSaveShown(id);
getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo, mPackageName,
this);
@@ -1362,14 +1364,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
// Autofill it directly...
if (dataset.getAuthentication() == null) {
- mService.setDatasetSelected(dataset.getId());
+ mService.setDatasetSelected(dataset.getId(), id);
autoFillApp(dataset);
return;
}
// ...or handle authentication.
- mService.setDatasetAuthenticationSelected(dataset.getId());
+ mService.setDatasetAuthenticationSelected(dataset.getId(), id);
setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH, false);
final Intent fillInIntent = createAuthFillInIntent(
getFillContextByRequestIdLocked(requestId).getStructure(), mClientState);
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index d1fbbf9ceda1..c9e2a928dee0 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -191,6 +191,7 @@ final class SaveUi {
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
+ window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS);
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
window.setGravity(Gravity.BOTTOM | Gravity.CENTER);
window.setCloseOnTouchOutside(true);
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 4d080e9d6103..0d01c2026176 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -33,6 +33,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
android.hardware.oemlock-V1.0-java-static \
android.hardware.tetheroffload.control-V1.0-java-static \
android.hardware.vibrator-V1.0-java-constants \
+ android.hardware.configstore-V1.0-java-static
ifneq ($(INCREMENTAL_BUILDS),)
LOCAL_PROGUARD_ENABLED := disabled
diff --git a/services/core/java/com/android/server/ContextHubSystemService.java b/services/core/java/com/android/server/ContextHubSystemService.java
index 5d4317cbdae3..110847dd54c8 100644
--- a/services/core/java/com/android/server/ContextHubSystemService.java
+++ b/services/core/java/com/android/server/ContextHubSystemService.java
@@ -16,17 +16,25 @@
package com.android.server;
+import com.android.internal.util.ConcurrentUtils;
import com.android.server.location.ContextHubService;
+import com.android.server.SystemServerInitThreadPool;
import android.content.Context;
import android.util.Log;
+import java.util.concurrent.Future;
+
class ContextHubSystemService extends SystemService {
private static final String TAG = "ContextHubSystemService";
- private final ContextHubService mContextHubService;
+ private ContextHubService mContextHubService;
+
+ private Future<?> mInit;
public ContextHubSystemService(Context context) {
super(context);
- mContextHubService = new ContextHubService(context);
+ mInit = SystemServerInitThreadPool.get().submit(() -> {
+ mContextHubService = new ContextHubService(context);
+ }, "Init ContextHubSystemService");
}
@Override
@@ -37,6 +45,9 @@ class ContextHubSystemService extends SystemService {
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY");
+ ConcurrentUtils.waitForFutureNoInterrupt(mInit,
+ "Wait for ContextHubSystemService init");
+ mInit = null;
publishBinderService(Context.CONTEXTHUB_SERVICE, mContextHubService);
}
}
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index b408da85425d..4c9495a786c3 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -17,7 +17,6 @@
package com.android.server;
import android.app.ActivityManager;
-import android.app.KeyguardManager;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -41,10 +40,12 @@ import android.provider.Settings;
import android.util.MutableBoolean;
import android.util.Slog;
import android.view.KeyEvent;
+import android.view.WindowManagerInternal;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.server.LocalServices;
import com.android.server.statusbar.StatusBarManagerInternal;
/**
@@ -56,6 +57,7 @@ import com.android.server.statusbar.StatusBarManagerInternal;
*/
public class GestureLauncherService extends SystemService {
private static final boolean DBG = false;
+ private static final boolean DBG_CAMERA_LIFT = true; // false once b/62623620 is fixed
private static final String TAG = "GestureLauncherService";
/**
@@ -82,7 +84,7 @@ public class GestureLauncherService extends SystemService {
private Context mContext;
private final MetricsLogger mMetricsLogger;
private PowerManager mPowerManager;
- private KeyguardManager mKeyguardManager;
+ private WindowManagerInternal mWindowManagerInternal;
/** The wake lock held when a gesture is detected. */
private WakeLock mWakeLock;
@@ -150,8 +152,7 @@ public class GestureLauncherService extends SystemService {
return;
}
- mKeyguardManager = (KeyguardManager) mContext.getSystemService(
- Context.KEYGUARD_SERVICE);
+ mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mPowerManager = (PowerManager) mContext.getSystemService(
Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
@@ -517,33 +518,40 @@ public class GestureLauncherService extends SystemService {
private final class CameraLiftTriggerEventListener extends TriggerEventListener {
@Override
public void onTrigger(TriggerEvent event) {
+ if (DBG_CAMERA_LIFT) Slog.d(TAG, String.format("onTrigger event - time: %d, name: %s",
+ event.timestamp, event.sensor.getName()));
if (!mCameraLiftRegistered) {
- if (DBG) Slog.d(TAG, "Ignoring camera lift event because it's unregistered.");
+ if (DBG_CAMERA_LIFT) Slog.d(TAG, "Ignoring camera lift event because it's " +
+ "unregistered.");
return;
}
if (event.sensor == mCameraLiftTriggerSensor) {
Resources resources = mContext.getResources();
SensorManager sensorManager = (SensorManager) mContext.getSystemService(
Context.SENSOR_SERVICE);
-
- if (DBG) {
+ boolean keyguardShowingAndNotOccluded =
+ mWindowManagerInternal.isKeyguardShowingAndNotOccluded();
+ boolean interactive = mPowerManager.isInteractive();
+ if (DBG_CAMERA_LIFT) {
float[] values = event.values;
- Slog.d(TAG, String.format("Received a camera lift trigger event: " +
- "values=[%.4f].", values[0]));
+ Slog.d(TAG, String.format("Received a camera lift trigger " +
+ "event: values=[%.4f], keyguard showing: %b, interactive: %b", values[0],
+ keyguardShowingAndNotOccluded, interactive));
}
- if (mKeyguardManager.isKeyguardLocked() || !mPowerManager.isInteractive()) {
+ if (keyguardShowingAndNotOccluded || !interactive) {
if (handleCameraGesture(true /* useWakelock */,
StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER)) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_CAMERA_LIFT_TRIGGER);
}
- } else if (DBG) {
- Slog.d(TAG, "Ignoring lift event because device is awake");
+ } else {
+ if (DBG_CAMERA_LIFT) Slog.d(TAG, "Ignoring lift event");
}
- mCameraLiftRegistered = sensorManager.requestTriggerSensor(mCameraLiftTriggerListener,
- mCameraLiftTriggerSensor);
+ mCameraLiftRegistered = sensorManager.requestTriggerSensor(
+ mCameraLiftTriggerListener, mCameraLiftTriggerSensor);
- if (DBG) Slog.d(TAG, "Camera lift trigger sensor re-registered: " + mCameraLiftRegistered);
+ if (DBG_CAMERA_LIFT) Slog.d(TAG, "Camera lift trigger sensor re-registered: " +
+ mCameraLiftRegistered);
return;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6202b912adc0..fd4f672640c9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4046,7 +4046,11 @@ public class ActivityManagerService extends IActivityManager.Stub
aInfo.applicationInfo.uid, true);
if (app == null || app.instr == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
- mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
+ final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
+ // For ANR debugging to verify if the user activity is the one that actually
+ // launched.
+ final String myReason = reason + ":" + userId + ":" + resolvedUserId;
+ mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
@@ -4118,7 +4122,8 @@ public class ActivityManagerService extends IActivityManager.Stub
ri.activityInfo.packageName, ri.activityInfo.name));
mActivityStarter.startActivityLocked(null, intent, null /*ephemeralIntent*/,
null, ri.activityInfo, null /*rInfo*/, null, null, null, null, 0, 0, 0,
- null, 0, 0, 0, null, false, false, null, null, null);
+ null, 0, 0, 0, null, false, false, null, null, null,
+ "startSetupActivity");
}
}
}
@@ -4457,8 +4462,9 @@ public class ActivityManagerService extends IActivityManager.Stub
container.checkEmbeddedAllowedInner(userId, intent, mimeType);
intent.addFlags(FORCE_NEW_TASK_FLAGS);
- return mActivityStarter.startActivityMayWait(null, -1, null, intent, mimeType, null, null, null,
- null, 0, 0, null, null, null, null, false, userId, container, null);
+ return mActivityStarter.startActivityMayWait(null, -1, null, intent, mimeType, null, null,
+ null, null, 0, 0, null, null, null, null, false, userId, container, null,
+ "startActivity");
}
@Override
@@ -4471,7 +4477,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- profilerInfo, null, null, bOptions, false, userId, null, null);
+ profilerInfo, null, null, bOptions, false, userId, null, null,
+ "startActivityAsUser");
}
@Override
@@ -4534,7 +4541,8 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
int ret = mActivityStarter.startActivityMayWait(null, targetUid, targetPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, null,
- null, null, bOptions, ignoreTargetSecurity, userId, null, null);
+ null, null, bOptions, ignoreTargetSecurity, userId, null, null,
+ "startActivityAsCaller");
return ret;
} catch (SecurityException e) {
// XXX need to figure out how to propagate to original app.
@@ -4563,7 +4571,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO: Switch to user app stacks here.
mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, res, null,
- bOptions, false, userId, null, null);
+ bOptions, false, userId, null, null, "startActivityAndWait");
return res;
}
@@ -4577,7 +4585,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO: Switch to user app stacks here.
int ret = mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- null, null, config, bOptions, false, userId, null, null);
+ null, null, config, bOptions, false, userId, null, null, "startActivityWithConfig");
return ret;
}
@@ -4634,7 +4642,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(null, callingUid, callingPackage, intent,
resolvedType, session, interactor, null, null, 0, startFlags, profilerInfo, null,
- null, bOptions, false, userId, null, null);
+ null, bOptions, false, userId, null, null, "startVoiceActivity");
}
@Override
@@ -4653,7 +4661,7 @@ public class ActivityManagerService extends IActivityManager.Stub
ALLOW_FULL_ONLY, "startAssistantActivity", null);
return mActivityStarter.startActivityMayWait(null, callingUid, callingPackage, intent,
resolvedType, null, null, null, null, 0, 0, null, null, null, bOptions, false,
- userId, null, null);
+ userId, null, null, "startAssistantActivity");
}
@Override
@@ -4826,7 +4834,7 @@ public class ActivityManagerService extends IActivityManager.Stub
null /*ephemeralIntent*/, r.resolvedType, aInfo, null /*rInfo*/, null,
null, resultTo != null ? resultTo.appToken : null, resultWho, requestCode, -1,
r.launchedFromUid, r.launchedFromPackage, -1, r.launchedFromUid, 0, options,
- false, false, null, null, null);
+ false, false, null, null, null, "startNextMatchingActivity");
Binder.restoreCallingIdentity(origId);
r.finishing = wasFinishing;
@@ -4858,7 +4866,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final int startActivityInPackage(int uid, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, Bundle bOptions, int userId,
- IActivityContainer container, TaskRecord inTask) {
+ IActivityContainer container, TaskRecord inTask, String reason) {
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivityInPackage", null);
@@ -4866,7 +4874,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO: Switch to user app stacks here.
int ret = mActivityStarter.startActivityMayWait(null, uid, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- null, null, null, bOptions, false, userId, container, inTask);
+ null, null, null, bOptions, false, userId, container, inTask, reason);
return ret;
}
@@ -4874,12 +4882,13 @@ public class ActivityManagerService extends IActivityManager.Stub
public final int startActivities(IApplicationThread caller, String callingPackage,
Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle bOptions,
int userId) {
- enforceNotIsolatedCaller("startActivities");
+ final String reason = "startActivities";
+ enforceNotIsolatedCaller(reason);
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
- userId, false, ALLOW_FULL_ONLY, "startActivity", null);
+ userId, false, ALLOW_FULL_ONLY, reason, null);
// TODO: Switch to user app stacks here.
int ret = mActivityStarter.startActivities(caller, -1, callingPackage, intents,
- resolvedTypes, resultTo, bOptions, userId);
+ resolvedTypes, resultTo, bOptions, userId, reason);
return ret;
}
@@ -4887,11 +4896,12 @@ public class ActivityManagerService extends IActivityManager.Stub
Intent[] intents, String[] resolvedTypes, IBinder resultTo,
Bundle bOptions, int userId) {
+ final String reason = "startActivityInPackage";
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
- userId, false, ALLOW_FULL_ONLY, "startActivityInPackage", null);
+ userId, false, ALLOW_FULL_ONLY, reason, null);
// TODO: Switch to user app stacks here.
int ret = mActivityStarter.startActivities(null, uid, callingPackage, intents, resolvedTypes,
- resultTo, bOptions, userId);
+ resultTo, bOptions, userId, reason);
return ret;
}
@@ -15005,6 +15015,10 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
dumpLastANRLocked(pw);
}
+ } else if ("starter".equals(cmd)) {
+ synchronized (this) {
+ dumpActivityStarterLocked(pw);
+ }
} else if ("recents".equals(cmd) || "r".equals(cmd)) {
synchronized (this) {
dumpRecentsLocked(fd, pw, args, opti, true, dumpPackage);
@@ -15238,6 +15252,11 @@ public class ActivityManagerService extends IActivityManager.Stub
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
+ dumpActivityStarterLocked(pw);
+ pw.println();
+ if (dumpAll) {
+ pw.println("-------------------------------------------------------------------------------");
+ }
dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
if (mAssociations.size() > 0) {
pw.println();
@@ -15303,6 +15322,11 @@ public class ActivityManagerService extends IActivityManager.Stub
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
+ dumpActivityStarterLocked(pw);
+ pw.println();
+ if (dumpAll) {
+ pw.println("-------------------------------------------------------------------------------");
+ }
dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage);
if (mAssociations.size() > 0) {
pw.println();
@@ -15322,14 +15346,19 @@ public class ActivityManagerService extends IActivityManager.Stub
}
private void dumpLastANRLocked(PrintWriter pw) {
+ pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity lastanr)");
if (mLastANRState == null) {
- pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity lastanr)");
pw.println(" <no ANR has occurred since boot>");
} else {
pw.println(mLastANRState);
}
}
+ private void dumpActivityStarterLocked(PrintWriter pw) {
+ pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity starter)");
+ mActivityStarter.dump(pw, "");
+ }
+
void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
dumpActivitiesLocked(fd, pw, args, opti, dumpAll, dumpClient, dumpPackage,
@@ -15356,7 +15385,6 @@ public class ActivityManagerService extends IActivityManager.Stub
if (needSep) {
pw.println();
}
- needSep = true;
printedAnything = true;
mStackSupervisor.dump(pw, " ");
}
@@ -24079,17 +24107,13 @@ public class ActivityManagerService extends IActivityManager.Stub
if (reason != null) {
pw.println(" Reason: " + reason);
}
- pw.println(" mLastHomeActivityStartResult: "
- + mActivityStarter.mLastHomeActivityStartResult);
- final ActivityRecord r = mActivityStarter.mLastHomeActivityStartRecord[0];
- if (r != null) {
- pw.println(" mLastHomeActivityStartRecord:");
- r.dump(pw, " ");
- }
pw.println();
+ mActivityStarter.dump(pw, " ");
+ pw.println();
+ pw.println("-------------------------------------------------------------------------------");
dumpActivitiesLocked(null /* fd */, pw, null /* args */, 0 /* opti */,
true /* dumpAll */, false /* dumpClient */, null /* dumpPackage */,
- "ACTIVITY MANAGER ACTIVITIES (dumpsys activity lastanr)");
+ "" /* header */);
pw.println();
pw.close();
@@ -24331,7 +24355,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
return mActivityStarter.startActivityMayWait(appThread, -1, callingPackage, intent,
resolvedType, null, null, null, null, 0, 0, null, null,
- null, bOptions, false, callingUser, null, tr);
+ null, bOptions, false, callingUser, null, tr, "AppTaskImpl");
}
@Override
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a45becdd1dda..9cde98598987 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3920,7 +3920,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
destIntent, null /*ephemeralIntent*/, null, aInfo, null /*rInfo*/, null,
null, parent.appToken, null, 0, -1, parent.launchedFromUid,
parent.launchedFromPackage, -1, parent.launchedFromUid, 0, null,
- false, true, null, null, null);
+ false, true, null, null, null, "navigateUpTo");
foundParentInTask = res == ActivityManager.START_SUCCESS;
} catch (RemoteException e) {
foundParentInTask = false;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 5d5614c2bb5f..1ccac1b8dc8a 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2273,6 +2273,31 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return null;
}
+ /**
+ * Get next valid stack for launching provided activity in the system. This will search across
+ * displays and stacks in last-focused order for a focusable and visible stack, except those
+ * that are on a currently focused display.
+ *
+ * @param r The activity that is being launched.
+ * @param currentFocus The display that previously had focus and thus needs to be ignored when
+ * searching for the next candidate.
+ * @return Next valid {@link ActivityStack}, null if not found.
+ */
+ ActivityStack getNextValidLaunchStackLocked(@NonNull ActivityRecord r, int currentFocus) {
+ mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
+ for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
+ final int displayId = mTmpOrderedDisplayIds.get(i);
+ if (displayId == currentFocus) {
+ continue;
+ }
+ final ActivityStack stack = getValidLaunchStackOnDisplay(displayId, r);
+ if (stack != null) {
+ return stack;
+ }
+ }
+ return null;
+ }
+
ActivityRecord getHomeActivity() {
return getHomeActivityForUser(mCurrentUser);
}
@@ -5159,7 +5184,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
userId = task.userId;
int result = mService.startActivityInPackage(callingUid, callingPackage, intent, null,
- null, null, 0, 0, bOptions, userId, null, task);
+ null, null, 0, 0, bOptions, userId, null, task, "startActivityFromRecents");
if (launchStackId == DOCKED_STACK_ID) {
setResizingDuringAnimation(task);
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index d74d1d6dc954..a31c33e4ab91 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.app.Activity.RESULT_CANCELED;
+import static android.app.ActivityManager.START_ABORTED;
import static android.app.ActivityManager.START_CANCELED;
import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
@@ -115,6 +116,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.voice.IVoiceInteractionSession;
+import android.text.TextUtils;
import android.util.EventLog;
import android.util.Slog;
@@ -124,7 +126,10 @@ import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
import com.android.server.pm.InstantAppResolver;
import com.android.server.wm.WindowManagerService;
+import java.io.PrintWriter;
+import java.text.DateFormat;
import java.util.ArrayList;
+import java.util.Date;
/**
* Controller for interpreting how and then launching activities.
@@ -189,9 +194,17 @@ class ActivityStarter {
private boolean mUsingVr2dDisplay;
// Last home activity record we attempted to start
- final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
+ private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
// The result of the last home activity we attempted to start.
- int mLastHomeActivityStartResult;
+ private int mLastHomeActivityStartResult;
+ // Last activity record we attempted to start
+ private final ActivityRecord[] mLastStartActivityRecord = new ActivityRecord[1];
+ // The result of the last activity we attempted to start.
+ private int mLastStartActivityResult;
+ // Time in milli seconds we attempted to start the last activity.
+ private long mLastStartActivityTimeMs;
+ // The reason we were trying to start the last activity
+ private String mLastStartReason;
private void reset() {
mStartActivity = null;
@@ -241,7 +254,39 @@ class ActivityStarter {
mUsingVr2dDisplay = false;
}
- final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
+ int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
+ String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
+ IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+ IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
+ String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
+ ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
+ ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
+ TaskRecord inTask, String reason) {
+
+ if (TextUtils.isEmpty(reason)) {
+ throw new IllegalArgumentException("Need to specify a reason.");
+ }
+ mLastStartReason = reason;
+ mLastStartActivityTimeMs = System.currentTimeMillis();
+ mLastStartActivityRecord[0] = null;
+
+ mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
+ aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
+ callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
+ options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
+ container, inTask);
+
+ if (outActivity != null) {
+ // mLastStartActivityRecord[0] is set in the call to startActivity above.
+ outActivity[0] = mLastStartActivityRecord[0];
+ }
+
+ // Aborted results are treated as successes externally, but we must track them internally.
+ return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
+ }
+
+ /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
+ private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
@@ -423,7 +468,7 @@ class ActivityStarter {
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
ActivityOptions.abort(options);
- return START_SUCCESS;
+ return START_ABORTED;
}
// If permissions need a review before any of the app components can run, we
@@ -604,7 +649,7 @@ class ActivityStarter {
null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
- null /*container*/, null /*inTask*/);
+ null /*container*/, null /*inTask*/, "startHomeActivity: " + reason);
if (mSupervisor.inResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
// resumed (to avoid recursive resume) and will stay that way until something pokes it
@@ -629,7 +674,7 @@ class ActivityStarter {
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
- IActivityContainer iContainer, TaskRecord inTask) {
+ IActivityContainer iContainer, TaskRecord inTask, String reason) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -784,7 +829,7 @@ class ActivityStarter {
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
- inTask);
+ inTask, reason);
Binder.restoreCallingIdentity(origId);
@@ -847,7 +892,7 @@ class ActivityStarter {
final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
Intent[] intents, String[] resolvedTypes, IBinder resultTo,
- Bundle bOptions, int userId) {
+ Bundle bOptions, int userId, String reason) {
if (intents == null) {
throw new NullPointerException("intents is null");
}
@@ -909,7 +954,7 @@ class ActivityStarter {
resolvedTypes[i], aInfo, null /*rInfo*/, null, null, resultTo, null, -1,
callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, 0,
- options, false, componentSpecified, outActivity, null, null);
+ options, false, componentSpecified, outActivity, null, null, reason);
if (res < 0) {
return res;
}
@@ -2027,7 +2072,18 @@ class ActivityStarter {
return mSupervisor.mFocusedStack;
}
- if (mSourceDisplayId == DEFAULT_DISPLAY) {
+ if (mSourceDisplayId != DEFAULT_DISPLAY) {
+ // Try to put the activity in a stack on a secondary display.
+ stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
+ if (stack == null) {
+ // If source display is not suitable - look for topmost valid stack in the system.
+ if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
+ "computeStackFocus: Can't launch on mSourceDisplayId=" + mSourceDisplayId
+ + ", looking on all displays.");
+ stack = mSupervisor.getNextValidLaunchStackLocked(r, mSourceDisplayId);
+ }
+ }
+ if (stack == null) {
// We first try to put the task in the first dynamic stack on home display.
final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
@@ -2043,8 +2099,6 @@ class ActivityStarter {
bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
FULLSCREEN_WORKSPACE_STACK_ID;
stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
- } else {
- stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
+ r + " stackId=" + stack.mStackId);
@@ -2252,4 +2306,41 @@ class ActivityStarter {
}
return didSomething;
}
+
+ void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + "ActivityStarter:");
+ prefix = prefix + " ";
+
+ pw.println(prefix + "mCurrentUser=" + mSupervisor.mCurrentUser);
+ pw.println(prefix + "mLastStartReason=" + mLastStartReason);
+ pw.println(prefix + "mLastStartActivityTimeMs="
+ + DateFormat.getDateTimeInstance().format(new Date(mLastStartActivityTimeMs)));
+ pw.println(prefix + "mLastStartActivityResult=" + mLastStartActivityResult);
+ ActivityRecord r = mLastStartActivityRecord[0];
+ if (r != null) {
+ pw.println(prefix + "mLastStartActivityRecord:");
+ r.dump(pw, prefix + " ");
+ }
+ pw.println(prefix + "mLastHomeActivityStartResult=" + mLastHomeActivityStartResult);
+ r = mLastHomeActivityStartRecord[0];
+ if (r != null) {
+ pw.println(prefix + "mLastHomeActivityStartRecord:");
+ r.dump(pw, prefix + " ");
+ }
+ if (mStartActivity != null) {
+ pw.println(prefix + "mStartActivity:");
+ mStartActivity.dump(pw, prefix + " ");
+ }
+ if (mIntent != null) {
+ pw.println(prefix + "mIntent=" + mIntent);
+ }
+ if (mOptions != null) {
+ pw.println(prefix + "mOptions=" + mOptions);
+ }
+ pw.println(prefix + "mLaunchSingleTop=" + mLaunchSingleTop
+ + " mLaunchSingleInstance=" + mLaunchSingleInstance
+ + " mLaunchSingleTask=" + mLaunchSingleTask
+ + " mLaunchFlags=0x" + Integer.toHexString(mLaunchFlags)
+ + " mDoResume=" + mDoResume + " mAddingToTask=" + mAddingToTask);
+ }
}
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index a83f989fbc5d..0d1c579f2b81 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -412,7 +412,7 @@ class AppErrors {
task.mCallingPackage, task.intent,
null, null, null, 0, 0,
ActivityOptions.makeBasic().toBundle(),
- task.userId, null, null);
+ task.userId, null, null, "AppErrors");
}
}
}
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index 2e0ec0b361e2..a46c85170ba2 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
@@ -34,6 +35,7 @@ import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.Trace;
import android.util.Slog;
import com.android.internal.policy.IKeyguardDismissCallback;
@@ -111,22 +113,28 @@ class KeyguardController {
* etc.
*/
void keyguardGoingAway(int flags) {
- if (mKeyguardShowing) {
- mWindowManager.deferSurfaceLayout();
- try {
- setKeyguardGoingAway(true);
- mWindowManager.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
- false /* alwaysKeepCurrent */, convertTransitFlags(flags),
- false /* forceOverride */);
- mService.updateSleepIfNeededLocked();
-
- // Some stack visibility might change (e.g. docked stack)
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- mStackSupervisor.addStartingWindowsForVisibleActivities(true /* taskSwitch */);
- mWindowManager.executeAppTransition();
- } finally {
- mWindowManager.continueSurfaceLayout();
- }
+ if (!mKeyguardShowing) {
+ return;
+ }
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway");
+ mWindowManager.deferSurfaceLayout();
+ try {
+ setKeyguardGoingAway(true);
+ mWindowManager.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
+ false /* alwaysKeepCurrent */, convertTransitFlags(flags),
+ false /* forceOverride */);
+ mService.updateSleepIfNeededLocked();
+
+ // Some stack visibility might change (e.g. docked stack)
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mStackSupervisor.addStartingWindowsForVisibleActivities(true /* taskSwitch */);
+ mWindowManager.executeAppTransition();
+ } finally {
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "keyguardGoingAway: surfaceLayout");
+ mWindowManager.continueSurfaceLayout();
+ Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+
+ Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 6eca3fa7350a..cad5dcf6b565 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -346,7 +346,7 @@ final class PendingIntentRecord extends IIntentSender.Stub {
} else {
owner.startActivityInPackage(uid, key.packageName, finalIntent,
resolvedType, resultTo, resultWho, requestCode, 0,
- options, userId, container, null);
+ options, userId, container, null, "PendingIntentRecord");
}
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startActivity intent", e);
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 702cbbed17de..f9e4d946a178 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -29,6 +29,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.util.ArrayUtils;
+
import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.ArrayList;
@@ -67,6 +69,12 @@ public final class PlaybackActivityMonitor
.createIfNeeded()
.build();
+ // TODO support VolumeShaper on those players
+ private static final int[] UNDUCKABLE_PLAYER_TYPES = {
+ AudioPlaybackConfiguration.PLAYER_TYPE_AAUDIO,
+ AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL,
+ };
+
// like a PLAY_CREATE_IF_NEEDED operation but with a skip to the end of the ramp
private static final VolumeShaper.Operation PLAY_SKIP_RAMP =
new VolumeShaper.Operation.Builder(PLAY_CREATE_IF_NEEDED).setXOffset(1.0f).build();
@@ -298,12 +306,12 @@ public final class PlaybackActivityMonitor
+ " uid:" + apc.getClientUid() + " pid:" + apc.getClientPid()
+ " - SPEECH");
return false;
- } else if (apc.getPlayerType()
- == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
- // TODO support ducking of SoundPool players
+ } else if (ArrayUtils.contains(UNDUCKABLE_PLAYER_TYPES, apc.getPlayerType())) {
Log.v(TAG, "not ducking player " + apc.getPlayerInterfaceId()
+ " uid:" + apc.getClientUid() + " pid:" + apc.getClientPid()
- + " - SoundPool");
+ + " due to type:"
+ + AudioPlaybackConfiguration.toLogFriendlyPlayerType(
+ apc.getPlayerType()));
return false;
}
apcsToDuck.add(apc);
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 37ef1320d755..e5fc4b1d1775 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -831,30 +831,41 @@ public class Tethering extends BaseNetworkObserver {
case WifiManager.WIFI_AP_STATE_DISABLING:
case WifiManager.WIFI_AP_STATE_FAILED:
default:
- disableWifiIpServingLocked(curState);
+ disableWifiIpServingLocked(ifname, curState);
break;
}
}
}
}
- // TODO: Pass in the interface name and, if non-empty, only turn down IP
- // serving on that one interface.
- private void disableWifiIpServingLocked(int apState) {
- if (DBG) Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" + apState);
+ private void disableWifiIpServingLocked(String ifname, int apState) {
+ mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState);
+
+ // Regardless of whether we requested this transition, the AP has gone
+ // down. Don't try to tether again unless we're requested to do so.
+ // TODO: Remove this altogether, once Wi-Fi reliably gives us an
+ // interface name with every broadcast.
+ mWifiTetherRequested = false;
+
+ if (!TextUtils.isEmpty(ifname)) {
+ final TetherState ts = mTetherStates.get(ifname);
+ if (ts != null) {
+ ts.stateMachine.unwanted();
+ return;
+ }
+ }
- // Tell appropriate interface state machines that they should tear
- // themselves down.
for (int i = 0; i < mTetherStates.size(); i++) {
TetherInterfaceStateMachine tism = mTetherStates.valueAt(i).stateMachine;
if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
- tism.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
- break; // There should be at most one of these.
+ tism.unwanted();
+ return;
}
}
- // Regardless of whether we requested this transition, the AP has gone
- // down. Don't try to tether again unless we're requested to do so.
- mWifiTetherRequested = false;
+
+ mLog.log("Error disabling Wi-Fi IP serving; " +
+ (TextUtils.isEmpty(ifname) ? "no interface name specified"
+ : "specified interface: " + ifname));
}
private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
@@ -874,6 +885,7 @@ public class Tethering extends BaseNetworkObserver {
}
if (!TextUtils.isEmpty(ifname)) {
+ maybeTrackNewInterfaceLocked(ifname, ConnectivityManager.TETHERING_WIFI);
changeInterfaceState(ifname, ipServingMode);
} else {
mLog.e(String.format(
@@ -1257,10 +1269,10 @@ public class Tethering extends BaseNetworkObserver {
sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
}
}
- setUpstreamByType(ns);
+ setUpstreamNetwork(ns);
}
- protected void setUpstreamByType(NetworkState ns) {
+ protected void setUpstreamNetwork(NetworkState ns) {
String iface = null;
if (ns != null && ns.linkProperties != null) {
// Find the interface with the default IPv4 route. It may be the
@@ -1779,7 +1791,9 @@ public class Tethering extends BaseNetworkObserver {
}
}
- mLog.log(String.format("OBSERVED LinkProperties update iface=%s state=%s", iface, state));
+ mLog.log(String.format(
+ "OBSERVED LinkProperties update iface=%s state=%s lp=%s",
+ iface, IControlsTethering.getStateString(state), newLp));
final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
mTetherMasterSM.sendMessage(which, state, 0, newLp);
}
@@ -1791,7 +1805,10 @@ public class Tethering extends BaseNetworkObserver {
mLog.log(iface + " is not a tetherable iface, ignoring");
return;
}
+ maybeTrackNewInterfaceLocked(iface, interfaceType);
+ }
+ private void maybeTrackNewInterfaceLocked(final String iface, int interfaceType) {
// If we have already started a TISM for this interface, skip.
if (mTetherStates.containsKey(iface)) {
mLog.log("active iface (" + iface + ") reported as added, ignoring");
diff --git a/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java b/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java
index aaa63b1613df..2b813475222f 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java
@@ -33,6 +33,16 @@ public class IControlsTethering {
public static final int STATE_TETHERED = 2;
public static final int STATE_LOCAL_ONLY = 3;
+ public static String getStateString(int state) {
+ switch (state) {
+ case STATE_UNAVAILABLE: return "UNAVAILABLE";
+ case STATE_AVAILABLE: return "AVAILABLE";
+ case STATE_TETHERED: return "TETHERED";
+ case STATE_LOCAL_ONLY: return "LOCAL_ONLY";
+ }
+ return "UNKNOWN: " + state;
+ }
+
/**
* Notify that |who| has changed its tethering state.
*
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
index ce6b8be77d44..08deef84f3ae 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -85,13 +85,16 @@ public class OffloadController {
mLog.i("tethering offload control not supported");
stop();
}
+ mLog.log("tethering offload started");
}
public void stop() {
+ final boolean wasStarted = started();
mUpstreamLinkProperties = null;
mHwInterface.stopOffloadControl();
mControlInitialized = false;
mConfigInitialized = false;
+ if (wasStarted) mLog.log("tethering offload stopped");
}
public void setUpstreamLinkProperties(LinkProperties lp) {
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 b88361f5677c..86b255128d6d 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -56,9 +56,10 @@ import java.util.Objects;
import java.util.Random;
/**
- * @hide
+ * Provides the interface to IP-layer serving functionality for a given network
+ * interface, e.g. for tethering or "local-only hotspot" mode.
*
- * Tracks the eligibility of a given network interface for tethering.
+ * @hide
*/
public class TetherInterfaceStateMachine extends StateMachine {
private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
@@ -117,6 +118,12 @@ public class TetherInterfaceStateMachine extends StateMachine {
private String mMyUpstreamIfaceName; // may change over time
private NetworkInterface mNetworkInterface;
private byte[] mHwAddr;
+ // TODO: De-duplicate this with mLinkProperties above. Currently, these link
+ // properties are those selected by the IPv6TetheringCoordinator and relayed
+ // to us. By comparison, mLinkProperties contains the addresses and directly
+ // connected routes that have been formed from these properties iff. we have
+ // succeeded in configuring them and are able to announce them within Router
+ // Advertisements (otherwise, we do not add them to mLinkProperties at all).
private LinkProperties mLastIPv6LinkProperties;
private RouterAdvertisementDaemon mRaDaemon;
private RaParams mLastRaParams;
@@ -133,7 +140,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
mIfaceName = ifaceName;
mInterfaceType = interfaceType;
mLinkProperties = new LinkProperties();
- mLinkProperties.setInterfaceName(mIfaceName);
+ resetLinkProperties();
mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
mInitialState = new InitialState();
@@ -156,14 +163,21 @@ public class TetherInterfaceStateMachine extends StateMachine {
public void stop() { sendMessage(CMD_INTERFACE_DOWN); }
+ public void unwanted() { sendMessage(CMD_TETHER_UNREQUESTED); }
+
/**
* Internals.
*/
- // configured when we start tethering and unconfig'd on error or conclusion
- private boolean configureIfaceIp(boolean enabled) {
- if (VDBG) Log.d(TAG, "configureIfaceIp(" + enabled + ")");
+ private boolean startIPv4() { return configureIPv4(true); }
+
+ private void stopIPv4() { configureIPv4(false); }
+
+ private boolean configureIPv4(boolean enabled) {
+ if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");
+ // TODO: Replace this hard-coded information with dynamically selected
+ // config passed down to us by a higher layer IP-coordinating element.
String ipAsString = null;
int prefixLen = 0;
if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
@@ -177,32 +191,45 @@ public class TetherInterfaceStateMachine extends StateMachine {
return true;
}
- InterfaceConfiguration ifcg = null;
+ final LinkAddress linkAddr;
try {
- ifcg = mNMService.getInterfaceConfig(mIfaceName);
- if (ifcg != null) {
- InetAddress addr = NetworkUtils.numericToInetAddress(ipAsString);
- ifcg.setLinkAddress(new LinkAddress(addr, prefixLen));
- if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
- // The WiFi stack has ownership of the interface up/down state.
- // It is unclear whether the bluetooth or USB stacks will manage their own
- // state.
- ifcg.ignoreInterfaceUpDownStatus();
+ final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName);
+ if (ifcg == null) {
+ mLog.e("Received null interface config");
+ return false;
+ }
+
+ InetAddress addr = NetworkUtils.numericToInetAddress(ipAsString);
+ linkAddr = new LinkAddress(addr, prefixLen);
+ ifcg.setLinkAddress(linkAddr);
+ if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
+ // The WiFi stack has ownership of the interface up/down state.
+ // It is unclear whether the Bluetooth or USB stacks will manage their own
+ // state.
+ ifcg.ignoreInterfaceUpDownStatus();
+ } else {
+ if (enabled) {
+ ifcg.setInterfaceUp();
} else {
- if (enabled) {
- ifcg.setInterfaceUp();
- } else {
- ifcg.setInterfaceDown();
- }
+ ifcg.setInterfaceDown();
}
- ifcg.clearFlag("running");
- mNMService.setInterfaceConfig(mIfaceName, ifcg);
}
+ ifcg.clearFlag("running");
+ mNMService.setInterfaceConfig(mIfaceName, ifcg);
} catch (Exception e) {
mLog.e("Error configuring interface " + e);
return false;
}
+ // Directly-connected route.
+ final RouteInfo route = new RouteInfo(linkAddr);
+ if (enabled) {
+ mLinkProperties.addLinkAddress(linkAddr);
+ mLinkProperties.addRoute(route);
+ } else {
+ mLinkProperties.removeLinkAddress(linkAddr);
+ mLinkProperties.removeRoute(route);
+ }
return true;
}
@@ -292,7 +319,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
mLastIPv6LinkProperties = v6only;
}
- private void configureLocalRoutes(
+ private void configureLocalIPv6Routes(
HashSet<IpPrefix> deprecatedPrefixes, HashSet<IpPrefix> newPrefixes) {
// [1] Remove the routes that are deprecated.
if (!deprecatedPrefixes.isEmpty()) {
@@ -307,6 +334,8 @@ public class TetherInterfaceStateMachine extends StateMachine {
} catch (RemoteException e) {
mLog.e("Failed to remove IPv6 routes from local table: " + e);
}
+
+ for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route);
}
// [2] Add only the routes that have not previously been added.
@@ -338,11 +367,13 @@ public class TetherInterfaceStateMachine extends StateMachine {
} catch (RemoteException e) {
mLog.e("Failed to add IPv6 routes to local table: " + e);
}
+
+ for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route);
}
}
}
- private void configureLocalDns(
+ private void configureLocalIPv6Dns(
HashSet<Inet6Address> deprecatedDnses, HashSet<Inet6Address> newDnses) {
final INetd netd = NetdService.getInstance();
if (netd == null) {
@@ -360,6 +391,8 @@ public class TetherInterfaceStateMachine extends StateMachine {
} catch (ServiceSpecificException | RemoteException e) {
mLog.e("Failed to remove local dns IP " + dnsString + ": " + e);
}
+
+ mLinkProperties.removeLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH));
}
}
@@ -378,6 +411,8 @@ public class TetherInterfaceStateMachine extends StateMachine {
mLog.e("Failed to add local dns IP " + dnsString + ": " + e);
newDnses.remove(dns);
}
+
+ mLinkProperties.addLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH));
}
}
@@ -394,10 +429,10 @@ public class TetherInterfaceStateMachine extends StateMachine {
final RaParams deprecatedParams =
RaParams.getDeprecatedRaParams(mLastRaParams, newParams);
- configureLocalRoutes(deprecatedParams.prefixes,
+ configureLocalIPv6Routes(deprecatedParams.prefixes,
(newParams != null) ? newParams.prefixes : null);
- configureLocalDns(deprecatedParams.dnses,
+ configureLocalIPv6Dns(deprecatedParams.dnses,
(newParams != null) ? newParams.dnses : null);
mRaDaemon.buildNewRa(deprecatedParams, newParams);
@@ -417,12 +452,19 @@ public class TetherInterfaceStateMachine extends StateMachine {
private void sendInterfaceState(int newInterfaceState) {
mTetherController.updateInterfaceState(
TetherInterfaceStateMachine.this, newInterfaceState, mLastError);
- // TODO: Populate mLinkProperties correctly, and send more sensible
- // updates more frequently (not just here).
+ sendLinkProperties();
+ }
+
+ private void sendLinkProperties() {
mTetherController.updateLinkProperties(
TetherInterfaceStateMachine.this, new LinkProperties(mLinkProperties));
}
+ private void resetLinkProperties() {
+ mLinkProperties.clear();
+ mLinkProperties.setInterfaceName(mIfaceName);
+ }
+
class InitialState extends State {
@Override
public void enter() {
@@ -462,7 +504,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
class BaseServingState extends State {
@Override
public void enter() {
- if (!configureIfaceIp(true)) {
+ if (!startIPv4()) {
mLastError = ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR;
return;
}
@@ -496,7 +538,9 @@ public class TetherInterfaceStateMachine extends StateMachine {
mLog.e("Failed to untether interface: " + e);
}
- configureIfaceIp(false);
+ stopIPv4();
+
+ resetLinkProperties();
}
@Override
@@ -513,6 +557,7 @@ public class TetherInterfaceStateMachine extends StateMachine {
break;
case CMD_IPV6_TETHER_UPDATE:
updateUpstreamIPv6LinkProperties((LinkProperties) message.obj);
+ sendLinkProperties();
break;
case CMD_IP_FORWARDING_ENABLE_ERROR:
case CMD_IP_FORWARDING_DISABLE_ERROR:
@@ -623,7 +668,6 @@ public class TetherInterfaceStateMachine extends StateMachine {
if (super.processMessage(message)) return true;
maybeLogMessage(this, message.what);
- boolean retValue = true;
switch (message.what) {
case CMD_TETHER_REQUESTED:
mLog.e("CMD_TETHER_REQUESTED while already tethering.");
@@ -653,10 +697,9 @@ public class TetherInterfaceStateMachine extends StateMachine {
mMyUpstreamIfaceName = newUpstreamIfaceName;
break;
default:
- retValue = false;
- break;
+ return false;
}
- return retValue;
+ return true;
}
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index b7fbfb756b1d..7efa1664788c 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -17,6 +17,7 @@
package com.android.server.connectivity.tethering;
import static android.content.Context.TELEPHONY_SERVICE;
+import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
@@ -211,29 +212,26 @@ public class TetheringConfiguration {
// *always* an upstream, regardless of the upstream interface types
// specified by configuration resources.
if (dunCheck == DUN_REQUIRED) {
- if (!upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)) {
- upstreamIfaceTypes.add(TYPE_MOBILE_DUN);
- }
+ appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_DUN);
} else if (dunCheck == DUN_NOT_REQUIRED) {
- if (!upstreamIfaceTypes.contains(TYPE_MOBILE)) {
- upstreamIfaceTypes.add(TYPE_MOBILE);
- }
- if (!upstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)) {
- upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI);
- }
+ appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE);
+ appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_HIPRI);
} else {
// Fix upstream interface types for case DUN_UNSPECIFIED.
// Do not modify if a cellular interface type is already present in the
// upstream interface types. Add TYPE_MOBILE and TYPE_MOBILE_HIPRI if no
// cellular interface types are found in the upstream interface types.
- if (!(upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)
- || upstreamIfaceTypes.contains(TYPE_MOBILE)
- || upstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI))) {
+ if (!(containsOneOf(upstreamIfaceTypes,
+ TYPE_MOBILE_DUN, TYPE_MOBILE, TYPE_MOBILE_HIPRI))) {
upstreamIfaceTypes.add(TYPE_MOBILE);
upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI);
}
}
+ // Always make sure our good friend Ethernet is present.
+ // TODO: consider unilaterally forcing this at the front.
+ prependIfNotPresent(upstreamIfaceTypes, TYPE_ETHERNET);
+
return upstreamIfaceTypes;
}
@@ -256,4 +254,21 @@ public class TetheringConfiguration {
private static String[] copy(String[] strarray) {
return Arrays.copyOf(strarray, strarray.length);
}
+
+ private static void prependIfNotPresent(ArrayList<Integer> list, int value) {
+ if (list.contains(value)) return;
+ list.add(0, value);
+ }
+
+ private static void appendIfNotPresent(ArrayList<Integer> list, int value) {
+ if (list.contains(value)) return;
+ list.add(value);
+ }
+
+ private static boolean containsOneOf(ArrayList<Integer> list, Integer... values) {
+ for (Integer value : values) {
+ if (list.contains(value)) return true;
+ }
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 13054a643e52..468cb2990b67 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -60,6 +60,7 @@ import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
@@ -166,6 +167,8 @@ public final class ContentService extends IContentService.Stub {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw_)) return;
final IndentingPrintWriter pw = new IndentingPrintWriter(pw_, " ");
+ final boolean dumpAll = ArrayUtils.contains(args, "-a");
+
// This makes it so that future permission checks will be in the context of this
// process rather than the caller's process. We will restore this before returning.
final long identityToken = clearCallingIdentity();
@@ -173,7 +176,7 @@ public final class ContentService extends IContentService.Stub {
if (mSyncManager == null) {
pw.println("No SyncManager created! (Disk full?)");
} else {
- mSyncManager.dump(fd, pw);
+ mSyncManager.dump(fd, pw, dumpAll);
}
pw.println();
pw.println("Observer tree:");
@@ -603,7 +606,7 @@ public final class ContentService extends IContentService.Stub {
SyncStorageEngine.EndPoint info;
info = new SyncStorageEngine.EndPoint(account, authority, userId);
syncManager.clearScheduledSyncOperations(info);
- syncManager.cancelActiveSync(info, null /* all syncs for this adapter */);
+ syncManager.cancelActiveSync(info, null /* all syncs for this adapter */, "API");
}
} finally {
restoreCallingIdentity(identityToken);
@@ -631,7 +634,7 @@ public final class ContentService extends IContentService.Stub {
}
// Cancel active syncs and clear pending syncs from the queue.
syncManager.cancelScheduledSyncOperation(info, extras);
- syncManager.cancelActiveSync(info, extras);
+ syncManager.cancelActiveSync(info, extras, "API");
} finally {
restoreCallingIdentity(identityToken);
}
diff --git a/services/core/java/com/android/server/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java
index a621d7376b7f..1f02ebfc4972 100644
--- a/services/core/java/com/android/server/content/SyncJobService.java
+++ b/services/core/java/com/android/server/content/SyncJobService.java
@@ -34,6 +34,8 @@ public class SyncJobService extends JobService {
private Messenger mMessenger;
private SparseArray<JobParameters> jobParamsMap = new SparseArray<JobParameters>();
+ private final SyncLogger mLogger = SyncLogger.getInstance();
+
/**
* This service is started by the SyncManager which passes a messenger object to
* communicate back with it. It never stops while the device is running.
@@ -63,6 +65,9 @@ public class SyncJobService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
+
+ mLogger.purgeOldLogs();
+
boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
synchronized (jobParamsMap) {
jobParamsMap.put(params.getJobId(), params);
@@ -70,6 +75,9 @@ public class SyncJobService extends JobService {
Message m = Message.obtain();
m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC;
SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
+
+ mLogger.log("onStopJob() jobid=", params.getJobId(), " op=", op);
+
if (op == null) {
Slog.e(TAG, "Got invalid job " + params.getJobId());
return false;
@@ -88,7 +96,7 @@ public class SyncJobService extends JobService {
Slog.v(TAG, "onStopJob called " + params.getJobId() + ", reason: "
+ params.getStopReason());
}
-
+ mLogger.log("onStopJob() ", mLogger.jobParametersToString(params));
synchronized (jobParamsMap) {
jobParamsMap.remove(params.getJobId());
}
@@ -108,9 +116,13 @@ public class SyncJobService extends JobService {
return false;
}
- public void callJobFinished(int jobId, boolean needsReschedule) {
+ public void callJobFinished(int jobId, boolean needsReschedule, String why) {
synchronized (jobParamsMap) {
JobParameters params = jobParamsMap.get(jobId);
+ mLogger.log("callJobFinished()",
+ " needsReschedule=", needsReschedule,
+ " ", mLogger.jobParametersToString(params),
+ " why=", why);
if (params != null) {
jobFinished(params, needsReschedule);
jobParamsMap.remove(jobId);
diff --git a/services/core/java/com/android/server/content/SyncLogger.java b/services/core/java/com/android/server/content/SyncLogger.java
new file mode 100644
index 000000000000..db794643b4df
--- /dev/null
+++ b/services/core/java/com/android/server/content/SyncLogger.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2017 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.content;
+
+import android.app.job.JobParameters;
+import android.os.Build;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.os.SystemProperties;
+import android.text.format.DateUtils;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import libcore.io.IoUtils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Implements a rotating file logger for the sync manager, which is enabled only on userdebug/eng
+ * builds (unless debug.synclog is set to 1).
+ *
+ * Note this class could be used for other purposes too, but in general we don't want various
+ * system components to log to files, so it's put in a local package here.
+ */
+public class SyncLogger {
+ private static final String TAG = "SyncLogger";
+
+ private static SyncLogger sInstance;
+
+ SyncLogger() {
+ }
+
+ /**
+ * @return the singleton instance.
+ */
+ public static synchronized SyncLogger getInstance() {
+ if (sInstance == null) {
+ final boolean enable = "1".equals(SystemProperties.get("debug.synclog",
+ Build.IS_DEBUGGABLE ? "1" : "0"));
+ if (enable) {
+ sInstance = new RotatingFileLogger();
+ } else {
+ sInstance = new SyncLogger();
+ }
+ }
+ return sInstance;
+ }
+
+ /**
+ * Write strings to the log file.
+ */
+ public void log(Object... message) {
+ }
+
+ /**
+ * Remove old log files.
+ */
+ public void purgeOldLogs() {
+ // The default implementation is no-op.
+ }
+
+ public String jobParametersToString(JobParameters params) {
+ // The default implementation is no-op.
+ return "";
+ }
+
+ /**
+ * Dump all existing log files into a given writer.
+ */
+ public void dumpAll(PrintWriter pw) {
+ }
+
+ /**
+ * Actual implementation which is only used on userdebug/eng builds (by default).
+ */
+ private static class RotatingFileLogger extends SyncLogger {
+ private final Object mLock = new Object();
+
+ private final long mKeepAgeMs = TimeUnit.DAYS.toMillis(7);
+
+ private static final SimpleDateFormat sTimestampFormat
+ = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+
+ private static final SimpleDateFormat sFilenameDateFormat
+ = new SimpleDateFormat("yyyy-MM-dd");
+
+ @GuardedBy("mLock")
+ private final Date mCachedDate = new Date();
+
+ @GuardedBy("mLock")
+ private final StringBuilder mStringBuilder = new StringBuilder();
+
+ private final File mLogPath;
+
+ @GuardedBy("mLock")
+ private long mCurrentLogFileDayTimestamp;
+
+ @GuardedBy("mLock")
+ private Writer mLogWriter;
+
+ @GuardedBy("mLock")
+ private boolean mErrorShown;
+
+ RotatingFileLogger() {
+ mLogPath = new File(Environment.getDataSystemDirectory(), "syncmanager-log");
+ }
+
+ private void handleException(String message, Exception e) {
+ if (!mErrorShown) {
+ Slog.e(TAG, message, e);
+ mErrorShown = true;
+ }
+ }
+
+ @Override
+ public void log(Object... message) {
+ if (message == null) {
+ return;
+ }
+ synchronized (mLock) {
+ final long now = System.currentTimeMillis();
+ openLogLocked(now);
+ if (mLogWriter == null) {
+ return; // Couldn't open log file?
+ }
+
+ mStringBuilder.setLength(0);
+ mCachedDate.setTime(now);
+ mStringBuilder.append(sTimestampFormat.format(mCachedDate));
+ mStringBuilder.append(' ');
+
+ mStringBuilder.append(android.os.Process.myTid());
+ mStringBuilder.append(' ');
+
+ for (Object o : message) {
+ mStringBuilder.append(o);
+ }
+ mStringBuilder.append('\n');
+
+ try {
+ mLogWriter.append(mStringBuilder);
+ mLogWriter.flush();
+ } catch (IOException e) {
+ handleException("Failed to write log", e);
+ }
+ }
+ }
+
+ private void openLogLocked(long now) {
+ // If we already have a log file opened and the date has't changed, just use it.
+ final long day = now % DateUtils.DAY_IN_MILLIS;
+ if ((mLogWriter != null) && (day == mCurrentLogFileDayTimestamp)) {
+ return;
+ }
+
+ // Otherwise create a new log file.
+ closeCurrentLogLocked();
+
+ mCurrentLogFileDayTimestamp = day;
+
+ mCachedDate.setTime(now);
+ final String filename = "synclog-" + sFilenameDateFormat.format(mCachedDate) + ".log";
+ final File file = new File(mLogPath, filename);
+
+ file.getParentFile().mkdirs();
+
+ try {
+ mLogWriter = new FileWriter(file, /* append= */ true);
+ } catch (IOException e) {
+ handleException("Failed to open log file: " + file, e);
+ }
+ }
+
+ private void closeCurrentLogLocked() {
+ IoUtils.closeQuietly(mLogWriter);
+ mLogWriter = null;
+ }
+
+ @Override
+ public void purgeOldLogs() {
+ synchronized (mLock) {
+ FileUtils.deleteOlderFiles(mLogPath, /* keepCount= */ 1, mKeepAgeMs);
+ }
+ }
+
+ @Override
+ public String jobParametersToString(JobParameters params) {
+ if (params == null) {
+ return "job:null";
+ } else {
+ return "job:#" + params.getJobId() + ":"
+ + SyncOperation.maybeCreateFromJobExtras(params.getExtras());
+ }
+ }
+
+ @Override
+ public void dumpAll(PrintWriter pw) {
+ synchronized (mLock) {
+ final String[] files = mLogPath.list();
+ if (files == null || (files.length == 0)) {
+ return;
+ }
+ Arrays.sort(files);
+
+ for (String file : files) {
+ dumpFile(pw, new File(mLogPath, file));
+ }
+ }
+ }
+
+ private void dumpFile(PrintWriter pw, File file) {
+ Slog.w(TAG, "Dumping " + file);
+ final char[] buffer = new char[32 * 1024];
+
+ try (Reader in = new BufferedReader(new FileReader(file))) {
+ int read;
+ while ((read = in.read(buffer)) >= 0) {
+ if (read > 0) {
+ pw.write(buffer, 0, read);
+ }
+ }
+ } catch (IOException e) {
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 3ca65cd0b826..35591420af50 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -74,7 +74,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.WorkSource;
import android.provider.Settings;
-import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.EventLog;
import android.util.Log;
@@ -113,6 +112,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
+import java.util.function.Predicate;
/**
* Implementation details:
@@ -241,6 +241,8 @@ public class SyncManager {
private final Random mRand;
+ private final SyncLogger mLogger;
+
private boolean isJobIdInUseLockedH(int jobId, List<JobInfo> pendingJobs) {
for (JobInfo job: pendingJobs) {
if (job.getId() == jobId) {
@@ -289,13 +291,15 @@ public class SyncManager {
mStorageIsLow = true;
cancelActiveSync(
SyncStorageEngine.EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL,
- null /* any sync */);
+ null /* any sync */,
+ "storage low");
} else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.v(TAG, "Internal storage is ok.");
}
mStorageIsLow = false;
- rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL);
+ rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL,
+ "storage ok");
}
}
};
@@ -378,15 +382,16 @@ public class SyncManager {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.v(TAG, "Reconnection detected: clearing all backoffs");
}
+ // Note the location of this code was wrong from nyc to oc; fixed in DR.
+ clearAllBackoffs("network reconnect");
}
- clearAllBackoffs();
}
}
};
- private void clearAllBackoffs() {
+ private void clearAllBackoffs(String why) {
mSyncStorageEngine.clearAllBackoffsLocked();
- rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL);
+ rescheduleSyncs(EndPoint.USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL, why);
}
private boolean readDataConnectionState() {
@@ -502,6 +507,8 @@ public class SyncManager {
// and creating threads and so on; it may fail if the disk is full.
mContext = context;
+ mLogger = SyncLogger.getInstance();
+
SyncStorageEngine.init(context);
mSyncStorageEngine = SyncStorageEngine.getSingleton();
mSyncStorageEngine.setOnSyncRequestListener(new OnSyncRequestListener() {
@@ -1145,8 +1152,12 @@ public class SyncManager {
mSyncHandler.sendMessage(msg);
}
- private void sendCancelSyncsMessage(final SyncStorageEngine.EndPoint info, Bundle extras) {
+ private void sendCancelSyncsMessage(final SyncStorageEngine.EndPoint info, Bundle extras,
+ String why) {
if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "sending MESSAGE_CANCEL");
+
+ mLogger.log("sendCancelSyncsMessage() ep=", info, " why=", why);
+
Message msg = mSyncHandler.obtainMessage();
msg.what = SyncHandler.MESSAGE_CANCEL;
msg.setData(extras);
@@ -1227,7 +1238,7 @@ public class SyncManager {
}
}
- private void clearBackoffSetting(EndPoint target) {
+ private void clearBackoffSetting(EndPoint target, String why) {
Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(target);
if (backoff != null && backoff.first == SyncStorageEngine.NOT_IN_BACKOFF_MODE &&
backoff.second == SyncStorageEngine.NOT_IN_BACKOFF_MODE) {
@@ -1240,7 +1251,7 @@ public class SyncManager {
SyncStorageEngine.NOT_IN_BACKOFF_MODE,
SyncStorageEngine.NOT_IN_BACKOFF_MODE);
- rescheduleSyncs(target);
+ rescheduleSyncs(target, why);
}
private void increaseBackoffSetting(EndPoint target) {
@@ -1281,14 +1292,16 @@ public class SyncManager {
Slog.v(TAG, "Backoff until: " + backoff + ", delayTime: " + newDelayInMs);
}
mSyncStorageEngine.setBackoff(target, backoff, newDelayInMs);
- rescheduleSyncs(target);
+ rescheduleSyncs(target, "increaseBackoffSetting");
}
/**
* Reschedule all scheduled syncs for this EndPoint. The syncs will be scheduled according
* to current backoff and delayUntil values of this EndPoint.
*/
- private void rescheduleSyncs(EndPoint target) {
+ private void rescheduleSyncs(EndPoint target, String why) {
+ mLogger.log("rescheduleSyncs() ep=", target, " why=", why);
+
List<SyncOperation> ops = getAllPendingSyncs();
int count = 0;
for (SyncOperation op: ops) {
@@ -1316,7 +1329,7 @@ public class SyncManager {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.v(TAG, "Delay Until time set to " + newDelayUntilTime + " for " + target);
}
- rescheduleSyncs(target);
+ rescheduleSyncs(target, "delayUntil newDelayUntilTime: " + newDelayUntilTime);
}
private boolean isAdapterDelayed(EndPoint target) {
@@ -1338,8 +1351,8 @@ public class SyncManager {
* have null account/provider info to specify all accounts/providers.
* @param extras if non-null, specifies the exact sync to remove.
*/
- public void cancelActiveSync(SyncStorageEngine.EndPoint info, Bundle extras) {
- sendCancelSyncsMessage(info, extras);
+ public void cancelActiveSync(SyncStorageEngine.EndPoint info, Bundle extras, String why) {
+ sendCancelSyncsMessage(info, extras, why);
}
/**
@@ -1599,7 +1612,8 @@ public class SyncManager {
null /* any account */,
null /* any authority */,
userId),
- null /* any sync. */
+ null /* any sync. */,
+ "onUserStopped"
);
}
@@ -1759,13 +1773,15 @@ public class SyncManager {
}
}
- protected void dump(FileDescriptor fd, PrintWriter pw) {
+ protected void dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll) {
final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
- dumpPendingSyncs(pw);
- dumpPeriodicSyncs(pw);
dumpSyncState(ipw);
- dumpSyncHistory(ipw);
dumpSyncAdapters(ipw);
+
+ if (dumpAll) {
+ ipw.println("Detailed Sync History");
+ mLogger.dumpAll(pw);
+ }
}
static String formatTime(long time) {
@@ -1774,9 +1790,58 @@ public class SyncManager {
return tobj.format("%Y-%m-%d %H:%M:%S");
}
+ private final static Comparator<SyncOperation> sOpDumpComparator = (op1, op2) -> {
+ int res = Integer.compare(op1.target.userId, op2.target.userId);
+ if (res != 0) return res;
+
+ final Comparator<String> stringComparator = String.CASE_INSENSITIVE_ORDER;
+
+ res = stringComparator.compare(op1.target.account.type, op2.target.account.type);
+ if (res != 0) return res;
+
+ res = stringComparator.compare(op1.target.account.name, op2.target.account.name);
+ if (res != 0) return res;
+
+ res = stringComparator.compare(op1.target.provider, op2.target.provider);
+ if (res != 0) return res;
+
+ res = Integer.compare(op1.reason, op2.reason);
+ if (res != 0) return res;
+
+ res = Long.compare(op1.periodMillis, op2.periodMillis);
+ if (res != 0) return res;
+
+ res = Long.compare(op1.expectedRuntime, op2.expectedRuntime);
+ if (res != 0) return res;
+
+ res = Long.compare(op1.jobId, op2.jobId);
+ if (res != 0) return res;
+
+ return 0;
+ };
+
+ private final static Comparator<SyncOperation> sOpRuntimeComparator = (op1, op2) -> {
+ int res = Long.compare(op1.expectedRuntime, op2.expectedRuntime);
+ if (res != 0) return res;
+
+ return sOpDumpComparator.compare(op1, op2);
+ };
+
+ private static <T> int countIf(Collection<T> col, Predicate<T> p) {
+ int ret = 0;
+ for (T item : col) {
+ if (p.test(item)) ret++;
+ }
+ return ret;
+ }
+
protected void dumpPendingSyncs(PrintWriter pw) {
- pw.println("Pending Syncs:");
List<SyncOperation> pendingSyncs = getAllPendingSyncs();
+
+ pw.print("Pending Syncs: ");
+ pw.println(countIf(pendingSyncs, op -> !op.isPeriodic));
+
+ Collections.sort(pendingSyncs, sOpRuntimeComparator);
int count = 0;
for (SyncOperation op: pendingSyncs) {
if (!op.isPeriodic) {
@@ -1784,13 +1849,16 @@ public class SyncManager {
count++;
}
}
- pw.println("Total: " + count);
pw.println();
}
protected void dumpPeriodicSyncs(PrintWriter pw) {
- pw.println("Periodic Syncs:");
List<SyncOperation> pendingSyncs = getAllPendingSyncs();
+
+ pw.print("Periodic Syncs: ");
+ pw.println(countIf(pendingSyncs, op -> op.isPeriodic));
+
+ Collections.sort(pendingSyncs, sOpDumpComparator);
int count = 0;
for (SyncOperation op: pendingSyncs) {
if (op.isPeriodic) {
@@ -1798,11 +1866,62 @@ public class SyncManager {
count++;
}
}
- pw.println("Total: " + count);
pw.println();
}
+ /**
+ * Similar to {@link android.util.TimeUtils#formatDuration}, but it's more suitable and concise
+ * for the sync manager dumpsys. (Don't add the leading + sign, don't show milliseconds.)
+ */
+ public static StringBuilder formatDurationHMS(StringBuilder sb, long duration) {
+ duration /= 1000;
+ if (duration < 0) {
+ sb.append('-');
+ duration = -duration;
+ }
+ final long seconds = duration % 60;
+ duration /= 60;
+
+ final long minutes = duration % 60;
+ duration /= 60;
+
+ final long hours = duration % 24;
+ duration /= 24;
+
+ final long days = duration;
+
+ boolean print = false;
+ if (days > 0) {
+ sb.append(days);
+ sb.append('d');
+ print = true;
+ }
+ print = printTwoDigitNumber(sb, hours, 'h', print);
+ print = printTwoDigitNumber(sb, minutes, 'm', print);
+ print = printTwoDigitNumber(sb, seconds, 's', print);
+ if (!print) {
+ sb.append("0s");
+ }
+
+ return sb;
+ }
+
+ private static boolean printTwoDigitNumber(StringBuilder sb, long value, char unit,
+ boolean always) {
+ if (!always && (value == 0)) {
+ return false;
+ }
+ if (always && (value < 10)) {
+ sb.append('0');
+ }
+ sb.append(value);
+ sb.append(unit);
+ return true;
+ }
+
protected void dumpSyncState(PrintWriter pw) {
+ final StringBuilder sb = new StringBuilder();
+
pw.print("data connected: "); pw.println(mDataConnectionIsConnected);
pw.print("auto sync: ");
List<UserInfo> users = getAllUsers();
@@ -1828,13 +1947,16 @@ public class SyncManager {
final long now = SystemClock.elapsedRealtime();
pw.print("now: "); pw.print(now);
pw.println(" (" + formatTime(System.currentTimeMillis()) + ")");
- pw.println(" (HH:MM:SS)");
- pw.print("uptime: "); pw.print(DateUtils.formatElapsedTime(now / 1000));
- pw.println(" (HH:MM:SS)");
+
+ sb.setLength(0);
+ pw.print("uptime: "); pw.print(formatDurationHMS(sb, now));
+ pw.println();
pw.print("time spent syncing: ");
- pw.print(DateUtils.formatElapsedTime(
- mSyncHandler.mSyncTimeTracker.timeSpentSyncing() / 1000));
- pw.print(" (HH:MM:SS), sync ");
+
+ sb.setLength(0);
+ pw.print(formatDurationHMS(sb,
+ mSyncHandler.mSyncTimeTracker.timeSpentSyncing()));
+ pw.print(", sync ");
pw.print(mSyncHandler.mSyncTimeTracker.mLastWasSyncing ? "" : "not ");
pw.println("in progress");
@@ -1842,17 +1964,24 @@ public class SyncManager {
pw.println("Active Syncs: " + mActiveSyncContexts.size());
final PackageManager pm = mContext.getPackageManager();
for (SyncManager.ActiveSyncContext activeSyncContext : mActiveSyncContexts) {
- final long durationInSeconds = (now - activeSyncContext.mStartTime) / 1000;
+ final long durationInSeconds = (now - activeSyncContext.mStartTime);
pw.print(" ");
- pw.print(DateUtils.formatElapsedTime(durationInSeconds));
+ sb.setLength(0);
+ pw.print(formatDurationHMS(sb, durationInSeconds));
pw.print(" - ");
pw.print(activeSyncContext.mSyncOperation.dump(pm, false));
pw.println();
}
+ pw.println();
+
+ dumpPendingSyncs(pw);
+ dumpPeriodicSyncs(pw);
// Join the installed sync adapter with the accounts list and emit for everything.
- pw.println();
pw.println("Sync Status");
+
+ final ArrayList<Pair<EndPoint, SyncStatusInfo>> statuses = new ArrayList<>();
+
for (AccountAndUser account : accounts) {
pw.printf("Account %s u%d %s\n",
account.account.name, account.userId, account.account.type);
@@ -1872,7 +2001,7 @@ public class SyncManager {
"Tot", // 9
"Time", // 10
"Last Sync", // 11
- "Etc" // 12
+ "Backoff" // 12
);
final List<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> sorted =
@@ -1899,11 +2028,14 @@ public class SyncManager {
account.userId));
SyncStorageEngine.AuthorityInfo settings = syncAuthoritySyncStatus.first;
SyncStatusInfo status = syncAuthoritySyncStatus.second;
+ statuses.add(Pair.create(settings.target, status));
String authority = settings.target.provider;
if (authority.length() > 50) {
authority = authority.substring(authority.length() - 50);
}
table.set(row, 0, authority, settings.syncable, settings.enabled);
+
+ sb.setLength(0);
table.set(row, 4,
status.numSourceLocal,
status.numSourcePoll,
@@ -1911,7 +2043,7 @@ public class SyncManager {
status.numSourceServer,
status.numSourceUser,
status.numSyncs,
- DateUtils.formatElapsedTime(status.totalElapsedTime / 1000));
+ formatDurationHMS(sb, status.totalElapsedTime));
int row1 = row;
if (settings.delayUntil > now) {
@@ -1938,6 +2070,34 @@ public class SyncManager {
}
table.writeTo(pw);
}
+
+ dumpSyncHistory(pw);
+
+ pw.println();
+ pw.println("Per Adapter History");
+
+ for (int i = 0; i < statuses.size(); i++) {
+ final Pair<EndPoint, SyncStatusInfo> event = statuses.get(i);
+
+ pw.print(" ");
+ pw.print(event.first.account.name);
+ pw.print('/');
+ pw.print(event.first.account.type);
+ pw.print(" u");
+ pw.print(event.first.userId);
+ pw.print(" [");
+ pw.print(event.first.provider);
+ pw.print("]");
+ pw.println();
+
+ for (int j = 0; j < event.second.getEventCount(); j++) {
+ pw.print(" ");
+ pw.print(formatTime(event.second.getEventTime(j)));
+ pw.print(' ');
+ pw.print(event.second.getEvent(j));
+ pw.println();
+ }
+ }
}
private void dumpTimeSec(PrintWriter pw, long time) {
@@ -2503,7 +2663,7 @@ public class SyncManager {
Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_CANCEL: "
+ endpoint + " bundle: " + extras);
}
- cancelActiveSyncH(endpoint, extras);
+ cancelActiveSyncH(endpoint, extras, "MESSAGE_CANCEL");
break;
case SyncHandler.MESSAGE_SYNC_FINISHED:
@@ -2519,7 +2679,8 @@ public class SyncManager {
Slog.v(TAG, "syncFinished" + payload.activeSyncContext.mSyncOperation);
}
mSyncJobService.callJobFinished(
- payload.activeSyncContext.mSyncOperation.jobId, false);
+ payload.activeSyncContext.mSyncOperation.jobId, false,
+ "sync finished");
runSyncFinishedOrCanceledH(payload.syncResult,
payload.activeSyncContext);
break;
@@ -2563,7 +2724,8 @@ public class SyncManager {
SyncResult syncResult = new SyncResult();
syncResult.stats.numIoExceptions++;
mSyncJobService.callJobFinished(
- currentSyncContext.mSyncOperation.jobId, false);
+ currentSyncContext.mSyncOperation.jobId, false,
+ "service disconnected");
runSyncFinishedOrCanceledH(syncResult, currentSyncContext);
}
break;
@@ -2581,7 +2743,8 @@ public class SyncManager {
"Detected sync making no progress for %s. cancelling.",
monitoredSyncContext));
mSyncJobService.callJobFinished(
- monitoredSyncContext.mSyncOperation.jobId, false);
+ monitoredSyncContext.mSyncOperation.jobId, false,
+ "no network activity");
runSyncFinishedOrCanceledH(
null /* cancel => no result */, monitoredSyncContext);
} else {
@@ -2613,8 +2776,10 @@ public class SyncManager {
* delay. This is equivalent to a failure. If this is a periodic sync, a delayed one-off
* sync will be scheduled.
*/
- private void deferSyncH(SyncOperation op, long delay) {
- mSyncJobService.callJobFinished(op.jobId, false);
+ private void deferSyncH(SyncOperation op, long delay, String why) {
+ mLogger.log("deferSyncH() ", (op.isPeriodic ? "periodic " : ""),
+ "sync. op=", op, " delay=", delay, " why=", why);
+ mSyncJobService.callJobFinished(op.jobId, false, why);
if (op.isPeriodic) {
scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
} else {
@@ -2638,10 +2803,10 @@ public class SyncManager {
/**
* Cancel an active sync and reschedule it on the JobScheduler with some delay.
*/
- private void deferActiveSyncH(ActiveSyncContext asc) {
+ private void deferActiveSyncH(ActiveSyncContext asc, String why) {
SyncOperation op = asc.mSyncOperation;
runSyncFinishedOrCanceledH(null, asc);
- deferSyncH(op, SYNC_DELAY_ON_CONFLICT);
+ deferSyncH(op, SYNC_DELAY_ON_CONFLICT, why);
}
private void startSyncH(SyncOperation op) {
@@ -2649,7 +2814,7 @@ public class SyncManager {
if (isLoggable) Slog.v(TAG, op.toString());
if (mStorageIsLow) {
- deferSyncH(op, SYNC_DELAY_ON_LOW_STORAGE);
+ deferSyncH(op, SYNC_DELAY_ON_LOW_STORAGE, "storage low");
return;
}
@@ -2659,7 +2824,8 @@ public class SyncManager {
List<SyncOperation> ops = getAllPendingSyncs();
for (SyncOperation syncOperation: ops) {
if (syncOperation.sourcePeriodicId == op.jobId) {
- mSyncJobService.callJobFinished(op.jobId, false);
+ mSyncJobService.callJobFinished(op.jobId, false,
+ "periodic sync, pending");
return;
}
}
@@ -2667,13 +2833,14 @@ public class SyncManager {
// executing according to some backoff criteria.
for (ActiveSyncContext asc: mActiveSyncContexts) {
if (asc.mSyncOperation.sourcePeriodicId == op.jobId) {
- mSyncJobService.callJobFinished(op.jobId, false);
+ mSyncJobService.callJobFinished(op.jobId, false,
+ "periodic sync, already running");
return;
}
}
// Check for adapter delays.
if (isAdapterDelayed(op.target)) {
- deferSyncH(op, 0 /* No minimum delay */);
+ deferSyncH(op, 0 /* No minimum delay */, "backing off");
return;
}
}
@@ -2687,13 +2854,13 @@ public class SyncManager {
if (isLoggable) {
Slog.v(TAG, "Rescheduling sync due to conflict " + op.toString());
}
- deferSyncH(op, SYNC_DELAY_ON_CONFLICT);
+ deferSyncH(op, SYNC_DELAY_ON_CONFLICT, "delay on conflict");
return;
} else {
if (isLoggable) {
Slog.v(TAG, "Pushing back running sync due to a higher priority sync");
}
- deferActiveSyncH(asc);
+ deferActiveSyncH(asc, "preempted");
break;
}
}
@@ -2703,12 +2870,13 @@ public class SyncManager {
switch (syncOpState) {
case SYNC_OP_STATE_INVALID_NO_ACCOUNT_ACCESS:
case SYNC_OP_STATE_INVALID: {
- mSyncJobService.callJobFinished(op.jobId, false);
+ mSyncJobService.callJobFinished(op.jobId, false,
+ "invalid op state: " + syncOpState);
} return;
}
if (!dispatchSyncOperation(op)) {
- mSyncJobService.callJobFinished(op.jobId, false);
+ mSyncJobService.callJobFinished(op.jobId, false, "dispatchSyncOperation() failed");
}
setAuthorityPendingState(op.target);
@@ -2878,7 +3046,8 @@ public class SyncManager {
if (op.sourcePeriodicId == syncOperation.jobId || op.jobId == syncOperation.jobId) {
ActiveSyncContext asc = findActiveSyncContextH(syncOperation.jobId);
if (asc != null) {
- mSyncJobService.callJobFinished(syncOperation.jobId, false);
+ mSyncJobService.callJobFinished(syncOperation.jobId, false,
+ "removePeriodicSyncInternalH");
runSyncFinishedOrCanceledH(null, asc);
}
getJobScheduler().cancel(op.jobId);
@@ -2990,6 +3159,8 @@ public class SyncManager {
final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, info.userId);
if (syncAdapterInfo == null) {
+ mLogger.log("dispatchSyncOperation() failed: no sync adapter info for ",
+ syncAdapterType);
Log.d(TAG, "can't find a sync adapter for " + syncAdapterType
+ ", removing settings for it");
mSyncStorageEngine.removeAuthority(info);
@@ -3010,6 +3181,8 @@ public class SyncManager {
postMonitorSyncProgressMessage(activeSyncContext);
if (!activeSyncContext.bindToSyncAdapter(targetComponent, info.userId)) {
+ mLogger.log("dispatchSyncOperation() failed: bind failed. target: ",
+ targetComponent);
Slog.e(TAG, "Bind attempt failed - target: " + targetComponent);
closeActiveSyncContext(activeSyncContext);
return false;
@@ -3025,16 +3198,25 @@ public class SyncManager {
activeSyncContext.mIsLinkedToDeath = true;
syncAdapter.linkToDeath(activeSyncContext, 0);
+ mLogger.log("Sync start: account=" + syncOperation.target.account,
+ " authority=", syncOperation.target.provider,
+ " reason=", SyncOperation.reasonToString(null, syncOperation.reason),
+ " extras=", SyncOperation.extrasToString(syncOperation.extras));
+
activeSyncContext.mSyncAdapter = ISyncAdapter.Stub.asInterface(syncAdapter);
activeSyncContext.mSyncAdapter
.startSync(activeSyncContext, syncOperation.target.provider,
syncOperation.target.account, syncOperation.extras);
+
+ mLogger.log("Sync finish");
} catch (RemoteException remoteExc) {
+ mLogger.log("Sync failed with RemoteException: ", remoteExc.toString());
Log.d(TAG, "maybeStartNextSync: caught a RemoteException, rescheduling", remoteExc);
closeActiveSyncContext(activeSyncContext);
increaseBackoffSetting(syncOperation.target);
scheduleSyncOperationH(syncOperation);
} catch (RuntimeException exc) {
+ mLogger.log("Sync failed with RuntimeException: ", exc.toString());
closeActiveSyncContext(activeSyncContext);
Slog.e(TAG, "Caught RuntimeException while starting the sync " + syncOperation, exc);
}
@@ -3045,7 +3227,8 @@ public class SyncManager {
* @param info Can have null fields to indicate all the active syncs for that field.
* @param extras Can be null to indicate <strong>all</strong> syncs for the given endpoint.
*/
- private void cancelActiveSyncH(SyncStorageEngine.EndPoint info, Bundle extras) {
+ private void cancelActiveSyncH(SyncStorageEngine.EndPoint info, Bundle extras,
+ String why) {
ArrayList<ActiveSyncContext> activeSyncs =
new ArrayList<ActiveSyncContext>(mActiveSyncContexts);
for (ActiveSyncContext activeSyncContext : activeSyncs) {
@@ -3061,7 +3244,8 @@ public class SyncManager {
false /* no config settings */)) {
continue;
}
- mSyncJobService.callJobFinished(activeSyncContext.mSyncOperation.jobId, false);
+ mSyncJobService.callJobFinished(activeSyncContext.mSyncOperation.jobId, false,
+ why);
runSyncFinishedOrCanceledH(null /* cancel => no result */, activeSyncContext);
}
}
@@ -3109,6 +3293,7 @@ public class SyncManager {
// potentially rescheduling all pending jobs to respect new backoff values.
getJobScheduler().cancel(syncOperation.jobId);
}
+ mLogger.log("runSyncFinishedOrCanceledH() op=", syncOperation, " result=", syncResult);
if (syncResult != null) {
if (isLoggable) {
@@ -3121,7 +3306,7 @@ public class SyncManager {
// TODO: set these correctly when the SyncResult is extended to include it
downstreamActivity = 0;
upstreamActivity = 0;
- clearBackoffSetting(syncOperation.target);
+ clearBackoffSetting(syncOperation.target, "sync success");
// If the operation completes successfully and it was scheduled due to
// a periodic operation failing, we reschedule the periodic operation to
@@ -3403,7 +3588,7 @@ public class SyncManager {
}
static class PrintTable {
- private ArrayList<Object[]> mTable = Lists.newArrayList();
+ private ArrayList<String[]> mTable = Lists.newArrayList();
private final int mCols;
PrintTable(int cols) {
@@ -3416,13 +3601,17 @@ public class SyncManager {
" columns. can't set " + values.length + " at column " + col);
}
for (int i = mTable.size(); i <= row; i++) {
- final Object[] list = new Object[mCols];
+ final String[] list = new String[mCols];
mTable.add(list);
for (int j = 0; j < mCols; j++) {
list[j] = "";
}
}
- System.arraycopy(values, 0, mTable.get(row), col, values.length);
+ final String[] rowArray = mTable.get(row);
+ for (int i = 0; i < values.length; i++) {
+ final Object value = values[i];
+ rowArray[col + i] = (value == null) ? "" : value.toString();
+ }
}
void writeTo(PrintWriter out) {
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index c371f9705285..7d2cc0035847 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -18,10 +18,11 @@ package com.android.server.content;
import android.accounts.Account;
import android.app.job.JobInfo;
-import android.content.pm.PackageManager;
import android.content.ContentResolver;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.PersistableBundle;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Slog;
@@ -236,6 +237,9 @@ public class SyncOperation {
* contain a valid sync operation.
*/
static SyncOperation maybeCreateFromJobExtras(PersistableBundle jobExtras) {
+ if (jobExtras == null) {
+ return null;
+ }
String accountName, accountType;
String provider;
int userId, owningUid;
@@ -350,37 +354,46 @@ public class SyncOperation {
return dump(null, true);
}
- String dump(PackageManager pm, boolean useOneLine) {
+ String dump(PackageManager pm, boolean shorter) {
StringBuilder sb = new StringBuilder();
- sb.append("JobId: ").append(jobId)
- .append(", ")
+ sb.append("JobId=").append(jobId)
+ .append(" ")
.append(target.account.name)
- .append(" u")
- .append(target.userId).append(" (")
+ .append("/")
.append(target.account.type)
- .append(")")
- .append(", ")
+ .append(" u")
+ .append(target.userId)
+ .append(" [")
.append(target.provider)
- .append(", ");
+ .append("] ");
sb.append(SyncStorageEngine.SOURCES[syncSource]);
+ if (expectedRuntime != 0) {
+ sb.append(" ExpectedIn=");
+ SyncManager.formatDurationHMS(sb,
+ (expectedRuntime - SystemClock.elapsedRealtime()));
+ }
if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
- sb.append(", EXPEDITED");
+ sb.append(" EXPEDITED");
}
- sb.append(", reason: ");
+ sb.append(" Reason=");
sb.append(reasonToString(pm, reason));
if (isPeriodic) {
- sb.append(", period: " + periodMillis).append(", flexMillis: " + flexMillis);
+ sb.append(" (period=");
+ SyncManager.formatDurationHMS(sb, periodMillis);
+ sb.append(" flex=");
+ SyncManager.formatDurationHMS(sb, flexMillis);
+ sb.append(")");
}
- if (!useOneLine) {
- sb.append("\n ");
- sb.append("owningUid=");
+ if (!shorter) {
+ sb.append(" Owner={");
UserHandle.formatUid(sb, owningUid);
- sb.append(" owningPackage=");
+ sb.append(" ");
sb.append(owningPackage);
- }
- if (!useOneLine && !extras.keySet().isEmpty()) {
- sb.append("\n ");
- extrasToStringBuilder(extras, sb);
+ sb.append("}");
+ if (!extras.keySet().isEmpty()) {
+ sb.append(" ");
+ extrasToStringBuilder(extras, sb);
+ }
}
return sb.toString();
}
@@ -434,7 +447,11 @@ public class SyncOperation {
return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
}
- private static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
+ static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
+ if (bundle == null) {
+ sb.append("null");
+ return;
+ }
sb.append("[");
for (String key : bundle.keySet()) {
sb.append(key).append("=").append(bundle.get(key)).append(" ");
@@ -442,6 +459,12 @@ public class SyncOperation {
sb.append("]");
}
+ static String extrasToString(Bundle bundle) {
+ final StringBuilder sb = new StringBuilder();
+ extrasToStringBuilder(bundle, sb);
+ return sb.toString();
+ }
+
String wakeLockName() {
if (wakeLockName != null) {
return wakeLockName;
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index f804fa1cff3e..7b277c06328e 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -1183,6 +1183,16 @@ public class SyncStorageEngine extends Handler {
ds.failureCount++;
ds.failureTime += elapsedTime;
}
+ final StringBuilder event = new StringBuilder();
+ event.append("" + resultMessage + " Source=" + SyncStorageEngine.SOURCES[item.source]
+ + " Elapsed=");
+ SyncManager.formatDurationHMS(event, elapsedTime);
+ event.append(" Reason=");
+ event.append(SyncOperation.reasonToString(null, item.reason));
+ event.append(" Extras=");
+ SyncOperation.extrasToStringBuilder(item.extras, event);
+
+ status.addEvent(event.toString());
if (writeStatusNow) {
writeStatusLocked();
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 8129f450a85b..ab3aff99937d 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1221,6 +1221,18 @@ public final class DisplayManagerService extends SystemService {
}
}
+ @VisibleForTesting
+ DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) {
+ synchronized (mSyncRoot) {
+ LogicalDisplay display = mLogicalDisplays.get(displayId);
+ if (display != null) {
+ DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked();
+ return displayDevice.getDisplayDeviceInfoLocked();
+ }
+ return null;
+ }
+ }
+
private final class DisplayManagerHandler extends Handler {
public DisplayManagerHandler(Looper looper) {
super(looper, null, true /*async*/);
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 9d3021af1ac2..d6ab88813f4d 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -23,6 +23,7 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESE
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
import android.content.Context;
import android.hardware.display.IVirtualDisplayCallback;
@@ -359,6 +360,10 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
if ((mFlags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
mInfo.flags |= DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
}
+ if ((mFlags & VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT) != 0) {
+ mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
+ }
+
mInfo.type = Display.TYPE_VIRTUAL;
mInfo.touch = ((mFlags & VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH) == 0) ?
DisplayDeviceInfo.TOUCH_NONE : DisplayDeviceInfo.TOUCH_VIRTUAL;
diff --git a/services/core/java/com/android/server/job/JobPackageTracker.java b/services/core/java/com/android/server/job/JobPackageTracker.java
index 8ad1beace643..ba922959213c 100644
--- a/services/core/java/com/android/server/job/JobPackageTracker.java
+++ b/services/core/java/com/android/server/job/JobPackageTracker.java
@@ -39,19 +39,23 @@ public final class JobPackageTracker {
public static final int EVENT_NULL = 0;
public static final int EVENT_START_JOB = 1;
public static final int EVENT_STOP_JOB = 2;
+ public static final int EVENT_START_PERIODIC_JOB = 3;
+ public static final int EVENT_STOP_PERIODIC_JOB = 4;
private final RingBufferIndices mEventIndices = new RingBufferIndices(EVENT_BUFFER_SIZE);
private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
private final int[] mEventUids = new int[EVENT_BUFFER_SIZE];
private final String[] mEventTags = new String[EVENT_BUFFER_SIZE];
+ private final int[] mEventJobIds = new int[EVENT_BUFFER_SIZE];
- public void addEvent(int cmd, int uid, String tag) {
+ public void addEvent(int cmd, int uid, String tag, int jobId) {
int index = mEventIndices.add();
mEventCmds[index] = cmd;
mEventTimes[index] = SystemClock.elapsedRealtime();
mEventUids[index] = uid;
mEventTags[index] = tag;
+ mEventJobIds[index] = jobId;
}
DataSet mCurDataSet = new DataSet();
@@ -365,7 +369,8 @@ public final class JobPackageTracker {
} else {
mCurDataSet.incActive(job.getSourceUid(), job.getSourcePackageName(), now);
}
- addEvent(EVENT_START_JOB, job.getSourceUid(), job.getBatteryName());
+ addEvent(job.getJob().isPeriodic() ? EVENT_START_PERIODIC_JOB : EVENT_START_JOB,
+ job.getSourceUid(), job.getBatteryName(), job.getJobId());
}
public void noteInactive(JobStatus job) {
@@ -376,7 +381,8 @@ public final class JobPackageTracker {
mCurDataSet.decActive(job.getSourceUid(), job.getSourcePackageName(), now);
}
rebatchIfNeeded(now);
- addEvent(EVENT_STOP_JOB, job.getSourceUid(), job.getBatteryName());
+ addEvent(job.getJob().isPeriodic() ? EVENT_STOP_JOB : EVENT_STOP_PERIODIC_JOB,
+ job.getSourceUid(), job.getBatteryName(), job.getJobId());
}
public void noteConcurrency(int totalActive, int fgActive) {
@@ -448,16 +454,20 @@ public final class JobPackageTracker {
}
final String label;
switch (mEventCmds[index]) {
- case EVENT_START_JOB: label = "START"; break;
- case EVENT_STOP_JOB: label = " STOP"; break;
- default: label = " ??"; break;
+ case EVENT_START_JOB: label = " START"; break;
+ case EVENT_STOP_JOB: label = " STOP"; break;
+ case EVENT_START_PERIODIC_JOB: label = "START-P"; break;
+ case EVENT_STOP_PERIODIC_JOB: label = " STOP-P"; break;
+ default: label = " ??"; break;
}
pw.print(prefix);
TimeUtils.formatDuration(mEventTimes[index]-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
pw.print(" ");
pw.print(label);
- pw.print(": ");
+ pw.print(": #");
UserHandle.formatUid(pw, uid);
+ pw.print("/");
+ pw.print(mEventJobIds[index]);
pw.print(" ");
pw.println(mEventTags[index]);
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index b8fe88439c2d..98c65fd487ca 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1122,7 +1122,8 @@ public final class JobSchedulerService extends com.android.server.SystemService
delayMillis =
Math.min(delayMillis, JobInfo.MAX_BACKOFF_DELAY_MILLIS);
JobStatus newJob = new JobStatus(failureToReschedule, elapsedNowMillis + delayMillis,
- JobStatus.NO_LATEST_RUNTIME, backoffAttempts);
+ JobStatus.NO_LATEST_RUNTIME, backoffAttempts,
+ failureToReschedule.getLastSuccessfulRunTime(), System.currentTimeMillis());
for (int ic=0; ic<mControllers.size(); ic++) {
StateController controller = mControllers.get(ic);
controller.rescheduleForFailureLocked(newJob, failureToReschedule);
@@ -1160,7 +1161,9 @@ public final class JobSchedulerService extends com.android.server.SystemService
newEarliestRunTimeElapsed/1000 + ", " + newLatestRuntimeElapsed/1000 + "]s");
}
return new JobStatus(periodicToReschedule, newEarliestRunTimeElapsed,
- newLatestRuntimeElapsed, 0 /* backoffAttempt */);
+ newLatestRuntimeElapsed, 0 /* backoffAttempt */,
+ System.currentTimeMillis() /* lastSuccessfulRunTime */,
+ periodicToReschedule.getLastFailedRunTime());
}
// JobCompletedListener implementations.
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 5d3f6f7b804b..107475f36c73 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -438,7 +438,21 @@ public final class JobServiceContext implements ServiceConnection {
switch (message.what) {
case MSG_TIMEOUT:
synchronized (mLock) {
- handleOpTimeoutLocked();
+ if (message.obj == mRunningCallback) {
+ handleOpTimeoutLocked();
+ } else {
+ JobCallback jc = (JobCallback)message.obj;
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("Ignoring timeout of no longer active job");
+ if (jc.mStoppedReason != null) {
+ sb.append(", stopped ");
+ TimeUtils.formatDuration(SystemClock.elapsedRealtime()
+ - jc.mStoppedTime, sb);
+ sb.append(" because: ");
+ sb.append(jc.mStoppedReason);
+ }
+ Slog.w(TAG, sb.toString());
+ }
}
break;
default:
@@ -621,7 +635,7 @@ public final class JobServiceContext implements ServiceConnection {
private void handleOpTimeoutLocked() {
switch (mVerb) {
case VERB_BINDING:
- Slog.e(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() +
+ Slog.w(TAG, "Time-out while trying to bind " + mRunningJob.toShortString() +
", dropping.");
closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while binding");
break;
@@ -629,26 +643,28 @@ public final class JobServiceContext implements ServiceConnection {
// Client unresponsive - wedged or failed to respond in time. We don't really
// know what happened so let's log it and notify the JobScheduler
// FINISHED/NO-RETRY.
- Slog.e(TAG, "No response from client for onStartJob '" +
- mRunningJob.toShortString());
+ Slog.w(TAG, "No response from client for onStartJob " +
+ mRunningJob != null ? mRunningJob.toShortString() : "<null>");
closeAndCleanupJobLocked(false /* needsReschedule */, "timed out while starting");
break;
case VERB_STOPPING:
// At least we got somewhere, so fail but ask the JobScheduler to reschedule.
- Slog.e(TAG, "No response from client for onStopJob, '" +
- mRunningJob.toShortString());
+ Slog.w(TAG, "No response from client for onStopJob " +
+ mRunningJob != null ? mRunningJob.toShortString() : "<null>");
closeAndCleanupJobLocked(true /* needsReschedule */, "timed out while stopping");
break;
case VERB_EXECUTING:
// Not an error - client ran out of time.
- Slog.i(TAG, "Client timed out while executing (no jobFinished received)." +
- " sending onStop. " + mRunningJob.toShortString());
+ Slog.i(TAG, "Client timed out while executing (no jobFinished received), " +
+ "sending onStop: " +
+ mRunningJob != null ? mRunningJob.toShortString() : "<null>");
mParams.setStopReason(JobParameters.REASON_TIMEOUT);
sendStopMessageLocked("timeout while executing");
break;
default:
Slog.e(TAG, "Handling timeout for an invalid job state: " +
- mRunningJob.toShortString() + ", dropping.");
+ mRunningJob != null ? mRunningJob.toShortString() : "<null>"
+ + ", dropping.");
closeAndCleanupJobLocked(false /* needsReschedule */, "invalid timeout");
}
}
@@ -749,7 +765,7 @@ public final class JobServiceContext implements ServiceConnection {
mRunningJob.getServiceComponent().getShortClassName() + "' jId: " +
mParams.getJobId() + ", in " + (timeoutMillis / 1000) + " s");
}
- Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT);
+ Message m = mCallbackHandler.obtainMessage(MSG_TIMEOUT, mRunningCallback);
mCallbackHandler.sendMessageDelayed(m, timeoutMillis);
mTimeoutElapsed = SystemClock.elapsedRealtime() + timeoutMillis;
}
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index f0cd8a8569e0..84810bebf1f1 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -345,6 +345,11 @@ public final class JobStore {
out.attribute(null, "uid", Integer.toString(jobStatus.getUid()));
out.attribute(null, "priority", String.valueOf(jobStatus.getPriority()));
out.attribute(null, "flags", String.valueOf(jobStatus.getFlags()));
+
+ out.attribute(null, "lastSuccessfulRunTime",
+ String.valueOf(jobStatus.getLastSuccessfulRunTime()));
+ out.attribute(null, "lastFailedRunTime",
+ String.valueOf(jobStatus.getLastFailedRunTime()));
}
private void writeBundleToXml(PersistableBundle extras, XmlSerializer out)
@@ -555,6 +560,8 @@ public final class JobStore {
IOException {
JobInfo.Builder jobBuilder;
int uid, sourceUserId;
+ long lastSuccessfulRunTime;
+ long lastFailedRunTime;
// Read out job identifier attributes and priority.
try {
@@ -572,6 +579,12 @@ public final class JobStore {
}
val = parser.getAttributeValue(null, "sourceUserId");
sourceUserId = val == null ? -1 : Integer.parseInt(val);
+
+ val = parser.getAttributeValue(null, "lastSuccessfulRunTime");
+ lastSuccessfulRunTime = val == null ? 0 : Long.parseLong(val);
+
+ val = parser.getAttributeValue(null, "lastFailedRunTime");
+ lastFailedRunTime = val == null ? 0 : Long.parseLong(val);
} catch (NumberFormatException e) {
Slog.e(TAG, "Error parsing job's required fields, skipping");
return null;
@@ -708,7 +721,8 @@ public final class JobStore {
// And now we're done
JobStatus js = new JobStatus(
jobBuilder.build(), uid, sourcePackageName, sourceUserId, sourceTag,
- elapsedRuntimes.first, elapsedRuntimes.second);
+ elapsedRuntimes.first, elapsedRuntimes.second,
+ lastSuccessfulRunTime, lastFailedRunTime);
return js;
}
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 446b0d67ce95..9658da7a5de0 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -26,6 +26,7 @@ import android.net.Uri;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.text.format.Time;
import android.util.ArraySet;
import android.util.Slog;
import android.util.TimeUtils;
@@ -184,6 +185,17 @@ public final class JobStatus {
public long madeActive;
/**
+ * Last time a job finished successfully for a periodic job, in the currentTimeMillis time,
+ * for dumpsys.
+ */
+ private long mLastSuccessfulRunTime;
+
+ /**
+ * Last time a job finished unsuccessfully, in the currentTimeMillis time, for dumpsys.
+ */
+ private long mLastFailedRunTime;
+
+ /**
* For use only by ContentObserverController: state it is maintaining about content URIs
* being observed.
*/
@@ -196,7 +208,7 @@ public final class JobStatus {
private JobStatus(JobInfo job, int callingUid, String sourcePackageName,
int sourceUserId, String tag, int numFailures, long earliestRunTimeElapsedMillis,
- long latestRunTimeElapsedMillis) {
+ long latestRunTimeElapsedMillis, long lastSuccessfulRunTime, long lastFailedRunTime) {
this.job = job;
this.callingUid = callingUid;
@@ -263,6 +275,9 @@ public final class JobStatus {
requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER;
}
this.requiredConstraints = requiredConstraints;
+
+ mLastSuccessfulRunTime = lastSuccessfulRunTime;
+ mLastFailedRunTime = lastFailedRunTime;
}
/** Copy constructor. */
@@ -270,7 +285,8 @@ public final class JobStatus {
this(jobStatus.getJob(), jobStatus.getUid(),
jobStatus.getSourcePackageName(), jobStatus.getSourceUserId(),
jobStatus.getSourceTag(), jobStatus.getNumFailures(),
- jobStatus.getEarliestRunTime(), jobStatus.getLatestRunTimeElapsed());
+ jobStatus.getEarliestRunTime(), jobStatus.getLatestRunTimeElapsed(),
+ jobStatus.getLastSuccessfulRunTime(), jobStatus.getLastFailedRunTime());
}
/**
@@ -281,18 +297,22 @@ public final class JobStatus {
* We consider a freshly loaded job to no longer be in back-off.
*/
public JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId,
- String sourceTag, long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis) {
+ String sourceTag, long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis,
+ long lastSuccessfulRunTime, long lastFailedRunTime) {
this(job, callingUid, sourcePackageName, sourceUserId, sourceTag, 0,
- earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
+ earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
+ lastSuccessfulRunTime, lastFailedRunTime);
}
/** Create a new job to be rescheduled with the provided parameters. */
public JobStatus(JobStatus rescheduling, long newEarliestRuntimeElapsedMillis,
- long newLatestRuntimeElapsedMillis, int backoffAttempt) {
+ long newLatestRuntimeElapsedMillis, int backoffAttempt,
+ long lastSuccessfulRunTime, long lastFailedRunTime) {
this(rescheduling.job, rescheduling.getUid(),
rescheduling.getSourcePackageName(), rescheduling.getSourceUserId(),
rescheduling.getSourceTag(), backoffAttempt, newEarliestRuntimeElapsedMillis,
- newLatestRuntimeElapsedMillis);
+ newLatestRuntimeElapsedMillis,
+ lastSuccessfulRunTime, lastFailedRunTime);
}
/**
@@ -316,7 +336,8 @@ public final class JobStatus {
elapsedNow + job.getMaxExecutionDelayMillis() : NO_LATEST_RUNTIME;
}
return new JobStatus(job, callingUid, sourcePackageName, sourceUserId, tag, 0,
- earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis);
+ earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
+ 0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */);
}
public void enqueueWorkLocked(IActivityManager am, JobWorkItem work) {
@@ -669,6 +690,14 @@ public final class JobStatus {
trackingControllers |= which;
}
+ public long getLastSuccessfulRunTime() {
+ return mLastSuccessfulRunTime;
+ }
+
+ public long getLastFailedRunTime() {
+ return mLastFailedRunTime;
+ }
+
public boolean shouldDump(int filterUid) {
return filterUid == -1 || UserHandle.getAppId(getUid()) == filterUid
|| UserHandle.getAppId(getSourceUid()) == filterUid;
@@ -1041,5 +1070,17 @@ public final class JobStatus {
if (numFailures != 0) {
pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures);
}
+ final Time t = new Time();
+ final String format = "%Y-%m-%d %H:%M:%S";
+ if (mLastSuccessfulRunTime != 0) {
+ pw.print(prefix); pw.print("Last successful run: ");
+ t.set(mLastSuccessfulRunTime);
+ pw.println(t.format(format));
+ }
+ if (mLastFailedRunTime != 0) {
+ pw.print(prefix); pw.print("Last failed run: ");
+ t.set(mLastFailedRunTime);
+ pw.println(t.format(format));
+ }
}
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 4a45c074f4d1..4511aa9390c6 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -466,6 +466,11 @@ public class GnssLocationProvider implements LocationProviderInterface {
// Always on, notify HAL so it can get data it needs
sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
}
+
+ @Override
+ public void onLost(Network network) {
+ sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
+ }
};
/**
@@ -784,6 +789,18 @@ public class GnssLocationProvider implements LocationProviderInterface {
}
};
mGnssMetrics = new GnssMetrics();
+
+ /*
+ * A cycle of native_init() and native_cleanup() is needed so that callbacks are registered
+ * after bootup even when location is disabled. This will allow Emergency SUPL to work even
+ * when location is disabled before device restart.
+ * */
+ boolean isInitialized = native_init();
+ if(!isInitialized) {
+ Log.d(TAG, "Failed to initialize at bootup");
+ } else {
+ native_cleanup();
+ }
}
/**
@@ -802,11 +819,21 @@ public class GnssLocationProvider implements LocationProviderInterface {
private void handleUpdateNetworkState(Network network) {
// retrieve NetworkInfo for this UID
NetworkInfo info = mConnMgr.getNetworkInfo(network);
- if (info == null) {
- return;
+
+ boolean networkAvailable = false;
+ boolean isConnected = false;
+ int type = ConnectivityManager.TYPE_NONE;
+ boolean isRoaming = false;
+ String apnName = null;
+
+ if (info != null) {
+ networkAvailable = info.isAvailable() && TelephonyManager.getDefault().getDataEnabled();
+ isConnected = info.isConnected();
+ type = info.getType();
+ isRoaming = info.isRoaming();
+ apnName = info.getExtraInfo();
}
- boolean isConnected = info.isConnected();
if (DEBUG) {
String message = String.format(
"UpdateNetworkState, state=%s, connected=%s, info=%s, capabilities=%S",
@@ -818,8 +845,6 @@ public class GnssLocationProvider implements LocationProviderInterface {
}
if (native_is_agps_ril_supported()) {
- boolean dataEnabled = TelephonyManager.getDefault().getDataEnabled();
- boolean networkAvailable = info.isAvailable() && dataEnabled;
String defaultApn = getSelectedApn();
if (defaultApn == null) {
defaultApn = "dummy-apn";
@@ -827,10 +852,10 @@ public class GnssLocationProvider implements LocationProviderInterface {
native_update_network_state(
isConnected,
- info.getType(),
- info.isRoaming(),
+ type,
+ isRoaming,
networkAvailable,
- info.getExtraInfo(),
+ apnName,
defaultApn);
} else if (DEBUG) {
Log.d(TAG, "Skipped network state update because GPS HAL AGPS-RIL is not supported");
@@ -838,7 +863,6 @@ public class GnssLocationProvider implements LocationProviderInterface {
if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
if (isConnected) {
- String apnName = info.getExtraInfo();
if (apnName == null) {
// assign a dummy value in the case of C2K as otherwise we will have a runtime
// exception in the following call to native_agps_data_conn_open
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index fe2c5bd87df4..c1e820c9b787 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -142,6 +142,7 @@ public class LockSettingsService extends ILockSettings.Stub {
private static final int SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT = 1;
// Order of holding lock: mSeparateChallengeLock -> mSpManager -> this
+ // Do not call into ActivityManager while holding mSpManager lock.
private final Object mSeparateChallengeLock = new Object();
private final DeviceProvisionedObserver mDeviceProvisionedObserver =
@@ -1434,16 +1435,14 @@ public class LockSettingsService extends ILockSettings.Stub {
Slog.e(TAG, "FRP credential can only be verified prior to provisioning.");
return VerifyCredentialResponse.ERROR;
}
- synchronized (mSpManager) {
- if (isSyntheticPasswordBasedCredentialLocked(userId)) {
- VerifyCredentialResponse response = spBasedDoVerifyCredentialLocked(credential,
- credentialType, hasChallenge, challenge, userId, progressCallback);
- if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
- mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
- }
- return response;
- }
+ VerifyCredentialResponse response = null;
+ response = spBasedDoVerifyCredential(credential, credentialType, hasChallenge, challenge,
+ userId, progressCallback);
+ // The user employs synthetic password based credential.
+ if (response != null) {
+ return response;
}
+
final CredentialHash storedHash;
if (userId == USER_FRP) {
PersistentData data = mStorage.readPersistentDataBlock();
@@ -1472,7 +1471,7 @@ public class LockSettingsService extends ILockSettings.Stub {
credentialToVerify = credential;
}
- VerifyCredentialResponse response = verifyCredential(userId, storedHash, credentialToVerify,
+ response = verifyCredential(userId, storedHash, credentialToVerify,
hasChallenge, challenge, progressCallback);
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
@@ -1995,33 +1994,46 @@ public class LockSettingsService extends ILockSettings.Stub {
setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
}
- private VerifyCredentialResponse spBasedDoVerifyCredentialLocked(String userCredential, int
+ private VerifyCredentialResponse spBasedDoVerifyCredential(String userCredential, int
credentialType, boolean hasChallenge, long challenge, int userId,
ICheckCredentialProgressCallback progressCallback) throws RemoteException {
- if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredentialLocked: user=" + userId);
+ if (DEBUG) Slog.d(TAG, "spBasedDoVerifyCredential: user=" + userId);
if (credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
userCredential = null;
}
- if (userId == USER_FRP) {
- return mSpManager.verifyFrpCredential(getGateKeeperService(),
- userCredential, credentialType, progressCallback);
- }
- long handle = getSyntheticPasswordHandleLocked(userId);
- AuthenticationResult authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
- getGateKeeperService(), handle, userCredential, userId);
+ final AuthenticationResult authResult;
+ VerifyCredentialResponse response;
+ synchronized (mSpManager) {
+ if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
+ return null;
+ }
+ if (userId == USER_FRP) {
+ return mSpManager.verifyFrpCredential(getGateKeeperService(),
+ userCredential, credentialType, progressCallback);
+ }
- VerifyCredentialResponse response = authResult.gkResponse;
- if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+ long handle = getSyntheticPasswordHandleLocked(userId);
+ authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
+ getGateKeeperService(), handle, userCredential, userId);
+
+ response = authResult.gkResponse;
// credential has matched
- // perform verifyChallenge with synthetic password which generates the real auth
- // token for the current user
- response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken,
- challenge, userId);
- if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
- Slog.wtf(TAG, "verifyChallenge with SP failed.");
- return VerifyCredentialResponse.ERROR;
+ if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
+ // perform verifyChallenge with synthetic password which generates the real GK auth
+ // token and response for the current user
+ response = mSpManager.verifyChallenge(getGateKeeperService(), authResult.authToken,
+ challenge, userId);
+ if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
+ // This shouldn't really happen: the unwrapping of SP succeeds, but SP doesn't
+ // match the recorded GK password handle.
+ Slog.wtf(TAG, "verifyChallenge with SP failed.");
+ return VerifyCredentialResponse.ERROR;
+ }
}
+ }
+
+ if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
if (progressCallback != null) {
progressCallback.onCredentialVerified();
}
@@ -2032,12 +2044,14 @@ public class LockSettingsService extends ILockSettings.Stub {
Slog.i(TAG, "Unlocking user " + userId + " with secret only, length " + secret.length);
unlockUser(userId, null, secret);
+ activateEscrowTokens(authResult.authToken, userId);
+
if (isManagedProfileWithSeparatedLock(userId)) {
TrustManager trustManager =
(TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
trustManager.setDeviceLockedForUser(userId, false);
}
- activateEscrowTokens(authResult.authToken, userId);
+ mStrongAuth.reportSuccessfulStrongAuthUnlock(userId);
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
if (response.getTimeout() > 0) {
requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
@@ -2184,8 +2198,8 @@ public class LockSettingsService extends ILockSettings.Stub {
private void activateEscrowTokens(AuthenticationToken auth, int userId) throws RemoteException {
if (DEBUG) Slog.d(TAG, "activateEscrowTokens: user=" + userId);
- disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
synchronized (mSpManager) {
+ disableEscrowTokenOnNonManagedDevicesIfNeeded(userId);
for (long handle : mSpManager.getPendingTokensForUser(userId)) {
Slog.i(TAG, String.format("activateEscrowTokens: %x %d ", handle, userId));
mSpManager.activateTokenBasedSyntheticPassword(handle, auth, userId);
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index b3c6ff657867..d7b36aaa8008 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -525,12 +525,11 @@ public class RankingHelper implements RankingConfig {
if (r == null) {
throw new IllegalArgumentException("Invalid package");
}
- LogMaker lm = new LogMaker(MetricsProto.MetricsEvent.ACTION_NOTIFICATION_CHANNEL_GROUP)
- .setType(MetricsProto.MetricsEvent.TYPE_UPDATE)
- .addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CHANNEL_GROUP_ID,
- group.getId())
- .setPackageName(pkg);
- MetricsLogger.action(lm);
+ final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
+ if (!group.equals(oldGroup)) {
+ // will log for new entries as well as name changes
+ MetricsLogger.action(getChannelGroupLog(group.getId(), pkg));
+ }
r.groups.put(group.getId(), group);
updateConfig();
}
@@ -558,13 +557,16 @@ public class RankingHelper implements RankingConfig {
if (existing != null && fromTargetApp) {
if (existing.isDeleted()) {
existing.setDeleted(false);
+
+ // log a resurrected channel as if it's new again
+ MetricsLogger.action(getChannelLog(channel, pkg).setType(
+ MetricsProto.MetricsEvent.TYPE_OPEN));
}
existing.setName(channel.getName().toString());
existing.setDescription(channel.getDescription());
existing.setBlockableSystem(channel.isBlockableSystem());
- MetricsLogger.action(getChannelLog(channel, pkg));
updateConfig();
return;
}
@@ -622,7 +624,10 @@ public class RankingHelper implements RankingConfig {
r.showBadge = updatedChannel.canShowBadge();
}
- MetricsLogger.action(getChannelLog(updatedChannel, pkg));
+ if (!channel.equals(updatedChannel)) {
+ // only log if there are real changes
+ MetricsLogger.action(getChannelLog(updatedChannel, pkg));
+ }
updateConfig();
}
@@ -1141,6 +1146,14 @@ public class RankingHelper implements RankingConfig {
channel.getImportance());
}
+ private LogMaker getChannelGroupLog(String groupId, String pkg) {
+ return new LogMaker(MetricsProto.MetricsEvent.ACTION_NOTIFICATION_CHANNEL_GROUP)
+ .setType(MetricsProto.MetricsEvent.TYPE_UPDATE)
+ .addTaggedData(MetricsProto.MetricsEvent.FIELD_NOTIFICATION_CHANNEL_GROUP_ID,
+ groupId)
+ .setPackageName(pkg);
+ }
+
public void updateBadgingEnabled() {
if (mBadgingEnabled == null) {
mBadgingEnabled = new SparseBooleanArray();
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 75190f3e3e89..15e32ff6469e 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -762,7 +762,9 @@ public class ZenModeHelper {
for (int usage : AudioAttributes.SDK_USAGES) {
final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
- if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
+ if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
+ applyRestrictions(false /*mute*/, usage);
+ } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
applyRestrictions(muteNotifications || muteEverything, usage);
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
applyRestrictions(muteCalls || muteEverything, usage);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 682d6667cd87..1242daa48bee 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -58,6 +58,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE
import static android.content.pm.PackageManager.INSTALL_FORWARD_LOCK;
import static android.content.pm.PackageManager.INSTALL_INTERNAL;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
@@ -5060,9 +5061,6 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public String getPermissionControllerPackageName() {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
- throw new SecurityException("Instant applications don't have access to this method");
- }
synchronized (mPackages) {
return mRequiredInstallerPackage;
}
@@ -7179,16 +7177,13 @@ public class PackageManagerService extends IPackageManager.Stub
*/
private List<ResolveInfo> applyPostResolutionFilter(List<ResolveInfo> resolveInfos,
String ephemeralPkgName) {
- // TODO: When adding on-demand split support for non-instant apps, remove this check
- // and always apply post filtering
- if (ephemeralPkgName == null) {
- return resolveInfos;
- }
for (int i = resolveInfos.size() - 1; i >= 0; i--) {
final ResolveInfo info = resolveInfos.get(i);
final boolean isEphemeralApp = info.activityInfo.applicationInfo.isInstantApp();
+ // TODO: When adding on-demand split support for non-instant apps, remove this check
+ // and always apply post filtering
// allow activities that are defined in the provided package
- if (isEphemeralApp && ephemeralPkgName.equals(info.activityInfo.packageName)) {
+ if (isEphemeralApp) {
if (info.activityInfo.splitName != null
&& !ArrayUtils.contains(info.activityInfo.applicationInfo.splitNames,
info.activityInfo.splitName)) {
@@ -7210,7 +7205,14 @@ public class PackageManagerService extends IPackageManager.Stub
// load resources from the correct package
installerInfo.resolvePackageName = info.getComponentInfo().packageName;
resolveInfos.set(i, installerInfo);
+ continue;
}
+ }
+ // caller is a full app, don't need to apply any other filtering
+ if (ephemeralPkgName == null) {
+ continue;
+ } else if (ephemeralPkgName.equals(info.activityInfo.packageName)) {
+ // caller is same app; don't need to apply any other filtering
continue;
}
// allow activities that have been explicitly exposed to ephemeral apps
@@ -10491,8 +10493,9 @@ public class PackageManagerService extends IPackageManager.Stub
if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
if ((scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
- derivePackageAbi(
- pkg, scanFile, cpuAbiOverride, true /*extractLibs*/, mAppLib32InstallDir);
+ final boolean extractNativeLibs = !pkg.isLibrary();
+ derivePackageAbi(pkg, scanFile, cpuAbiOverride, extractNativeLibs,
+ mAppLib32InstallDir);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
// Some system apps still use directory structure for native libraries
@@ -11520,6 +11523,12 @@ public class PackageManagerService extends IPackageManager.Stub
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
+ // Shared library native code should be in the APK zip aligned
+ if (abi32 >= 0 && pkg.isLibrary() && extractLibs) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Shared library native lib extraction not supported");
+ }
+
maybeThrowExceptionForMultiArchCopy(
"Error unpackaging 32 bit native libs for multiarch app.", abi32);
@@ -11540,6 +11549,11 @@ public class PackageManagerService extends IPackageManager.Stub
"Error unpackaging 64 bit native libs for multiarch app.", abi64);
if (abi64 >= 0) {
+ // Shared library native libs should be in the APK zip aligned
+ if (extractLibs && pkg.isLibrary()) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Shared library native lib extraction not supported");
+ }
pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
}
@@ -11556,7 +11570,6 @@ public class PackageManagerService extends IPackageManager.Stub
pkg.applicationInfo.primaryCpuAbi = abi;
}
}
-
} else {
String[] abiList = (cpuAbiOverride != null) ?
new String[] { cpuAbiOverride } : Build.SUPPORTED_ABIS;
@@ -11589,6 +11602,11 @@ public class PackageManagerService extends IPackageManager.Stub
}
if (copyRet >= 0) {
+ // Shared libraries that have native libs must be multi-architecture
+ if (pkg.isLibrary()) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Shared library with native libs must be multiarch");
+ }
pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
} else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && cpuAbiOverride != null) {
pkg.applicationInfo.primaryCpuAbi = cpuAbiOverride;
@@ -18143,8 +18161,9 @@ public class PackageManagerService extends IPackageManager.Stub
try {
String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ?
args.abiOverride : pkg.cpuAbiOverride);
+ final boolean extractNativeLibs = !pkg.isLibrary();
derivePackageAbi(pkg, new File(pkg.codePath), abiOverride,
- true /*extractLibs*/, mAppLib32InstallDir);
+ extractNativeLibs, mAppLib32InstallDir);
} catch (PackageManagerException pme) {
Slog.e(TAG, "Error deriving application ABI", pme);
res.setError(INSTALL_FAILED_INTERNAL_ERROR, "Error deriving application ABI");
@@ -20013,7 +20032,7 @@ public class PackageManagerService extends IPackageManager.Stub
// Queue up an async operation since the package deletion may take a little while.
mHandler.post(new Runnable() {
public void run() {
- final PackageSetting ps = (PackageSetting) pkg.mExtras;
+ final PackageSetting ps = pkg == null ? null : (PackageSetting) pkg.mExtras;
boolean doClearData = true;
if (ps != null) {
final boolean targetIsInstantApp =
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index a032844a81b7..89dbc2a1c1c4 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -23,6 +23,7 @@ import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.AppOpsManager.OP_TOAST_WINDOW;
+import static android.content.Context.CONTEXT_RESTRICTED;
import static android.content.Context.DISPLAY_SERVICE;
import static android.content.Context.WINDOW_SERVICE;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
@@ -2823,7 +2824,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (theme != context.getThemeResId() || labelRes != 0) {
try {
- context = context.createPackageContext(packageName, 0);
+ context = context.createPackageContext(packageName, CONTEXT_RESTRICTED);
context.setTheme(theme);
} catch (PackageManager.NameNotFoundException e) {
// Ignore
@@ -7713,6 +7714,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE:
return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
+ case HapticFeedbackConstants.TEXT_HANDLE_MOVE:
+ return VibrationEffect.get(VibrationEffect.EFFECT_TICK);
default:
return null;
}
diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java
index 4a1297f8af71..8335243d590f 100644
--- a/services/core/java/com/android/server/vr/Vr2dDisplay.java
+++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java
@@ -266,6 +266,7 @@ class Vr2dDisplay {
}
int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
+ flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
mVirtualDisplay = mDisplayManager.createVirtualDisplay(null /* projection */,
DISPLAY_NAME, mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi,
null /* surface */, flags, null /* callback */, null /* handler */,
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index fe7494728ac3..5f34c6067997 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -614,8 +614,8 @@ public class AppWindowContainerController
return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
} else if (taskSwitch && allowTaskSnapshot) {
return snapshot == null ? STARTING_WINDOW_TYPE_NONE
- : snapshotFillsWidth(snapshot) || fromRecents ? STARTING_WINDOW_TYPE_SNAPSHOT
- : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ : snapshotOrientationSameAsDisplay(snapshot) || fromRecents
+ ? STARTING_WINDOW_TYPE_SNAPSHOT : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
} else {
return STARTING_WINDOW_TYPE_NONE;
}
@@ -640,7 +640,7 @@ public class AppWindowContainerController
return true;
}
- private boolean snapshotFillsWidth(TaskSnapshot snapshot) {
+ private boolean snapshotOrientationSameAsDisplay(TaskSnapshot snapshot) {
if (snapshot == null) {
return false;
}
@@ -655,7 +655,9 @@ public class AppWindowContainerController
mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
stableInsets);
displayBounds.inset(stableInsets);
- return rect.width() >= displayBounds.width();
+ final boolean snapshotInLandscape = rect.width() >= rect.height();
+ final boolean displayInLandscape = displayBounds.width() >= displayBounds.height();
+ return snapshotInLandscape == displayInLandscape;
}
public void removeStartingWindow() {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fbe6f94ddc3b..c98d60dcad93 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1217,7 +1217,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
(displayInfo.isHdr()
? Configuration.COLOR_MODE_HDR_YES
: Configuration.COLOR_MODE_HDR_NO)
- | (displayInfo.isWideColorGamut()
+ | (displayInfo.isWideColorGamut() && mService.hasWideColorGamutSupport()
? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES
: Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 091e1cba43a2..22b0f5bcdf07 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
@@ -37,6 +38,7 @@ import android.os.Parcel;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.Trace;
import android.os.UserHandle;
import android.util.MergedConfiguration;
import android.util.Slog;
@@ -85,6 +87,7 @@ public class Session extends IWindowSession.Stub
private boolean mClientDead = false;
private float mLastReportedAnimatorScale;
private String mPackageName;
+ private String mRelayoutTag;
public Session(WindowManagerService service, IWindowSessionCallback callback,
IInputMethodClient client, IInputContext inputContext) {
@@ -224,10 +227,12 @@ public class Session extends IWindowSession.Stub
MergedConfiguration mergedConfiguration, Surface outSurface) {
if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
+ Binder.getCallingPid());
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
int res = mService.relayoutWindow(this, window, seq, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
outStableInsets, outsets, outBackdropFrame, mergedConfiguration, outSurface);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
+ Binder.getCallingPid());
return res;
@@ -575,6 +580,7 @@ public class Session extends IWindowSession.Stub
void windowAddedLocked(String packageName) {
mPackageName = packageName;
+ mRelayoutTag = "relayoutWindow: " + mPackageName;
if (mSurfaceSession == null) {
if (WindowManagerService.localLOGV) Slog.v(
TAG_WM, "First window added to " + this + ", creating SurfaceSession");
@@ -698,6 +704,7 @@ public class Session extends IWindowSession.Stub
pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces);
pw.print(" mClientDead="); pw.print(mClientDead);
pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
+ pw.print(prefix); pw.print("mPackageName="); pw.println(mPackageName);
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f86534b03da8..a95a0cf9808c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -30,6 +30,7 @@ import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import static android.os.Process.myPid;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.os.UserHandle.USER_NULL;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -131,6 +132,8 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
+import android.hardware.configstore.V1_0.ISurfaceFlingerConfigs;
+import android.hardware.configstore.V1_0.OptionalBool;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.InputManager;
@@ -715,6 +718,9 @@ public class WindowManagerService extends IWindowManager.Stub
final DisplayManager mDisplayManager;
private final Display[] mDisplays;
+ // Indicates whether this device supports wide color gamut rendering
+ private boolean mHasWideColorGamutSupport;
+
// Who is holding the screen on.
private Session mHoldingScreenOn;
private PowerManager.WakeLock mHoldingScreenWakeLock;
@@ -887,11 +893,16 @@ public class WindowManagerService extends IWindowManager.Stub
}
void openSurfaceTransaction() {
- synchronized (mWindowMap) {
- if (mRoot.mSurfaceTraceEnabled) {
- mRoot.mRemoteEventTrace.openSurfaceTransaction();
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
+ synchronized (mWindowMap) {
+ if (mRoot.mSurfaceTraceEnabled) {
+ mRoot.mRemoteEventTrace.openSurfaceTransaction();
+ }
+ SurfaceControl.openTransaction();
}
- SurfaceControl.openTransaction();
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
@@ -907,16 +918,21 @@ public class WindowManagerService extends IWindowManager.Stub
* blocks and we call it repeatedly, like we do for animations.
*/
void closeSurfaceTransaction(boolean withLockHeld) {
- synchronized (mWindowMap) {
- if (mRoot.mSurfaceTraceEnabled) {
- mRoot.mRemoteEventTrace.closeSurfaceTransaction();
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
+ synchronized (mWindowMap) {
+ if (mRoot.mSurfaceTraceEnabled) {
+ mRoot.mRemoteEventTrace.closeSurfaceTransaction();
+ }
+ if (withLockHeld) {
+ SurfaceControl.closeTransaction();
+ }
}
- if (withLockHeld) {
+ if (!withLockHeld) {
SurfaceControl.closeTransaction();
}
- }
- if (!withLockHeld) {
- SurfaceControl.closeTransaction();
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
@@ -1991,6 +2007,8 @@ public class WindowManagerService extends IWindowManager.Stub
(win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
|| !win.mAppToken.isClientHidden())) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
+
// We are about to create a surface, but we didn't run a layout yet. So better run
// a layout now that we already know the right size, as a resize call will make the
// surface transaction blocking until next vsync and slow us down.
@@ -2002,6 +2020,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
result = win.relayoutVisibleWindow(mergedConfiguration, result, attrChanges,
oldVisibility);
+
try {
result = createSurfaceControl(outSurface, result, win, winAnimator);
} catch (Exception e) {
@@ -2021,7 +2040,10 @@ public class WindowManagerService extends IWindowManager.Stub
imMayMove = true;
}
win.adjustStartingWindowFlags();
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} else {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_2");
+
winAnimator.mEnterAnimationPending = false;
winAnimator.mEnteringAnimation = false;
final boolean usingSavedSurfaceBeforeVisible =
@@ -2056,18 +2078,22 @@ public class WindowManagerService extends IWindowManager.Stub
// We already told the client to go invisible, but the message may not be
// handled yet, or it might want to draw a last frame. If we already have a
// surface, let the client use that, but don't create new surface at this point.
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface");
winAnimator.mSurfaceController.getSurface(outSurface);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} else {
if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
try {
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
+ win.mAttrs.getTitle());
outSurface.release();
} finally {
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
+
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
if (focusMayChange) {
@@ -2104,8 +2130,11 @@ public class WindowManagerService extends IWindowManager.Stub
}
win.setDisplayLayoutNeeded();
- win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
+ win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
+ "relayoutWindow: updateOrientationFromAppTokens");
configChanged = updateOrientationFromAppTokensLocked(false, displayId);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
// We may be deferring layout passes at the moment, but since the client is interested
// in the new out values right now we need to force a layout.
@@ -2158,7 +2187,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (configChanged) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: sendNewConfiguration");
sendNewConfiguration(displayId);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
Binder.restoreCallingIdentity(origId);
return result;
@@ -2219,8 +2250,14 @@ public class WindowManagerService extends IWindowManager.Stub
if (!win.mHasSurface) {
result |= RELAYOUT_RES_SURFACE_CHANGED;
}
- WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked(
- win.mAttrs.type, win.mOwnerUid);
+
+ WindowSurfaceController surfaceController;
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
+ surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ }
if (surfaceController != null) {
surfaceController.getSurface(outSurface);
if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " OUT SURFACE " + outSurface + ": copied");
@@ -2230,6 +2267,7 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.w(TAG_WM, "Failed to create surface control for " + win);
outSurface.release();
}
+
return result;
}
@@ -2276,7 +2314,7 @@ public class WindowManagerService extends IWindowManager.Stub
// frozen, there is no reason to animate and it can cause strange
// artifacts when we unfreeze the display if some different animation
// is running.
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WM#applyAnimationLocked");
if (okToDisplay()) {
final DisplayContent displayContent = atoken.getTask().getDisplayContent();
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
@@ -2332,7 +2370,7 @@ public class WindowManagerService extends IWindowManager.Stub
} else {
atoken.mAppAnimator.clearAnimation();
}
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return atoken.mAppAnimator.animation != null;
}
@@ -2910,9 +2948,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
public void setKeyguardGoingAway(boolean keyguardGoingAway) {
- synchronized (mWindowMap) {
- mKeyguardGoingAway = keyguardGoingAway;
- }
+// TODO: Use of this can be removed. Revert ag/I8369723d6a77f2c602f1ef080371fa7cd9ee094e
+// synchronized (mWindowMap) {
+// mKeyguardGoingAway = keyguardGoingAway;
+// }
}
// -------------------------------------------------------------
@@ -3040,6 +3079,10 @@ public class WindowManagerService extends IWindowManager.Stub
return mPolicy.isKeyguardLocked();
}
+ public boolean isKeyguardShowingAndNotOccluded() {
+ return mPolicy.isKeyguardShowingAndNotOccluded();
+ }
+
@Override
public boolean isKeyguardSecure() {
int userId = UserHandle.getCallingUserId();
@@ -3415,7 +3458,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (!mBootAnimationStopped) {
// Do this one time.
- Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
+ Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
try {
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
if (surfaceFlinger != null) {
@@ -3438,7 +3481,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
- Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
+ Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
mDisplayEnabled = true;
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
@@ -3669,12 +3712,12 @@ public class WindowManagerService extends IWindowManager.Stub
throw new SecurityException("Requires READ_FRAME_BUFFER permission");
}
try {
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
return screenshotApplications(null /* appToken */, DEFAULT_DISPLAY, -1 /* width */,
-1 /* height */, true /* includeFullDisplay */, 1f /* frameScale */,
Bitmap.Config.ARGB_8888, true /* wallpaperOnly */, false /* includeDecor */);
} finally {
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
@@ -3860,6 +3903,8 @@ public class WindowManagerService extends IWindowManager.Stub
+ " alwaysSendConfiguration=" + alwaysSendConfiguration
+ " forceRelayout=" + forceRelayout);
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation");
+
long origId = Binder.clearCallingIdentity();
try {
@@ -3868,20 +3913,28 @@ public class WindowManagerService extends IWindowManager.Stub
final int displayId;
synchronized (mWindowMap) {
final DisplayContent displayContent = getDefaultDisplayContentLocked();
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");
rotationChanged = displayContent.updateRotationUnchecked(
false /* inTransaction */);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (!rotationChanged || forceRelayout) {
displayContent.setLayoutNeeded();
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
+ "updateRotation: performSurfacePlacement");
mWindowPlacerLocked.performSurfacePlacement();
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
displayId = displayContent.getDisplayId();
}
if (rotationChanged || alwaysSendConfiguration) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: sendNewConfiguration");
sendNewConfiguration(displayId);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
} finally {
Binder.restoreCallingIdentity(origId);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
@@ -4722,6 +4775,20 @@ public class WindowManagerService extends IWindowManager.Stub
public void systemReady() {
mPolicy.systemReady();
mTaskSnapshotController.systemReady();
+ mHasWideColorGamutSupport = queryWideColorGamutSupport();
+ }
+
+ private static boolean queryWideColorGamutSupport() {
+ try {
+ ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService();
+ OptionalBool hasWideColor = surfaceFlinger.hasWideColorDisplay();
+ if (hasWideColor != null) {
+ return hasWideColor.value;
+ }
+ } catch (RemoteException e) {
+ // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store
+ }
+ return false;
}
// -------------------------------------------------------------
@@ -5832,7 +5899,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
WindowState newFocus = mRoot.computeFocusedWindow();
if (mCurrentFocus != newFocus) {
- Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmUpdateFocus");
// This check makes sure that we don't already have the focus
// change message pending.
mH.removeMessages(H.REPORT_FOCUS_CHANGE);
@@ -5908,7 +5975,7 @@ public class WindowManagerService extends IWindowManager.Stub
// other apps' UI.
displayContent.scheduleToastWindowsTimeoutIfNeededLocked(oldFocus, newFocus);
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
return true;
}
return false;
@@ -7291,6 +7358,11 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
+ public boolean isKeyguardShowingAndNotOccluded() {
+ return WindowManagerService.this.isKeyguardShowingAndNotOccluded();
+ }
+
+ @Override
public void showGlobalActions() {
WindowManagerService.this.showGlobalActions();
}
@@ -7512,4 +7584,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
}
+
+ boolean hasWideColorGamutSupport() {
+ return mHasWideColorGamutSupport;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index edbdf8bc5ed9..27927e6c0693 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
@@ -33,6 +34,7 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
import android.os.Debug;
+import android.os.Trace;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -101,8 +103,10 @@ class WindowSurfaceController {
mSurfaceControl = new SurfaceTrace(
s, name, w, h, format, flags, windowType, ownerUid);
} else {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
mSurfaceControl = new SurfaceControl(
s, name, w, h, format, flags, windowType, ownerUid);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
if (mService.mRoot.mSurfaceTraceEnabled) {
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index c722629a28f4..86c5e9927617 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -157,8 +157,10 @@ static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring
static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
std::lock_guard<std::mutex> lock(gPowerHalMutex);
if (getPowerHal()) {
- String8 err("Excessive delay in setInteractive(%s) while turning screen %s");
- ALOGD_IF_SLOW(20, String8::format(err, enable ? "true" : "false", enable ? "on" : "off"));
+ String8 err = String8::format(
+ "Excessive delay in setInteractive(%s) while turning screen %s",
+ enable ? "true" : "false", enable ? "on" : "off");
+ ALOGD_IF_SLOW(20, err);
Return<void> ret = gPowerHal->setInteractive(enable);
processReturn(ret, "setInteractive");
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 136d335cf473..8cac6e051e6b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -43,6 +43,7 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
+import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
@@ -1691,9 +1692,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mContext.getSystemService(PowerManager.class).reboot(reason);
}
- void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force)
- throws IOException {
- RecoverySystem.rebootWipeUserData(mContext, shutdown, reason, force);
+ void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force,
+ boolean wipeEuicc) throws IOException {
+ RecoverySystem.rebootWipeUserData(mContext, shutdown, reason, force, wipeEuicc);
}
boolean systemPropertiesGetBoolean(String key, boolean def) {
@@ -5302,7 +5303,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason) {
+ private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason, boolean wipeEuicc) {
wtfIfInLock();
if (wipeExtRequested) {
@@ -5312,7 +5313,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
try {
mInjector.recoverySystemRebootWipeUserData(
- /*shutdown=*/ false, reason, /*force=*/ true);
+ /*shutdown=*/ false, reason, /*force=*/ true, /*wipeEuicc=*/ wipeEuicc);
} catch (IOException | SecurityException e) {
Slog.w(LOG_TAG, "Failed requesting data wipe", e);
}
@@ -5389,7 +5390,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// removes that user (but still clears FRP...)
if (userId == UserHandle.USER_SYSTEM) {
forceWipeDeviceNoLock(/*wipeExtRequested=*/ (flags & WIPE_EXTERNAL_STORAGE) != 0,
- reason);
+ reason, /*wipeEuicc=*/ (flags & WIPE_EUICC) != 0);
} else {
forceWipeUser(userId);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
index 70c7e586d3fe..608635491849 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
@@ -25,8 +25,8 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
-import android.util.Log;
import android.util.LongSparseArray;
+import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -60,16 +60,21 @@ final class NetworkLoggingHandler extends Handler {
/** Delay after which older batches get discarded after a retrieval. */
private static final long RETRIEVED_BATCH_DISCARD_DELAY_MS = 5 * 60 * 1000; // 5m
+ /** Do not call into mDpm with locks held */
private final DevicePolicyManagerService mDpm;
private final AlarmManager mAlarmManager;
private final OnAlarmListener mBatchTimeoutAlarmListener = new OnAlarmListener() {
@Override
public void onAlarm() {
- Log.d(TAG, "Received a batch finalization timeout alarm, finalizing "
+ Slog.d(TAG, "Received a batch finalization timeout alarm, finalizing "
+ mNetworkEvents.size() + " pending events.");
+ Bundle notificationExtras = null;
synchronized (NetworkLoggingHandler.this) {
- finalizeBatchAndNotifyDeviceOwnerLocked();
+ notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked();
+ }
+ if (notificationExtras != null) {
+ notifyDeviceOwner(notificationExtras);
}
}
};
@@ -110,17 +115,21 @@ final class NetworkLoggingHandler extends Handler {
case LOG_NETWORK_EVENT_MSG: {
final NetworkEvent networkEvent = msg.getData().getParcelable(NETWORK_EVENT_KEY);
if (networkEvent != null) {
+ Bundle notificationExtras = null;
synchronized (NetworkLoggingHandler.this) {
mNetworkEvents.add(networkEvent);
if (mNetworkEvents.size() >= MAX_EVENTS_PER_BATCH) {
- finalizeBatchAndNotifyDeviceOwnerLocked();
+ notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked();
}
}
+ if (notificationExtras != null) {
+ notifyDeviceOwner(notificationExtras);
+ }
}
break;
}
default: {
- Log.d(TAG, "NetworkLoggingHandler received an unknown of message.");
+ Slog.d(TAG, "NetworkLoggingHandler received an unknown of message.");
break;
}
}
@@ -133,40 +142,48 @@ final class NetworkLoggingHandler extends Handler {
mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, when,
BATCH_FINALIZATION_TIMEOUT_ALARM_INTERVAL_MS, NETWORK_LOGGING_TIMEOUT_ALARM_TAG,
mBatchTimeoutAlarmListener, this);
- Log.d(TAG, "Scheduled a new batch finalization alarm " + BATCH_FINALIZATION_TIMEOUT_MS
+ Slog.d(TAG, "Scheduled a new batch finalization alarm " + BATCH_FINALIZATION_TIMEOUT_MS
+ "ms from now.");
}
synchronized void pause() {
- Log.d(TAG, "Paused network logging");
+ Slog.d(TAG, "Paused network logging");
mPaused = true;
}
- synchronized void resume() {
- if (!mPaused) {
- Log.d(TAG, "Attempted to resume network logging, but logging is not paused.");
- return;
- }
+ void resume() {
+ Bundle notificationExtras = null;
+ synchronized (this) {
+ if (!mPaused) {
+ Slog.d(TAG, "Attempted to resume network logging, but logging is not paused.");
+ return;
+ }
- Log.d(TAG, "Resumed network logging. Current batch=" + mCurrentBatchToken
- + ", LastRetrievedBatch=" + mLastRetrievedBatchToken);
- mPaused = false;
+ Slog.d(TAG, "Resumed network logging. Current batch=" + mCurrentBatchToken
+ + ", LastRetrievedBatch=" + mLastRetrievedBatchToken);
+ mPaused = false;
- // If there is a batch ready that the device owner hasn't been notified about, do it now.
- if (mBatches.size() > 0 && mLastRetrievedBatchToken != mCurrentBatchToken) {
- scheduleBatchFinalization();
- notifyDeviceOwnerLocked();
+ // If there is a batch ready that the device owner hasn't been notified about, do it now.
+ if (mBatches.size() > 0 && mLastRetrievedBatchToken != mCurrentBatchToken) {
+ scheduleBatchFinalization();
+ notificationExtras = buildDeviceOwnerMessageLocked();
+ }
+ }
+ if (notificationExtras != null) {
+ notifyDeviceOwner(notificationExtras);
}
}
synchronized void discardLogs() {
mBatches.clear();
mNetworkEvents = new ArrayList<>();
- Log.d(TAG, "Discarded all network logs");
+ Slog.d(TAG, "Discarded all network logs");
}
@GuardedBy("this")
- private void finalizeBatchAndNotifyDeviceOwnerLocked() {
+ /** @returns extras if a message should be sent to the device owner */
+ private Bundle finalizeBatchAndBuildDeviceOwnerMessageLocked() {
+ Bundle notificationExtras = null;
if (mNetworkEvents.size() > 0) {
// Finalize the batch and start a new one from scratch.
if (mBatches.size() >= MAX_BATCHES) {
@@ -177,27 +194,39 @@ final class NetworkLoggingHandler extends Handler {
mBatches.append(mCurrentBatchToken, mNetworkEvents);
mNetworkEvents = new ArrayList<>();
if (!mPaused) {
- notifyDeviceOwnerLocked();
+ notificationExtras = buildDeviceOwnerMessageLocked();
}
} else {
// Don't notify the DO, since there are no events; DPC can still retrieve
// the last full batch if not paused.
- Log.d(TAG, "Was about to finalize the batch, but there were no events to send to"
+ Slog.d(TAG, "Was about to finalize the batch, but there were no events to send to"
+ " the DPC, the batchToken of last available batch: " + mCurrentBatchToken);
}
// Regardless of whether the batch was non-empty schedule a new finalization after timeout.
scheduleBatchFinalization();
+ return notificationExtras;
}
- /** Sends a notification to the DO. Should only be called when there is a batch available. */
@GuardedBy("this")
- private void notifyDeviceOwnerLocked() {
+ /** Build extras notification to the DO. Should only be called when there
+ is a batch available. */
+ private Bundle buildDeviceOwnerMessageLocked() {
final Bundle extras = new Bundle();
final int lastBatchSize = mBatches.valueAt(mBatches.size() - 1).size();
extras.putLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, mCurrentBatchToken);
extras.putInt(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT, lastBatchSize);
- Log.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: "
- + mCurrentBatchToken);
+ return extras;
+ }
+
+ /** Sends a notification to the DO. Should not hold locks as DevicePolicyManagerService may
+ call into NetworkLoggingHandler. */
+ private void notifyDeviceOwner(Bundle extras) {
+ Slog.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: "
+ + extras.getLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, -1));
+ if (Thread.holdsLock(this)) {
+ Slog.wtfStack(TAG, "Shouldn't be called with NetworkLoggingHandler lock held");
+ return;
+ }
mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE, extras);
}
diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java
index 75df892b30b1..5770c5079d94 100644
--- a/services/print/java/com/android/server/print/UserState.java
+++ b/services/print/java/com/android/server/print/UserState.java
@@ -159,10 +159,12 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks,
readInstalledPrintServicesLocked();
upgradePersistentStateIfNeeded();
readDisabledPrintServicesLocked();
+ }
- // Some print services might have gotten installed before the User State came up
- prunePrintServices();
+ // Some print services might have gotten installed before the User State came up
+ prunePrintServices();
+ synchronized (mLock) {
onConfigurationChangedLocked();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java b/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java
index 07280bc881d8..62b0ca805c1b 100644
--- a/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/ObserverNodeTest.java
@@ -21,16 +21,22 @@ import java.util.ArrayList;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
+import android.os.Looper;
import android.os.UserHandle;
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.content.ContentService.ObserverCall;
import com.android.server.content.ContentService.ObserverNode;
+/**
+ * bit FrameworksServicesTests:com.android.server.content.ObserverNodeTest
+ */
+@SmallTest
public class ObserverNodeTest extends AndroidTestCase {
static class TestObserver extends ContentObserver {
public TestObserver() {
- super(new Handler());
+ super(new Handler(Looper.getMainLooper()));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java b/services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java
index be6861c43699..d093e7961b22 100644
--- a/services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/SyncManagerTest.java
@@ -1,9 +1,32 @@
+/*
+ * Copyright (C) 2017 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.content;
import android.os.Bundle;
+import android.test.suitebuilder.annotation.SmallTest;
import junit.framework.TestCase;
+/**
+ * Tests for SyncManager.
+ *
+ * bit FrameworksServicesTests:com.android.server.content.SyncManagerTest
+ */
+@SmallTest
public class SyncManagerTest extends TestCase {
final String KEY_1 = "key_1";
@@ -61,4 +84,42 @@ public class SyncManagerTest extends TestCase {
assertFalse("Extras considered equal when they are different.",
SyncManager.syncExtrasEquals(b1, b2, false /* don't care about system extras */));
}
+
+ public void testFormatDurationHMS() {
+ checkFormatDurationHMS("0s", 0, 0, 0, 0);
+ checkFormatDurationHMS("1s", 0, 0, 0, 1);
+ checkFormatDurationHMS("9s", 0, 0, 0, 9);
+ checkFormatDurationHMS("10s", 0, 0, 0, 10);
+ checkFormatDurationHMS("59s", 0, 0, 0, 59);
+ checkFormatDurationHMS("1m00s", 0, 0, 1, 0);
+ checkFormatDurationHMS("1m01s", 0, 0, 1, 1);
+ checkFormatDurationHMS("1m09s", 0, 0, 1, 9);
+ checkFormatDurationHMS("1m10s", 0, 0, 1, 10);
+ checkFormatDurationHMS("1m59s", 0, 0, 1, 59);
+ checkFormatDurationHMS("1h00m00s", 0, 1, 0, 0);
+ checkFormatDurationHMS("1h00m01s", 0, 1, 0, 1);
+ checkFormatDurationHMS("1h01m01s", 0, 1, 1, 1);
+ checkFormatDurationHMS("1h09m10s", 0, 1, 9, 10);
+ checkFormatDurationHMS("1h10m59s", 0, 1, 10, 59);
+ checkFormatDurationHMS("1h59m00s", 0, 1, 59, 0);
+
+ checkFormatDurationHMS("1d00h00m00s", 1, 0, 0, 0);
+ checkFormatDurationHMS("1d00h00m00s", 1, 0, 0, 0);
+ checkFormatDurationHMS("1d01h00m00s", 1, 1, 0, 0);
+ checkFormatDurationHMS("1d09h00m00s", 1, 9, 0, 0);
+ checkFormatDurationHMS("1d10h00m00s", 1, 10, 0, 0);
+ checkFormatDurationHMS("1d23h00m00s", 1, 23, 0, 0);
+ checkFormatDurationHMS("123d01h00m00s", 123, 1, 0, 0);
+
+ final StringBuilder sb = new StringBuilder();
+ assertEquals("-1m01s", SyncManager.formatDurationHMS(sb, -61000L).toString());
+ }
+
+ private void checkFormatDurationHMS(String expected,
+ int d, int h, int m, int s) {
+ final long time = (d * 24 * 3600) + (h * 3600) + (m * 60) + s;
+
+ final StringBuilder sb = new StringBuilder();
+ assertEquals(expected, SyncManager.formatDurationHMS(sb, time * 1000).toString());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java b/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
index e45b92a1b486..deaa34ca9f51 100644
--- a/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
@@ -17,24 +17,17 @@
package com.android.server.content;
import android.accounts.Account;
-import android.content.ContentResolver;
-import android.content.Context;
import android.os.Bundle;
import android.os.PersistableBundle;
-import android.os.SystemClock;
-import android.provider.Settings;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
/**
- * You can run those tests with:
+ * Test for SyncOperation.
*
- * adb shell am instrument
- * -e debug false
- * -w
- * -e class android.content.SyncOperationTest com.android.frameworks.coretests/android.test.InstrumentationTestRunner
+ * bit FrameworksServicesTests:com.android.server.content.SyncOperationTest
*/
-
+@SmallTest
public class SyncOperationTest extends AndroidTestCase {
Account mDummy;
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java b/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
index 91c0de64cb82..85de1f1c3e86 100644
--- a/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
@@ -22,7 +22,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
-import android.content.PeriodicSync;
import android.content.res.Resources;
import android.os.Bundle;
import android.test.AndroidTestCase;
@@ -33,14 +32,18 @@ import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.server.content.SyncStorageEngine.EndPoint;
-
import com.android.internal.os.AtomicFile;
import java.io.File;
import java.io.FileOutputStream;
-import java.util.List;
+/**
+ * Test for SyncStorageEngine.
+ *
+ * bit FrameworksServicesTests:com.android.server.content.SyncStorageEngineTest
+ *
+ * TODO Broken. Fix it. b/62485315
+ */
public class SyncStorageEngineTest extends AndroidTestCase {
protected Account account1;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index a33153e07496..54717157d069 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -269,9 +269,9 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
}
@Override
- void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force)
- throws IOException {
- services.recoverySystem.rebootWipeUserData(shutdown, reason, force);
+ void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force,
+ boolean wipeEuicc) throws IOException {
+ services.recoverySystem.rebootWipeUserData(shutdown, reason, force, wipeEuicc);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 6393b0b4018e..c58b733b8b54 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -17,6 +17,7 @@ package com.android.server.devicepolicy;
import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS;
import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL;
+import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
import static android.os.UserManagerInternal.CAMERA_DISABLED_GLOBALLY;
import static android.os.UserManagerInternal.CAMERA_DISABLED_LOCALLY;
import static android.os.UserManagerInternal.CAMERA_NOT_DISABLED;
@@ -3451,7 +3452,21 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.wipeData(0);
verify(getServices().recoverySystem).rebootWipeUserData(
- /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true));
+ /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
+ /*wipeEuicc=*/ eq(false));
+ }
+
+ public void testWipeEuiccDataEnabled() throws Exception {
+ setDeviceOwner();
+ when(getServices().userManager.getUserRestrictionSource(
+ UserManager.DISALLOW_FACTORY_RESET,
+ UserHandle.SYSTEM))
+ .thenReturn(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER);
+
+ dpm.wipeData(WIPE_EUICC);
+ verify(getServices().recoverySystem).rebootWipeUserData(
+ /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
+ /*wipeEuicc=*/ eq(true));
}
public void testWipeDataDeviceOwnerDisallowed() throws Exception {
@@ -3549,7 +3564,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// The device should be wiped even if DISALLOW_FACTORY_RESET is enabled, because both the
// user restriction and the policy were set by the DO.
verify(getServices().recoverySystem).rebootWipeUserData(
- /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true));
+ /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
+ /*wipeEuicc=*/ eq(false));
}
public void testMaximumFailedPasswordAttemptsReachedDeviceOwnerDisallowed() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index ed8de0517631..8121bcf16c60 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -314,8 +314,8 @@ public class MockSystemServices {
}
public static class RecoverySystemForMock {
- public void rebootWipeUserData(
- boolean shutdown, String reason, boolean force) throws IOException {
+ public void rebootWipeUserData(boolean shutdown, String reason, boolean force,
+ boolean wipeEuicc) throws IOException {
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
index c399a5de46dd..e3ce17bcd2d8 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -29,6 +29,7 @@ import android.view.SurfaceControl;
import android.view.WindowManagerInternal;
import com.android.server.LocalServices;
+import com.android.server.display.DisplayDeviceInfo;
import com.android.server.display.DisplayManagerService.SyncRoot;
import com.android.server.display.VirtualDisplayAdapter.SurfaceControlDisplayFactory;
@@ -115,4 +116,30 @@ public class DisplayManagerServiceTest extends AndroidTestCase {
assertEquals(uniqueIdPrefix + uniqueId, dv.uniqueId);
assertEquals(displayId, dv.displayId);
}
+
+ public void testCreateVirtualDisplayRotatesWithContent() throws Exception {
+ // This is effectively the DisplayManager service published to ServiceManager.
+ DisplayManagerService.BinderService bs = mDisplayManager.new BinderService();
+
+ String uniqueId = "uniqueId --- Rotates With Content Test";
+ int width = 600;
+ int height = 800;
+ int dpi = 320;
+ int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
+
+ when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
+ int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */,
+ null /* projection */, "com.android.frameworks.servicestests",
+ "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
+ uniqueId);
+
+ mDisplayManager.performTraversalInTransactionFromWindowManagerInternal();
+
+ // flush the handler
+ mHandler.runWithScissors(() -> {}, 0 /* now */);
+
+ DisplayDeviceInfo ddi = mDisplayManager.getDisplayDeviceInfoInternal(displayId);
+ assertNotNull(ddi);
+ assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 33e1a1652b22..689c8f7e6e01 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -206,7 +206,8 @@ public class JobStoreTest extends AndroidTestCase {
invalidLateRuntimeElapsedMillis - TWO_HOURS; // Early is (late - period).
final JobStatus js = new JobStatus(b.build(), SOME_UID, "somePackage",
0 /* sourceUserId */, "someTag",
- invalidEarlyRuntimeElapsedMillis, invalidLateRuntimeElapsedMillis);
+ invalidEarlyRuntimeElapsedMillis, invalidLateRuntimeElapsedMillis,
+ 0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */);
mTaskStoreUnderTest.add(js);
Thread.sleep(IO_WAIT);
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a6bfbad8e053..e8e06808e189 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -189,6 +189,19 @@ public final class Call {
*/
public static final String EVENT_HANDOVER_COMPLETE =
"android.telecom.event.HANDOVER_COMPLETE";
+
+ /**
+ * Call event sent from Telecom to the handover destination {@link ConnectionService} via
+ * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
+ * source connection has disconnected. The {@link Bundle} parameter for the call event will be
+ * {@code null}.
+ * <p>
+ * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
+ * @hide
+ */
+ public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
+ "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
+
/**
* Call event sent from Telecom to the handover {@link ConnectionService} via
* {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 11770fb06c95..f22a6327c80f 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -320,7 +320,8 @@ public class EuiccManager {
return;
}
try {
- mController.getDownloadableSubscriptionMetadata(subscription, callbackIntent);
+ mController.getDownloadableSubscriptionMetadata(
+ subscription, mContext.getOpPackageName(), callbackIntent);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -349,7 +350,8 @@ public class EuiccManager {
return;
}
try {
- mController.getDefaultDownloadableSubscriptionList(callbackIntent);
+ mController.getDefaultDownloadableSubscriptionList(
+ mContext.getOpPackageName(), callbackIntent);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index c3010296d9c0..e7b22bdfadcc 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -697,4 +697,11 @@ public class ImsConfig {
ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
}
}
+
+ /**
+ * @return true if the binder connection is alive, false otherwise.
+ */
+ public boolean isBinderAlive() {
+ return miConfig.asBinder().isBinderAlive();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/NetworkScanResult.java b/telephony/java/com/android/internal/telephony/NetworkScanResult.java
index 2f0fdba85b1e..95f39d7f878a 100644
--- a/telephony/java/com/android/internal/telephony/NetworkScanResult.java
+++ b/telephony/java/com/android/internal/telephony/NetworkScanResult.java
@@ -21,6 +21,7 @@ import android.os.Parcelable;
import android.telephony.CellInfo;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Defines the incremental network scan result.
@@ -34,10 +35,10 @@ import java.util.List;
public final class NetworkScanResult implements Parcelable {
// Contains only part of the scan result and more are coming.
- public static final int SCAN_STATUS_PARTIAL = 0;
+ public static final int SCAN_STATUS_PARTIAL = 1;
// Contains the last part of the scan result and the scan is now complete.
- public static final int SCAN_STATUS_COMPLETE = 1;
+ public static final int SCAN_STATUS_COMPLETE = 2;
// The status of the scan, only valid when scanError = SUCCESS.
public int scanStatus;
@@ -108,7 +109,7 @@ public final class NetworkScanResult implements Parcelable {
public int hashCode () {
return ((scanStatus * 31)
+ (scanError * 23)
- + (networkInfos.hashCode() * 37));
+ + (Objects.hashCode(networkInfos) * 37));
}
public static final Creator<NetworkScanResult> CREATOR =
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 725b89bcf351..fa43631cee9e 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -26,8 +26,9 @@ import android.telephony.euicc.EuiccInfo;
interface IEuiccController {
oneway void continueOperation(in Intent resolutionIntent, in Bundle resolutionExtras);
oneway void getDownloadableSubscriptionMetadata(in DownloadableSubscription subscription,
- in PendingIntent callbackIntent);
- oneway void getDefaultDownloadableSubscriptionList(in PendingIntent callbackIntent);
+ String callingPackage, in PendingIntent callbackIntent);
+ oneway void getDefaultDownloadableSubscriptionList(
+ String callingPackage, in PendingIntent callbackIntent);
String getEid();
oneway void downloadSubscription(in DownloadableSubscription subscription,
boolean switchAfterDownload, String callingPackage, in PendingIntent callbackIntent);
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
index f28d1263d13a..0fabc2ff6b86 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
@@ -30,10 +30,6 @@ public class SmsCbConstants {
/** Private constructor for utility class. */
private SmsCbConstants() { }
- /** Channel 50 required by Brazil. ID 0~999 is allocated by GSMA */
- public static final int MESSAGE_ID_GSMA_ALLOCATED_CHANNEL_50
- = 0x0032;
-
/** Start of PWS Message Identifier range (includes ETWS and CMAS). */
public static final int MESSAGE_ID_PWS_FIRST_IDENTIFIER
= 0x1100; // 4352
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index 582506a367d0..d4098d94ba6c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -278,6 +278,10 @@ public class SmsMessage extends SmsMessageBase {
scAddress, destinationAddress, mtiByte,
statusReportRequested, ret);
+ // Skip encoding pdu if error occurs when create pdu head and the error will be handled
+ // properly later on encodedMessage sanity check.
+ if (bo == null) return ret;
+
// User Data (and length)
byte[] userData;
try {
@@ -420,6 +424,9 @@ public class SmsMessage extends SmsMessageBase {
scAddress, destinationAddress, (byte) 0x41, // MTI = SMS-SUBMIT,
// TP-UDHI = true
statusReportRequested, ret);
+ // Skip encoding pdu if error occurs when create pdu head and the error will be handled
+ // properly later on encodedMessage sanity check.
+ if (bo == null) return ret;
// TP-Data-Coding-Scheme
// No class, 8 bit data
@@ -451,7 +458,7 @@ public class SmsMessage extends SmsMessageBase {
* @param destinationAddress the address of the destination for the message
* @param mtiByte
* @param ret <code>SubmitPdu</code> containing the encoded SC
- * address, if applicable, and the encoded message
+ * address, if applicable, and the encoded message. Returns null on encode error.
*/
private static ByteArrayOutputStream getSubmitPduHead(
String scAddress, String destinationAddress, byte mtiByte,
@@ -482,6 +489,9 @@ public class SmsMessage extends SmsMessageBase {
daBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(destinationAddress);
+ // return empty pduHead for invalid destination address
+ if (daBytes == null) return null;
+
// destination address length in BCD digits, ignoring TON byte and pad
// TODO Should be better.
bo.write((daBytes.length - 1) * 2
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index ebad81cdda34..5e5ba462cfca 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -816,6 +816,12 @@ public class MockContext extends Context {
/** {@hide} */
@Override
+ public boolean canLoadUnsafeResources() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@hide} */
+ @Override
public IBinder getActivityToken() {
throw new UnsupportedOperationException();
}
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 2137e557cd0c..ab874ce2cc50 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -261,32 +261,51 @@ public class TetheringTest {
mIntents.remove(bcast);
}
- @Test
- public void failingLocalOnlyHotspotLegacyApBroadcast() throws Exception {
+ public void failingLocalOnlyHotspotLegacyApBroadcast(
+ boolean emulateInterfaceStatusChanged) throws Exception {
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
// hotspot mode is to be started.
- mTethering.interfaceStatusChanged(mTestIfname, true);
+ if (emulateInterfaceStatusChanged) {
+ mTethering.interfaceStatusChanged(mTestIfname, true);
+ }
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
mLooper.dispatchAll();
- verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
- verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
+ // If, and only if, Tethering received an interface status changed
+ // then it creates a TetherInterfaceStateMachine and sends out a
+ // broadcast indicating that the interface is "available".
+ if (emulateInterfaceStatusChanged) {
+ verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
+ verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
+ }
verifyNoMoreInteractions(mConnectivityManager);
verifyNoMoreInteractions(mNMService);
verifyNoMoreInteractions(mWifiManager);
}
@Test
- public void workingLocalOnlyHotspotEnrichedApBroadcast() throws Exception {
+ public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
+ failingLocalOnlyHotspotLegacyApBroadcast(true);
+ }
+
+ @Test
+ public void failingLocalOnlyHotspotLegacyApBroadcastSansIfaceStatusChanged() throws Exception {
+ failingLocalOnlyHotspotLegacyApBroadcast(false);
+ }
+
+ public void workingLocalOnlyHotspotEnrichedApBroadcast(
+ boolean emulateInterfaceStatusChanged) throws Exception {
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
// hotspot mode is to be started.
- mTethering.interfaceStatusChanged(mTestIfname, true);
+ if (emulateInterfaceStatusChanged) {
+ mTethering.interfaceStatusChanged(mTestIfname, true);
+ }
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_LOCAL_ONLY);
mLooper.dispatchAll();
@@ -331,6 +350,17 @@ public class TetheringTest {
}
@Test
+ public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
+ workingLocalOnlyHotspotEnrichedApBroadcast(true);
+ }
+
+ @Test
+ public void workingLocalOnlyHotspotEnrichedApBroadcastSansIfaceChanged() throws Exception {
+ workingLocalOnlyHotspotEnrichedApBroadcast(false);
+ }
+
+ // TODO: Test with and without interfaceStatusChanged().
+ @Test
public void failingWifiTetheringLegacyApBroadcast() throws Exception {
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
@@ -357,6 +387,7 @@ public class TetheringTest {
verifyNoMoreInteractions(mWifiManager);
}
+ // TODO: Test with and without interfaceStatusChanged().
@Test
public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
@@ -437,6 +468,7 @@ public class TetheringTest {
mTethering.getLastTetherError(mTestIfname));
}
+ // TODO: Test with and without interfaceStatusChanged().
@Test
public void failureEnablingIpForwarding() throws Exception {
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 14284d661744..1ddaf66d2274 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -62,7 +62,8 @@ public class OffloadControllerTest {
@Mock private OffloadHardwareInterface mHardware;
@Mock private ApplicationInfo mApplicationInfo;
@Mock private Context mContext;
- final ArgumentCaptor<ArrayList> mStringArrayCaptor = ArgumentCaptor.forClass(ArrayList.class);
+ private final ArgumentCaptor<ArrayList> mStringArrayCaptor =
+ ArgumentCaptor.forClass(ArrayList.class);
private MockContentResolver mContentResolver;
@Before public void setUp() throws Exception {
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
index ce419a5070d2..db5373ac34b2 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
@@ -16,6 +16,8 @@
package com.android.server.connectivity.tethering;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
@@ -40,17 +42,23 @@ import static com.android.server.connectivity.tethering.IControlsTethering.STATE
import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
+import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.RouteInfo;
import android.net.util.SharedLog;
import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
+
+import java.net.Inet4Address;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -69,6 +77,8 @@ public class TetherInterfaceStateMachineTest {
@Mock private SharedLog mSharedLog;
private final TestLooper mLooper = new TestLooper();
+ private final ArgumentCaptor<LinkProperties> mLinkPropertiesCaptor =
+ ArgumentCaptor.forClass(LinkProperties.class);
private TetherInterfaceStateMachine mTestedSm;
private void initStateMachine(int interfaceType) throws Exception {
@@ -77,7 +87,7 @@ public class TetherInterfaceStateMachineTest {
mNMService, mStatsService, mTetherHelper);
mTestedSm.start();
// Starting the state machine always puts us in a consistent state and notifies
- // the test of the world that we've changed from an unknown to available state.
+ // the rest of the world that we've changed from an unknown to available state.
mLooper.dispatchAll();
reset(mNMService, mStatsService, mTetherHelper);
when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
@@ -181,7 +191,8 @@ public class TetherInterfaceStateMachineTest {
inOrder.verify(mTetherHelper).updateInterfaceState(
mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
inOrder.verify(mTetherHelper).updateLinkProperties(
- eq(mTestedSm), any(LinkProperties.class));
+ eq(mTestedSm), mLinkPropertiesCaptor.capture());
+ assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
}
@@ -281,7 +292,8 @@ public class TetherInterfaceStateMachineTest {
usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
- eq(mTestedSm), any(LinkProperties.class));
+ eq(mTestedSm), mLinkPropertiesCaptor.capture());
+ assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
}
}
@@ -298,7 +310,8 @@ public class TetherInterfaceStateMachineTest {
usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
mTestedSm, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
- eq(mTestedSm), any(LinkProperties.class));
+ eq(mTestedSm), mLinkPropertiesCaptor.capture());
+ assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
}
@Test
@@ -313,7 +326,8 @@ public class TetherInterfaceStateMachineTest {
usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
mTestedSm, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
- eq(mTestedSm), any(LinkProperties.class));
+ eq(mTestedSm), mLinkPropertiesCaptor.capture());
+ assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
}
@Test
@@ -360,4 +374,28 @@ public class TetherInterfaceStateMachineTest {
upstreamIface);
mLooper.dispatchAll();
}
+
+ private void assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp) {
+ // Find the first IPv4 LinkAddress.
+ LinkAddress addr4 = null;
+ for (LinkAddress addr : lp.getLinkAddresses()) {
+ if (!(addr.getAddress() instanceof Inet4Address)) continue;
+ addr4 = addr;
+ break;
+ }
+ assertTrue("missing IPv4 address", addr4 != null);
+
+ // Assert the presence of the associated directly connected route.
+ final RouteInfo directlyConnected = new RouteInfo(addr4, null, lp.getInterfaceName());
+ assertTrue("missing directly connected route: '" + directlyConnected.toString() + "'",
+ lp.getRoutes().contains(directlyConnected));
+ }
+
+ private void assertNoAddressesNorRoutes(LinkProperties lp) {
+ assertTrue(lp.getLinkAddresses().isEmpty());
+ assertTrue(lp.getRoutes().isEmpty());
+ // We also check that interface name is non-empty, because we should
+ // never see an empty interface name in any LinkProperties update.
+ assertFalse(TextUtils.isEmpty(lp.getInterfaceName()));
+ }
}
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
index 27be135cb796..b68f203d869f 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -16,6 +16,7 @@
package com.android.server.connectivity.tethering;
+import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
@@ -38,6 +39,8 @@ import android.telephony.TelephonyManager;
import com.android.internal.util.test.BroadcastInterceptingContext;
+import java.util.Iterator;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -134,4 +137,61 @@ public class TetheringConfigurationTest {
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
}
+
+ @Test
+ public void testNoDefinedUpstreamTypesAddsEthernet() {
+ when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+ .thenReturn(new int[]{});
+ mHasTelephonyManager = false;
+ when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
+
+ final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator();
+ assertTrue(upstreamIterator.hasNext());
+ assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue());
+ // The following is because the code always adds some kind of mobile
+ // upstream, be it DUN or, in this case where we use DUN_UNSPECIFIED,
+ // both vanilla and hipri mobile types.
+ assertTrue(upstreamIterator.hasNext());
+ assertEquals(TYPE_MOBILE, upstreamIterator.next().intValue());
+ assertTrue(upstreamIterator.hasNext());
+ assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue());
+ assertFalse(upstreamIterator.hasNext());
+ }
+
+ @Test
+ public void testDefinedUpstreamTypesSansEthernetAddsEthernet() {
+ when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+ .thenReturn(new int[]{TYPE_WIFI, TYPE_MOBILE_HIPRI});
+ mHasTelephonyManager = false;
+ when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
+
+ final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator();
+ assertTrue(upstreamIterator.hasNext());
+ assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue());
+ assertTrue(upstreamIterator.hasNext());
+ assertEquals(TYPE_WIFI, upstreamIterator.next().intValue());
+ assertTrue(upstreamIterator.hasNext());
+ assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue());
+ assertFalse(upstreamIterator.hasNext());
+ }
+
+ @Test
+ public void testDefinedUpstreamTypesWithEthernetDoesNotAddEthernet() {
+ when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
+ .thenReturn(new int[]{TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_HIPRI});
+ mHasTelephonyManager = false;
+ when(mTelephonyManager.getTetherApnRequired()).thenReturn(DUN_UNSPECIFIED);
+
+ final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
+ final Iterator<Integer> upstreamIterator = cfg.preferredUpstreamIfaceTypes.iterator();
+ assertTrue(upstreamIterator.hasNext());
+ assertEquals(TYPE_WIFI, upstreamIterator.next().intValue());
+ assertTrue(upstreamIterator.hasNext());
+ assertEquals(TYPE_ETHERNET, upstreamIterator.next().intValue());
+ assertTrue(upstreamIterator.hasNext());
+ assertEquals(TYPE_MOBILE_HIPRI, upstreamIterator.next().intValue());
+ assertFalse(upstreamIterator.hasNext());
+ }
}
diff --git a/tests/testables/src/android/testing/BaseFragmentTest.java b/tests/testables/src/android/testing/BaseFragmentTest.java
index 5cedbdffed35..5fa065a9135a 100644
--- a/tests/testables/src/android/testing/BaseFragmentTest.java
+++ b/tests/testables/src/android/testing/BaseFragmentTest.java
@@ -50,7 +50,7 @@ public abstract class BaseFragmentTest {
private static final int VIEW_ID = 42;
private final Class<? extends Fragment> mCls;
private Handler mHandler;
- private FrameLayout mView;
+ protected FrameLayout mView;
protected FragmentController mFragments;
protected Fragment mFragment;
@@ -61,9 +61,13 @@ public abstract class BaseFragmentTest {
mCls = cls;
}
+ protected void createRootView() {
+ mView = new FrameLayout(mContext);
+ }
+
@Before
public void setupFragment() throws Exception {
- mView = new FrameLayout(mContext);
+ createRootView();
mView.setId(VIEW_ID);
assertNotNull("BaseFragmentTest must be tagged with @RunWithLooper",
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 91fc2f7ce773..e7fbe4fe55fc 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -891,9 +891,13 @@ public class WifiConfiguration implements Parcelable {
*/
public static final int DISABLED_DUE_TO_USER_SWITCH = 11;
/**
+ * This network is disabled due to wrong password
+ */
+ public static final int DISABLED_BY_WRONG_PASSWORD = 12;
+ /**
* This Maximum disable reason value
*/
- public static final int NETWORK_SELECTION_DISABLED_MAX = 12;
+ public static final int NETWORK_SELECTION_DISABLED_MAX = 13;
/**
* Quality network selection disable reason String (for debug purpose)
@@ -910,7 +914,8 @@ public class WifiConfiguration implements Parcelable {
"NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS",
"NETWORK_SELECTION_DISABLED_NO_INTERNET",
"NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER",
- "NETWORK_SELECTION_DISABLED_BY_USER_SWITCH"
+ "NETWORK_SELECTION_DISABLED_BY_USER_SWITCH",
+ "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD"
};
/**
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 18f30f834bc1..bb3af3cd1687 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -156,9 +156,20 @@ public class WifiEnterpriseConfig implements Parcelable {
}
- /** Copy constructor */
- public WifiEnterpriseConfig(WifiEnterpriseConfig source) {
+ /**
+ * Copy over the contents of the source WifiEnterpriseConfig object over to this object.
+ *
+ * @param source Source WifiEnterpriseConfig object.
+ * @param ignoreMaskedPassword Set to true to ignore masked password field, false otherwise.
+ * @param mask if |ignoreMaskedPassword| is set, check if the incoming password field is set
+ * to this value.
+ */
+ private void copyFrom(WifiEnterpriseConfig source, boolean ignoreMaskedPassword, String mask) {
for (String key : source.mFields.keySet()) {
+ if (ignoreMaskedPassword && key.equals(PASSWORD_KEY)
+ && TextUtils.equals(source.mFields.get(key), mask)) {
+ continue;
+ }
mFields.put(key, source.mFields.get(key));
}
if (source.mCaCerts != null) {
@@ -178,6 +189,29 @@ public class WifiEnterpriseConfig implements Parcelable {
mPhase2Method = source.mPhase2Method;
}
+ /**
+ * Copy constructor.
+ * This copies over all the fields verbatim (does not ignore masked password fields).
+ *
+ * @param source Source WifiEnterpriseConfig object.
+ */
+ public WifiEnterpriseConfig(WifiEnterpriseConfig source) {
+ copyFrom(source, false, "");
+ }
+
+ /**
+ * Copy fields from the provided external WifiEnterpriseConfig.
+ * This is needed to handle the WifiEnterpriseConfig objects which were sent by apps with the
+ * password field masked.
+ *
+ * @param externalConfig External WifiEnterpriseConfig object.
+ * @param mask String mask to compare against.
+ * @hide
+ */
+ public void copyFromExternal(WifiEnterpriseConfig externalConfig, String mask) {
+ copyFrom(externalConfig, true, convertToQuotedString(mask));
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index ec8d91baf1ba..613c529fa616 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -676,16 +676,28 @@ public class WifiManager {
@SystemApi
public static final int CHANGE_REASON_CONFIG_CHANGE = 2;
/**
- * An access point scan has completed, and results are available from the supplicant.
- * Call {@link #getScanResults()} to obtain the results. {@link #EXTRA_RESULTS_UPDATED}
- * indicates if the scan was completed successfully.
+ * An access point scan has completed, and results are available.
+ * Call {@link #getScanResults()} to obtain the results.
+ * The broadcast intent may contain an extra field with the key {@link #EXTRA_RESULTS_UPDATED}
+ * and a {@code boolean} value indicating if the scan was successful.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS";
/**
- * Lookup key for a {@code boolean} representing the result of previous {@link #startScan}
- * operation, reported with {@link #SCAN_RESULTS_AVAILABLE_ACTION}.
+ * Lookup key for a {@code boolean} extra in intent {@link #SCAN_RESULTS_AVAILABLE_ACTION}
+ * representing if the scan was successful or not.
+ * Scans may fail for multiple reasons, these may include:
+ * <ol>
+ * <li>A non-privileged app requested too many scans in a certain period of time.
+ * This may lead to additional scan request rejections via "scan throttling".
+ * See
+ * <a href="https://developer.android.com/preview/features/background-location-limits.html">
+ * here</a> for details.
+ * </li>
+ * <li>The device is idle and scanning is disabled.</li>
+ * <li>Wifi hardware reported a scan failure.</li>
+ * </ol>
* @return true scan was successful, results are updated
* @return false scan was not successful, results haven't been updated since previous scan
*/
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index f596eef1bf21..0d4359e878d2 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -291,7 +291,6 @@ public class WifiP2pManager {
"android.net.wifi.p2p.CALLING_PACKAGE";
IWifiP2pManager mService;
- private final Map<Channel, Binder> mBinders = new HashMap<>();
private static final int BASE = Protocol.BASE_WIFI_P2P_MANAGER;
@@ -670,11 +669,12 @@ public class WifiP2pManager {
* by doing a call on {@link #initialize}
*/
public static class Channel {
- Channel(Context context, Looper looper, ChannelListener l) {
+ Channel(Context context, Looper looper, ChannelListener l, Binder binder) {
mAsyncChannel = new AsyncChannel();
mHandler = new P2pHandler(looper);
mChannelListener = l;
mContext = context;
+ mBinder = binder;
}
private final static int INVALID_LISTENER_KEY = 0;
private ChannelListener mChannelListener;
@@ -686,6 +686,8 @@ public class WifiP2pManager {
private final Object mListenerMapLock = new Object();
private int mListenerKey = 0;
+ /* package */ final Binder mBinder;
+
private AsyncChannel mAsyncChannel;
private P2pHandler mHandler;
Context mContext;
@@ -892,8 +894,8 @@ public class WifiP2pManager {
*/
public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
Binder binder = new Binder();
- Channel channel = initalizeChannel(srcContext, srcLooper, listener, getMessenger(binder));
- mBinders.put(channel, binder);
+ Channel channel = initalizeChannel(srcContext, srcLooper, listener, getMessenger(binder),
+ binder);
return channel;
}
@@ -903,14 +905,15 @@ public class WifiP2pManager {
*/
public Channel initializeInternal(Context srcContext, Looper srcLooper,
ChannelListener listener) {
- return initalizeChannel(srcContext, srcLooper, listener, getP2pStateMachineMessenger());
+ return initalizeChannel(srcContext, srcLooper, listener, getP2pStateMachineMessenger(),
+ null);
}
private Channel initalizeChannel(Context srcContext, Looper srcLooper, ChannelListener listener,
- Messenger messenger) {
+ Messenger messenger, Binder binder) {
if (messenger == null) return null;
- Channel c = new Channel(srcContext, srcLooper, listener);
+ Channel c = new Channel(srcContext, srcLooper, listener, binder);
if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
== AsyncChannel.STATUS_SUCCESSFUL) {
return c;
@@ -1428,8 +1431,9 @@ public class WifiP2pManager {
*/
public void close(Channel c) {
try {
- mService.close(mBinders.get(c));
- mBinders.remove(c);
+ if (c != null) {
+ mService.close(c.mBinder);
+ }
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
index d0aedbad03b5..1a7dd132389e 100644
--- a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -20,6 +20,7 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -316,15 +317,37 @@ public class WifiEnterpriseConfigTest {
assertEquals("\"auth=AKA'\"", getSupplicantPhase2Method());
}
- /** Verfies that the copy constructor preseves the inner method information. */
+ /**
+ * Verifies that the copy constructor preseves both the masked password and inner method
+ * information.
+ */
@Test
public void copyConstructor() {
WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setPassword("*");
enterpriseConfig.setEapMethod(Eap.TTLS);
enterpriseConfig.setPhase2Method(Phase2.GTC);
mEnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
assertEquals("TTLS", getSupplicantEapMethod());
assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
+ assertEquals("*", mEnterpriseConfig.getPassword());
+ }
+
+ /**
+ * Verifies that the copy from external ignores masked passwords and preserves the
+ * inner method information.
+ */
+ @Test
+ public void copyFromExternal() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setPassword("*");
+ enterpriseConfig.setEapMethod(Eap.TTLS);
+ enterpriseConfig.setPhase2Method(Phase2.GTC);
+ mEnterpriseConfig = new WifiEnterpriseConfig();
+ mEnterpriseConfig.copyFromExternal(enterpriseConfig, "*");
+ assertEquals("TTLS", getSupplicantEapMethod());
+ assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method());
+ assertNotEquals("*", mEnterpriseConfig.getPassword());
}
/** Verfies that parceling a WifiEnterpriseConfig preseves method information. */